Page MenuHomeFreeBSD

rtld: allow dlopen("#<number>/<path>")
AcceptedPublic

Authored by kib on Sun, Mar 29, 11:11 PM.
Tags
None
Referenced Files
F150423392: D56152.diff
Wed, Apr 1, 3:00 AM
Unknown Object (File)
Mon, Mar 30, 12:46 PM
Subscribers

Details

Reviewers
markj
emaste
dim
Summary
When a specially formatted path is passed to dlopen(), of the form
  #number/path
and the number is the valid dirfd file descriptor listed in the
LD_LIBRARY_FDS, interpret it as a relative path name against dirfd
number.

This complements the result returned from dladdr() for such objects
in dli_fname.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

kib requested review of this revision.Sun, Mar 29, 11:11 PM
kib added reviewers: markj, emaste, dim.

Add documentation and test.

Why introduce this special syntax instead of adding a new function fdlopenat(<fd>, <rel path>, <flags>)?

lib/libc/gen/dlopen.3
174
175

If an application is started with LD_LIBRARY_PATH_FDS=42, it may later close fd 42 and then open something else with that fd. Then, dlopen("#42/libfoo.so") will use an fd unrelated to the fd observed by rtld.

This being the case, why must the provided fd number be included in LD_LIBRARY_PATH_FDS?

177

It should be mentioned that this functionality is unavailable to setuid/setgid processes.

libexec/rtld-elf/rtld.c
3633

What's the purpose of specifying O_EMPTY_PATH?

kib marked 4 inline comments as done.Mon, Mar 30, 12:32 PM

Why introduce this special syntax instead of adding a new function fdlopenat(<fd>, <rel path>, <flags>)?

To complement the output from dlinfo(), as I noted in the summary. We record the name of the object opened through LD_LIBRARY_PATH_FDS in this format. I wanted to make it possible to use the info output directly without user code needing to understand the special case.

I do not see a need in fdlopenat() then, user code might do openat() and then fdlopen(), after all.

lib/libc/gen/dlopen.3
175

If an application is started with LD_LIBRARY_PATH_FDS=42, it may later close fd 42 and then open something else with that fd. Then, dlopen("#42/libfoo.so") will use an fd unrelated to the fd observed by rtld.

Yes, but I do not see anything that can be done with it, it is the issue for user.

This being the case, why must the provided fd number be included in LD_LIBRARY_PATH_FDS?

See the description of the motivation in the main response. It adds some consistency: if we recorded the name using LD_LIBRARY_PATH_FDS, then it makes sense to allow such action when dirfd is listed in the env var.

libexec/rtld-elf/rtld.c
3633

So that '#fd/' syntax worked. I do not see why disabling it.

kib marked 2 inline comments as done.

Man page editing.

lib/libc/gen/dlopen.3
178
libexec/rtld-elf/rtld.c
2879–2884

IMO it would be cleaner to test these conditions in try_fds_open(), so you can write

if (name[0] != '#')
    return (-1);
name++;

and avoid all of the name + 1.

3609

strchr() is available.

3633

fdlopen() is available, and dladdr() will never return such a string, but ok.

kib marked 4 inline comments as done.

Move checks into try_fds_open().
Use strchr.
Drop O_EMPTY_PATH.
Do name++ early.
Grammar fix in the man page.

fdlopenat(<fd>, <rel path>, <flags>)

Would it not just be dlopenat? But indeed it could be done with openat + fdlopen.

markj added inline comments.
libexec/rtld-elf/rtld.c
3637

Just return (__sys_openat(...))?

This revision is now accepted and ready to land.Wed, Apr 1, 11:42 AM