lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <8daedc8f-efba-4d2e-9e2a-8954eb4acbc0@t-8ch.de>
Date: Fri, 16 Jan 2026 20:29:03 +0100
From: Thomas Weißschuh <linux@...ssschuh.net>
To: Daniel Palmer <daniel@...ngy.jp>
Cc: Greg Ungerer <gerg@...ux-m68k.org>, w@....eu, dalias@...c.org, 
	linux-m68k@...ts.linux-m68k.org, linux-kernel@...r.kernel.org
Subject: Re: [RFC PATCH] tools/nolibc: HACK!: Add basic self relocation for
 static PIE for m68k nommu FDPIC

Hi Daniel,

On 2026-01-16 21:28:12+0900, Daniel Palmer wrote:
> This is some very quick hacky code to test if this works and get some ideas..
> 
> - I'm messing with m68k nommu. Currently I use FLAT binaries and this is working with nolibc
>   as-is mostly. Sometimes some relocations that elf2flat doesn't like get generated and the
>   resulting FLAT binary doesn't have any relocation information and crashes which isn't good
>   if you don't have an mmu.
> 
> - Since commit 1bde925d2354 ("fs/binfmt_elf_fdpic.c: provide NOMMU loader for regular ELF binaries")
>   the FDPIC loader has apparently been able to load non-FDPIC binaries as long as they are
>   PIE and can be relocated. I have been messing with this thinking that maybe I can stop using
>   FLAT binaries.
> 
> - By default linking with -pie is trying to set ld.so as the interpreter to do the
>   relocation. I don't think I have anything that can do that in my system. I am using uclibc but
>   statically linked. Aside from my programs written with nolibc there is a busybox FLAT that is
>   statically linked to uclibc and nothing else.
> 
>   Eitherway, the plan is not to have any libc and have everything compiled with nolibc. I'm writing
>   a small init, shell etc with nolibc that will replace busybox and not cause constant OOMs.

So far so good.

> - So, I can generate PIE binaries but they can't work because I have no linker to relocate them but
>   apparently static PIE is a thing and with a normal toolchain you'd get a crt that does the relocation
>   before jumping to main().
> 
> - I thought it shouldn't be too hard to add something like that to crt.h in nolibc and then pass
>   --no-dynamic-linker when linking to not set an interpreter.
> 
> - I got it working enough that a static pie "hello, world" loads and runs:
> 
> / # /root/test.elf
> [    9.970000] FDPIC ____ LOAD 23 ____
> [    9.970000] FDPIC Mapped Object [executable]:
> [    9.970000] FDPIC - elfhdr   : 6d8000
> [    9.970000] FDPIC - entry    : 6d83e4
> [    9.970000] FDPIC - PHDR[]   : 6d8034
> [    9.970000] FDPIC - DYNAMIC[]: 6da7b0
> [    9.970000] FDPIC - LOAD[0] : 006d8000-006d87ad [va=0 ms=7ae]
> [    9.970000] FDPIC - LOAD[1] : 006da7b0-006da873 [va=27b0 ms=c4]
> [    9.970000] FDPIC - start_code  6d8000
> [    9.970000] FDPIC - end_code    6d87ae
> [    9.970000] FDPIC - start_data  6da7b0
> [    9.970000] FDPIC - end_data    6da874
> [    9.970000] FDPIC - start_brk   6e0000
> [    9.970000] FDPIC - brk         6e0000
> [    9.970000] FDPIC - start_stack 6fff00
> hello, world!
> [    9.980000] test.elf (23) used greatest stack depth: 5348 bytes left

Nice! Is it sufficient for nolibc-test? If so, can you provide
instructions for that?

> Questions:
> 
> - My use case is weird/niche but maybe there are uses for static pie nolibc binaries?

I think it is a valid usecase to support nommu systems.
Also from a security perspective, pie should be better.
While I would like to defer to the 'uldso' tool from Greg, nolibc
positions itself as usable for single-binary systems. Requiring a
different tool would run a bit counter to that.
In my opinion it depends on the implementation complexity. If we can
have a simple implementation shared by all architectures, why not.

>   - If so what would be a cleaner way of implementing this?

Some comments inline.

> - Right now the base address offset all of the relocations against is hardcoded.
>   Maybe someone knows how I'm meant to get that properly?

