[Toybox] rm -rf doesn't chmod high enough

Rob Landley rob at landley.net
Wed Sep 24 21:19:45 PDT 2014


On 09/23/14 10:17, Isaac Dunham wrote:
> On Mon, Sep 22, 2014 at 08:19:21AM -0500, Rob Landley wrote:
>> On 09/20/14 08:22, Felix Janda wrote:
>>> Isaac Dunham wrote:
>>> [..]
>>>> A trickier bug is that rm -r dir will skip dir, saying 
>>>> "rm: dir: is a directory"
>>>> I guess the fix involves rm -r calling rmdir instead of unlink.
>>>
>>> unlinkat() also removes directories when given AT_REMOVEDIR.
>>> The following patch makes rm pass the tests and it still asks
>>> me when I try to remove a readonly dir.
>>>
>>> -Felix
>>>
>>> diff -r 434c4ae19f05 toys/posix/rm.c
>>> --- a/toys/posix/rm.c	Thu Sep 18 18:07:58 2014 -0500
>>> +++ b/toys/posix/rm.c	Sat Sep 20 15:19:09 2014 +0200
>>> @@ -50,7 +50,6 @@
>>>      // Handle chmod 000 directories when -f
>>>      if (faccessat(fd, try->name, R_OK, AT_SYMLINK_NOFOLLOW)) {
>>>        if (toys.optflags & FLAG_f) wfchmodat(fd, try->name, 0700);
>>> -      else goto skip;
>>>      }
>>>      if (!try->again) return DIRTREE_COMEAGAIN;
>>>      using = AT_REMOVEDIR;
>>
>> I'm confused: rm is currently passing for me? "scripts/test.sh rm"
>> passes, and "mkdir blah; rm -r blah" also works for me...
>>
>> How do I reproduce the failure? (Try on fedora maybe?)
> 
> Both "rm -r" tests fail on Alpine Linux (musl) for me.
> rm -rf passes.

Ah. That I can reproduce.

So the problem turns out to be that faccessat() in musl returns error
EINVAL whenever you feed AT_SYMLINK_NOFOLLOW into the flags field, which
the man page says you're allowed to do.

I'm pretty sure this is a musl bug, not a toybox bug. The code as-is
works on uClibc and glibc for a _reason_.

> And the mount test hangs in an infinite loop for me.
> Per strace, it's not doing any syscalls.

There's a mount test? Oh right, contribution I still haven't reviewed.

the reason i hadn't written a mount test yet was the "running tests as
root" issue I mentioned earlier, I need some kind of test harness using
qemu or similar. (It's on the todo list.)

Almost certainly the failure is related to the /etc/fstab "user" logic,
which I still haven't gotten around to properly testing. I tested the
"mount as root" paths, but just enough to get aboriginal working so I
could cut a release. I don't think I've ever properly tested remount yet...

> Workaround-hit it with a hammer:
> while killall mount; do sleep 1; done
> 
> (I'll be poking at that, if I get the time...)

I've been writing a new ping implementation. (I've gotten a couple ping
contributions but they always do ping and ping6 as two separate
implementations, tend to suck in 4-clause BSD code, and on top of the
normal cleanup it's just faster to do a new one. Not _fast_, just faster. :)

> Thanks,
> Isaac Dunham

Rob

 1411618785.0


More information about the Toybox mailing list