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.
Details
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Skipped - Unit
Tests Skipped
Event Timeline
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? | |
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 |
Yes, but I do not see anything that can be done with it, it is the issue for user.
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. | |
| 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. | |
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.
| libexec/rtld-elf/rtld.c | ||
|---|---|---|
| 3637 | Just return (__sys_openat(...))? | |