[lsb-discuss] Best-effort dynamic linking -- take 1

Alexey Khoroshilov khoroshilov at ispras.ru
Mon Jul 21 02:17:02 PDT 2008


Jeff Licquia wrote:
> Alexey Khoroshilov wrote:
>> If we do not consider the "/proc" topic, the main problem of this 
>> implementation is that it does not actually implement re-exec of an 
>> application with the lsblinker when required. It just call 
>> execv("/proc/self/exe",argv) that leads to cyclic execution of 
>> _lsb_init().
>
> Good catch.  I had done a "simple" implementation, intending to make 
> it work better later, and forgot.
>
> This should have been caught in my testing, though; I thought I had 
> tested the case where the new linker was needed.  So it looks like 
> I'll have to figure out why my test didn't busy-loop forever.
>
>> There are also some other issues, which are pointed below.
>
>> char *argv[128];                           // COMMENT: 1024/128 
>> limitations have to be fixed in production version.
>
> Do you think it's sufficient to simply declare argv to be 1024 members 
> long?
Using any fixed size buffers may lead to undesirable consequences.
At least we should check if an overflow happens and warn users explicitly.

>>     S_ISLNK(lsblinker.st_mode))            // WRONG: If lsblinker is 
>> a symbolic link, proceed with the nativelinker.
>>                                            // SHOULD BE(?): If 
>> lsblinker is not a symbolic link, re-exec.
>>                                            // (May be we also should 
>> support a hard link to nativelinker?)
>
> I (attempt to) support that with the code following.
>
>> if (lsblinker.st_ino == nativelinker.st_ino) // WRONG: lstat() sets 
>> st_ino of symlink itself instead of the file that it refers to.
>>   return;
>
> Correct, except that we've already determined that the LSB linker is 
> not a symlink; if it was, we would have exited above.  If the file is 
> not a symlink, stat() and lstat() act identically.
Yes, the thing that was not clear here is why we should exit (i.e. 
proceed with the nativelinker) if the LSB linker is a symlink.

>> pos = cmdbuf;
>> while (*pos && argc < 128) {                 // WRONG: 1. Invalid 
>> assumption that cmdbuf initialized by zeros.
>>   argv[argc++] = pos;                        //        2. Buffer 
>> overflow.
>>   while (*(++pos)) ;
>>   pos++;
>> }
>> argv[argc] = NULL;
>
> Hmm, not sure about this.  The null bytes are contained in 
> /proc/self/cmdline, so they should be pulled in with the read().
After reading the last argument "while (*pos && argc < 128)" 
dereferences the pos element, which is the next after the last written 
by read(). And it is zero only if cmdbuf was initialized by zeros. Also 
if size of "/proc/self/cmdline" is 1024 it leads to reading the memory 
out of the buffer.

> I do see a potential for problems if /proc/self/cmdline is larger than 
> our buffer.  Your fix looks good for that, though it also has the side 
> effect of using malloc().  Maybe we can do something better with the 
> static buffer.
>
>> exit(255);                                   // COMMENT: May be it is 
>> better to try to proceed with the nativelinker.
>
> Yup, entirely possible.  What do others think?
I am not sure which solution is preferable.
>
>> I have fixed some issues (see the file attached). The remaining 
>> questions are:
>> - What is the best way to re-exec an application with the lsblinker?
>
> A few options:
>
>  - Read the exe symlink, instead of just exec-ing it.
>
>  - Rely on argv[0] and do our own PATH searching, and trust that 
> nothing has screwed up the PATH.
>
>> - What is content of "/proc/self/cmdline" in non-POSIX locales?
>
> The "spec" in the kernel documentation is terrible.  My guess would be 
> that whatever got passed to the exec syscall as the argv array gets 
> stuffed into /proc/self/cmdline without locale translation.  But we 
> should probably look at the kernel code to make sure.
Yes, I suspect that our work with zero bytes may be incorrect in these 
cases.

>> - Is it ok to use malloc?
>
> There may be issues with it, since we may be running before the heap 
> manager initialization code.  I'd like to avoid it if at all possible.
>
As far as I know (not sure) the heap manager initialization code is 
executed during // the first invocation of malloc-family functions. At 
least, malloc can be called by any C++ constructor, which can be 
executed at the similar stage.
>> - Should we support symlink only or hardlinks too?
>
> Yup.
>
> Also:
>
>  - Should best-effort be the default for LSB 4 builds?
I would say yes. Of course, if we finish the implementation.

-- 
Alexey Khoroshilov

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.linux-foundation.org/pipermail/lsb-discuss/attachments/20080721/e5cc2104/attachment.htm 


More information about the lsb-discuss mailing list