[Toybox] cpio -d patch...

Rob Landley rob at landley.net
Tue Mar 11 04:53:36 PDT 2014


Trying to tie off the loose ends for a long-overdue release, and  
Isaac's cpio -d patch is half-finished in my tree.

The problem with the original patch is that "mkdir -pm 500  
one/two/three" should work creating a read only "three" under a  
read/write "one/two". If "one" is read only it fails to create "two".  
Thus the original mkpath logic was that the supplied mode only applied  
to the _last_ directory component, and the others just used the umask.  
But the version of the function moved to lib isn't doing that, which  
breaks mkpath.

So I took another stab at this (the patch to break out the mkpath.c  
logic so cpio -d can use it), and got a clean version that creates  
everything _except_ the last directory. (The idea was to avoid passing  
in a mode at all, because the mode only varies for the last directory.)  
Unfortunately, that didn't help because the logic to create _just_ the  
last directory (with the "verbose" option and error checking) was about  
as large as the whole recursive loop it factored out. I.E. genericizing  
this particular way bloats mkdir significantly...

What I _could_ do is is have it mkpath the whole thing with the umode,  
and then chmod the last path after creation. But I hate ever doing  
anything twice in the filesystem because that's where security  
exploitable race conditions come from: letting the directory be world  
writeable for a fraction of a section when it shouldn't have been. So  
if it's going to have certain permissions, it should be atomically  
_created_ with those permissions.

By the way, if you notice those games with 0777&~toys.umask, that's  
because mkdir has TOYFLAG_UMASK in its NEWTOY() flags, which tells  
main() to set the umask to 0 (and save the old umask in toys.umask).  
That way when we create things, we get the permission we actually  
request rather than a filtered subset, allowing things like mkdir -m to  
work properly. I note that toys/pending/cpio.c is _not_ doing that, nor  
is it calling umask(0) itself, meaning it's allowing umask to filter  
the permissions of everything it creates rather than producing output  
with the actual modes recorded in the archive. Is this intentional?

(The kernel's initramfs logic requires you to have a directory creation  
entry before any file using that directory. Files created in  
nonexistent directories are silently ignored. I haven't checked ot see  
what rpm does.)

This is why this one's taken so long: there turn out to be several  
subtly wrong ways to do it...

Rob
 1394538816.0


More information about the Toybox mailing list