Unfortunate dynamic linking for everything

Peter Jeremy peterjeremy at optushome.com.au
Fri Nov 21 21:07:09 PST 2003


On Fri, Nov 21, 2003 at 04:52:00PM -0500, Garance A Drosihn wrote:
>>>Shouldn't that be 'chmod +t /bin/sh' ???
>
>b) I thought that you might want to have this an "admin-only"
>   command, so nefarious users couldn't abuse it on a shared
>   system.

I would make one change to your proposal:  Instead of having the
pre-linked image wired in RAM, I'd allow it to be paged as for an
ordinary process image.  This means the overhead of starting a
pre-linked process would be similar to starting a statically-linked
executable.

Once you remove the "store image in RAM only" requirement, I don't see
that allowing an ordinary user to set the sticky bit would allow any
new attacks.  The user can only set the bit on their own files.  The
address space overhead of holding a pre-linked image is roughly the
same as executing that image so allowing a user to create sticky
executables is roughly the same as allowing the user to create an
additional process running that executable.

>I'm certainly fine with it using "+t".  Now it's just a matter
>of figuring out how to implement it...  :-)

I thought it was obvious so I left it as an exercise for the reader :-).

My guess is that if a pre-linked image didn't exist, imgact_elf()
would run as normal, transferring control to ld-elf.so.  ld-elf.so
would do symbol binding as per normal (probably as if with LD_BIND_NOW
was set) and would then invoke a new save_image() syscall just before
it transferred control to main().  This would trigger the kernel to
save the whole process image as COW.  This image would be associated
back to the original executable using a mechanism similar to that used
for sharing the text segment.  Next time that executable is execve()'d,
imgact_elf() would note that there was a pre-linked image available and
attach to it, rather than re-mapping the executable.  It would pass a
flag to ld-elf.so to inform the latter that it should just start main().

A few rough edges still need to be resolved:
- ld-elf.so runs as the invoking user but the above model has it telling
  the kernel what the process image is - which shouldn't be trusted by a
  different uid.  The easiest solution is to make save_image() a root-
  only syscall so pre-binding only works if the executable has been run
  by root.  An alternative would be to have the process images tied into
  the user's credentials - this would mean more significant changes
  because there's nothing that currently maintains information about
  an executable on a per-uid basis outside the process.
- ld-elf.so environment (eg LD_LIBRARY_PATH, LD_PRELOAD) impact.  This
  gets messy - it is undesirable to totally inhibit pre-linking if
  either is set so maybe ld-elf.so needs to verify that the pre-linked
  image matches the result if the environment is taken into account.
- ld-elf.so needs to make sure that the libraries haven't changed since
  the original image was mapped - to handle (eg) libc.so being replaced.
- There needs to be some way for the VM system to throw away the
  pre-linked images if the system runs low on RAM+swap.

An alternative approach might be to have a dummy 'placeholder' process
which solely exists to hold the pre-linked image.  This process would
be started by invoking the executable with a special "LD_PRELINK_ONLY"
flag.  When the executable was later exec'd, the kernel would fork() the
dummy process giving it the credentials, pid and ppid of the process
being exec'd.

I'm sure deeper thought will reveal problems...

Peter


More information about the freebsd-current mailing list