issue with unsetting 'arch' flag

Sergey Kandaurov pluknet at gmail.com
Wed Oct 6 22:01:36 UTC 2010


On 6 October 2010 23:38, Alexander Best <arundel at freebsd.org> wrote:
> On Wed Oct  6 10, Garrett Cooper wrote:
>> On Wed, Oct 6, 2010 at 10:35 AM, Alexander Best <arundel at freebsd.org> wrote:
>> > On Wed Oct  6 10, Garrett Cooper wrote:
>> >> On Tue, Oct 5, 2010 at 4:50 PM, Alexander Best <arundel at freebsd.org> wrote:
>> >> > hi there,
>> >> >
>> >> > i think the following example shows the problem better than a long explanation:
>> >> >
>> >> > `touch ftest && chflags arch ftest && chflags -vv 0 ftest`.
>> >> >  ^^non-root     ^^root                ^^non-root
>> >> >
>> >> > chflags claims to have cleared the 'arch' flag (which should be impossible as
>> >> > non-root user), but indeed has done nothing.
>> >> >
>> >> > i've tried the same with 'sappnd' and that works as can be expected.
>> >> >
>> >> > The issue was confirmed to exist in HEAD (me), stable/8 (pgollucc1, jpaetzel)
>> >> > and stable/7 (nox).
>> >> > On stable/6 it does NOT exist (jpaetzel). chflags properly fails with EPERM.
>> >>
>> >>     Fails for me when I call the syscall directly, as I would expect,
>> >> and passes when I'm superuser:
>> >>
>> >> $ ./test_chflags
>> >> (uid, euid) = (1000, 1000)
>> >> test_chflags: chflags: Operation not permitted
>> >> test_chflags: lchflags: Operation not permitted
>> >> $ sudo ./test_chflags
>> >> (uid, euid) = (0, 0)
>> >>
>> >>     According to my basic inspection in strtofflags
>> >> (.../lib/libc/gen/strtofflags.c), it works as well.
>> >>     And last but not least, executing the commands directly on the CLI work:
>> >>
>> >> $ tmpfile=`mktemp /tmp/chflags.XXXXXX`
>> >> $ chflags arch $tmpfile
>> >> chflags: /tmp/chflags.nQm1IL: Operation not permitted
>> >> $ rm $tmpfile
>> >> $ tmpfile=`mktemp /tmp/chflags.XXXXXX`
>> >> $ sudo chflags arch $tmpfile
>> >> $ sudo chflags noarch $tmpfile
>> >> $ rm $tmpfile
>> >
>> > thanks for your test app and helping out with this problem. i'm not sure
>> > however you understood the problem. probably i didn't explain it right:
>> >
>> > $ sudo rm -d /tmp/chflags.XXXXXX
>> > $ tmpfile=`mktemp /tmp/chflags.XXXXXX`
>> > $ sudo chflags arch $tmpfile
>> > $ chflags noarch $tmpfile
>> >
>> > is what's causing the problem. the last chflags call should fail, but it
>> > doesn't.
>>
>> Sorry... my CLI based example was stupid. I meant:
>>
>> $ tmpfile=`mktemp /tmp/chflags.XXXXXX`
>> $ chflags arch $tmpfile
>> chflags: /tmp/chflags.V2NpXR: Operation not permitted
>> $ chflags noarch $tmpfile
>> $ rm $tmpfile
>>
>> Currently chflags(2) states:
>>
>>      The SF_IMMUTABLE, SF_APPEND, SF_NOUNLINK, and SF_ARCHIVED flags may only
>>      be set or unset by the super-user.  Attempts to set these flags by non-
>>      super-users are rejected, >>> attempts by non-superusers to clear
>> flags that
>>      are already unset are silently ignored. <<<  These flags may be set at any
>>      time, but normally may only be unset when the system is in single-user
>>      mode.  (See init(8) for details.)
>>
>> So this behavior is already well documented :). The EPERM section
>> should really note SF_ARCHIVED though (whoever added the flag forgot
>> to add that particular item to the ERRORS section).
>
> that's perfectly alright. clearing an unset flag shouldn't cause any error to
> be returned. however in my example arch *does* get set and still trying to
> unset it as normal user doesn't return an error.
>

It's even more interesting.

As far as I could parse the code:
- UFS has no special handling for SF_ARCHIVED (I found only it for msdosfs)
- ufs_setattr() does not handle unsetting SF_ARCHIVED,
  so all what it does is simply return zero.
- /bin/chflags doesn't check the actual flags value from inode after
calling chflags() syscall, and blindly assumes all is well, if chflags()
returns with zero,

-- 
wbr,
pluknet


More information about the freebsd-hackers mailing list