Paul Fox wrote:
> denys wrote:
>  > 
>  > Thus I propose introducing xmalloc_readlink_recursive()
>  > which does not suffer from those two problems,
>  > and using it here (and elsewhere: insmod, syslogd -
>  > grep for xmalloc_readlink).
>
> well, i've written a new version, but it doesn't do what you
> thought it was going to.  :-)
>
> realpath() fully canonicalizes a path -- it makes it absolute,
> removes "/..", and expands symlinks all along the path.
>
> readlink() (and also xmalloc_readlink()) simply returns the value
> of the named symlink.  (which makes the switch from realpath()
> to xmalloc_readlink() somewhat suspicious, by the way.)
>   
I think that should be no problem. The path will eventually point to a 
real file, and as long as the new temporary file is created in the same 
directory, it should be possible to rename it later.

Also, I don't see why insmod should need the realpath of the object. I 
thought the basename of the object file is used as the module name, but 
I have also seen few cases where the module name was not the file name, 
so that seems to be only a convention and not mandatory.
> i've written xmalloc_readlink_follow(char *path) which iteratively
> does textual expansion of path, expanding symlinks at the tail end
> of path.  no other canonicalization is done, and the result is not
> necessarily absolute.  this is the minimum needed for my "allow
> /etc/passwd to be a symlink" change, and it's probably useful for
> most of the other current uses of xmalloc_readlink().
>   
I noticed that you test against MAXSYMLINKS only in the case of relative 
symlinks. I consider this inconsistent.
In the case of /etc/passwd, the administrator probably can be trusted to 
not create a loop. But suppose you have an absolute symlink /etc/passwd 
-> /etc/passwd. The function would loop forever, while a stat on 
/etc/passwd would fail.with ELOOP. With a relative symlink /etc/passwd 
-> passwd the loop would be detected.

Another question is what the function should do if the target of the 
link does not exist. xmalloc_readlink will always return the target 
name, whether it exists or not. I don't know whether this behavior would 
be useful for xmalloc_readlink_follow or not.

Regards
Ralf Friedl
> /*
>  * this routine is not the same as realpath(), which canonicalizes
>  * the given path completely.  this routine only follows trailing
>  * symlinks until a real file is reached, and returns its name. 
>  * intermediate symlinks are not expanded.  as above, a malloced
>  * char* is returned, which must be freed.
>  */
> char *xmalloc_readlink_follow(const char *path)
> {
>       char *buf = NULL, *lpc, *linkpath;
>       int bufsize;
>       smallint looping = 0;
>
>       buf = strdup(path);
>       bufsize = strlen(path) + 1;
>
>       while(1) {
>               linkpath = xmalloc_readlink(buf);
>               if (!linkpath) {
>                       if (errno == EINVAL) /* not a symlink */
>                               return buf;
>                       free(buf);
>                       return NULL;
>               } 
>
>               if (*linkpath == '/') {
>                       free(buf);
>                       buf = linkpath;
>                       bufsize = strlen(linkpath) + 1;
>               } else {
>                       bufsize += strlen(linkpath);
>                       if (looping++ > MAXSYMLINKS) {
>                               free(linkpath);
>                               free(buf);
>                               return NULL;
>                       }
>                       buf = xrealloc(buf, bufsize);
>                       lpc = bb_get_last_path_component_strip(buf);
>                       strcpy(lpc, linkpath);
>                       free(linkpath);
>               }
>       }
> }
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to