That should be getauxval(AT_BASE), I think.

> Signed-off-by: Daniel Palmer <daniel@...ngy.jp>
> ---
>  tools/include/nolibc/crt.h | 56 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 56 insertions(+)
> 
> diff --git a/tools/include/nolibc/crt.h b/tools/include/nolibc/crt.h
> index d9262998dae9..0931915280d8 100644
> --- a/tools/include/nolibc/crt.h
> +++ b/tools/include/nolibc/crt.h
> @@ -10,6 +10,7 @@
>  #ifndef NOLIBC_NO_RUNTIME
>  
>  #include "compiler.h"
> +#include "elf.h"
>  
>  char **environ __attribute__((weak));
>  const unsigned long *_auxv __attribute__((weak));
> @@ -47,6 +48,61 @@ void _start_c(long *sp)
>  	/* initialize stack protector */
>  	__stack_chk_init();
>  
> +#ifdef NOLIBC_STATIC_PIE

It might be possible to detect this automatically based on the
preprocessor symbols __pie__/__PIE__.

> +#define R_68K_RELATIVE	22

These definition should be moved to the UAPI headers.
See my related changes I did for some other architectures:
https://lore.kernel.org/lkml/20250812-vdso-absolute-reloc-v4-1-61a8b615e5ec@linutronix.de/
https://lore.kernel.org/lkml/20250812-vdso-absolute-reloc-v4-2-61a8b615e5ec@linutronix.de/

It means that nolibc would require new UAPI headers for pie support, but
given that pie didn't work before at all, that should be fine.

> +{
> +	void *base = (void *) 0x6d8000; // TODO: how to actually get this?

getauxval(AT_BASE)

> +	unsigned int rela_count = 0;
> +	unsigned int rela_off = 0;
> +	unsigned long dyn_addr;
> +	Elf32_Rela *rela;
> +	Elf32_Addr *addr;
> +	Elf32_Dyn *dyn;
> +	int i;

> +	/* For m68k with the FDPIC loader d5 contains the offset to the DYNAMIC segment */
> +	__asm__ volatile (
> +		"move.l %%d5, %0\n"
> +		: "=r" (dyn_addr)
> +	);

This should go into arch-m68k.h.
Is %d5 guaranteed not to have been clobbered by now?
If not we need to pass it in from the asm __start().

> +	dyn = (Elf32_Dyn *) dyn_addr;
> +
> +	/* Go through the DYNAMIC segment and get the offset to rela and the number of relocations */
> +	for (; dyn->d_tag != DT_NULL; dyn++) {
> +		switch (dyn->d_tag) {
> +		case DT_RELA:
> +			rela_off = dyn->d_un.d_ptr;
> +			break;
> +		case DT_RELACOUNT:
> +			rela_count = dyn->d_un.d_val;
> +			break;
> +		}
> +	}
> +
> +	if (!rela_off || !rela_count)
> +		exit(42); //TODO nonsense error

Maybe __builtin_trap()/__nolibc_trap()?

> +
> +	rela = base + rela_off;
> +
> +	/* Do the relocations, only R_68K_RELATIVE for now */

Are there any more that would need to be supported?
How many are there for other architectures?
(My knowledge here is limited)

> +	for (i = 0; i < rela_count; i++) {
> +		Elf32_Rela *entry = &rela[i];
> +
> +		switch (ELF32_R_TYPE(entry->r_info)) {
> +		case R_68K_RELATIVE:
> +		{
> +			addr = (Elf32_Addr *)(base + entry->r_offset);
> +			*addr = (Elf32_Addr) (base + entry->r_addend);

Can these point into read-only memory?
Do we need to fiddle with mprotect()?

> +		}
> +			break;
> +		default:
> +			exit(43); //TODO nonsense error
> +			break;
> +		}
> +	}
> +}
> +#endif

This whole block should go into a dedicated file/function.

> +
>  	/*
>  	 * sp  :    argc          <-- argument count, required by main()
>  	 * argv:    argv[0]       <-- argument vector, required by main()

All in all, if we can keep the complexity for a shared implementation at
the level of the code above, then I am in favor of implementing this in
nolibc.

Willy, your opinion?


Thomas

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