On Mon, 13 Jun 2022, Theo de Raadt wrote:
> Scott Cheloha <[email protected]> wrote:
> > > Am I wrong that kbind is never called twice in the same address space?
> >
> > Isn't this exactly what happened the last time we tried this?
>
> Tried what?  kbind has never been NOLOCK.

Scott's referring to rev 1.237 of kern_fork.c, where we tried to require
the first use of kbind be before __tfork(2) was called.  This blew up
because there's at least two ways to legitimately call pthread_create(3)
before doing your first lazy binding:

 1) build with -znow, then dlopen() something not linked with -znow after
    calling pthread_create()

 2) pass address of pthread_create() to another function which calls
    through the pointer, no special link options required (just need to
    split up the &pthread_create and *funcptr enough that the compiler
    won't optimize to a direct call)


I've thought about how to possibly force a lazy resolution and haven't
thought up anything that wasn't unmaintainable, and probably
unimplementable.


So, what could work reliably?

My first thought would be to have ld.so's _dl_boot() do the equivalent of
        struct __kbind kb = {
                .kb_addr = &kbind_syscall_in_dl_bind;
                .kb_size = 0;
        };
        kbind(&kb, sizeof kb, pcookie)

...after teaching the kernel to accept such a first call to kbind and set
pr->ps_kbind_* from them.  That would permit the reimposing of the "first
kbind can't be after __tfork" restriction; is it indeed enough to permit
the ps_kbind_* members without locks?


Another idea is to discard the cookie restriction and just trust the
calling address to be enough.  I mean, we trust it to be sufficient
for sigreturn and that's perhaps more powerful, no?  If we're fine with
that, then how about giving ld.so a PT_OPENBSD_KBIND segment with the
required address, so the kernel can just set it up at exec time?
Eventually, we could disable kbind if said header wasn't present on the ELF
interpreter.

(In a groteque abuse of the ELF program header, we *could* keep the cookie
by, for example, having the PT_OPENBSD_KBIND p_vaddr/p_memsz identify the
location of the random cookie in ld.so memory and pass the kbind syscall
address via p_paddr.  You are permitted to barf.)


Philip

Reply via email to