2016-02-16 1:22 GMT+03:00 Philip Guenther <[email protected]>:
> On Sun, 14 Feb 2016, Philip Guenther wrote:
>> On Sun, 14 Feb 2016, Nicolas Bedos wrote:
> ...
>> > >Fix:
>> > I did some digging and it seems pax gets stuck in a loop after
>> > calling node_creat (file_subs.c) to create /tmp/foo/bar:
>> ...
>> > The first argument of chk_path seems to end with '/' because of the
>> > cpio format. I could not reproduce the problem with the ustar
>> > format. I did not look any further since I think it is chk_path
>> > which is at fault here.
>>
>> It doesn't occur when reading ustar format input because a filename with a
>> trailing slash is already specially handled there to provide compat with
>> the old tar format where directories are stored with a trailing slash.
>
> ...and since pax's tar format code only trims a single trailing slash, it
> will loop even in that case if you add more than one trailing slash.
>
> Indeed, if you add more than one trailing slash in general then it'll
> still hang despite your patch: to fix it the code needs to be able to
> detect when its reached an arbitrary number of trailing slashes.
>
> So, I think a diff like this is in order. This also lets it skip extra
> slashes in the middle of the path and avoid the checks that would be
> duplicated.
>
> Look good to everyone?
>
>
> --- file_subs.c 19 Mar 2015 05:14:24 -0000 1.47
> +++ file_subs.c 15 Feb 2016 09:35:57 -0000
> @@ -597,6 +597,7 @@ int
> chk_path(char *name, uid_t st_uid, gid_t st_gid)
> {
> char *spt = name;
> + char *next;
> struct stat sb;
> int retval = -1;
>
> @@ -613,6 +614,17 @@ chk_path(char *name, uid_t st_uid, gid_t
Hello, Philip.
I think we should change "if" to "while" in this function, too...
After that, okay zhuk@.
--
WBR,
Vadim Zhukov
Index: file_subs.c
===================================================================
RCS file: /cvs/src/bin/pax/file_subs.c,v
retrieving revision 1.47
diff -u -p -r1.47 file_subs.c
--- file_subs.c 19 Mar 2015 05:14:24 -0000 1.47
+++ file_subs.c 15 Feb 2016 23:24:40 -0000
@@ -597,13 +597,14 @@ int
chk_path(char *name, uid_t st_uid, gid_t st_gid)
{
char *spt = name;
+ char *next;
struct stat sb;
int retval = -1;
/*
* watch out for paths with nodes stored directly in / (e.g. /bozo)
*/
- if (*spt == '/')
+ while (*spt == '/')
++spt;
for (;;) {
@@ -613,6 +614,17 @@ chk_path(char *name, uid_t st_uid, gid_t
spt = strchr(spt, '/');
if (spt == NULL)
break;
+
+ /*
+ * skip over duplicate slashes; stop if there're only
+ * trailing slashes left
+ */
+ next = spt + 1;
+ while (*next == '/')
+ next++;
+ if (*next == '\0')
+ break;
+
*spt = '\0';
/*
@@ -625,7 +637,8 @@ chk_path(char *name, uid_t st_uid, gid_t
* required (do an access()).
*/
if (lstat(name, &sb) == 0) {
- *(spt++) = '/';
+ *spt = '/';
+ spt = next;
continue;
}
@@ -659,7 +672,8 @@ chk_path(char *name, uid_t st_uid, gid_t
set_pmode(name, ((sb.st_mode & FILEBITS) | S_IRWXU));
add_dir(name, &sb, 1);
}
- *(spt++) = '/';
+ *spt = '/';
+ spt = next;
continue;
}
return(retval);