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
_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to