Date: Wed, 6 Oct 2010 16:03:00 -0700 From: Garrett Cooper <gcooper@FreeBSD.org> To: Sergey Kandaurov <pluknet@gmail.com> Cc: Alexander Best <arundel@freebsd.org>, freebsd-hackers@freebsd.org Subject: Re: issue with unsetting 'arch' flag Message-ID: <AANLkTimut3obh4VgKVv3PCgicwEKK4f0zg=W2OnSv86s@mail.gmail.com> In-Reply-To: <AANLkTikYX0vsxZi=J6Asekk-Kd_Y4MyemjDxM5FXARng@mail.gmail.com> References: <20101005235054.GA45827@freebsd.org> <AANLkTi=sA4GP=B61tbEmG6B0CYcET=dCFMJByoS_5=yi@mail.gmail.com> <20101006173522.GA92402@freebsd.org> <AANLkTi==F4zFmJxqOBzMCk%2Buci6XbvoQBe4mqxHjtbr6@mail.gmail.com> <20101006193827.GA13528@freebsd.org> <AANLkTikYX0vsxZi=J6Asekk-Kd_Y4MyemjDxM5FXARng@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
--0050450157037235620491fac75b Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable On Wed, Oct 6, 2010 at 3:01 PM, Sergey Kandaurov <pluknet@gmail.com> wrote: > On 6 October 2010 23:38, Alexander Best <arundel@freebsd.org> wrote: >> On Wed Oct =A06 10, Garrett Cooper wrote: >>> On Wed, Oct 6, 2010 at 10:35 AM, Alexander Best <arundel@freebsd.org> w= rote: >>> > On Wed Oct =A06 10, Garrett Cooper wrote: >>> >> On Tue, Oct 5, 2010 at 4:50 PM, Alexander Best <arundel@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`. >>> >> > =A0^^non-root =A0 =A0 ^^root =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0^^non-= root >>> >> > >>> >> > chflags claims to have cleared the 'arch' flag (which should be im= possible as >>> >> > non-root user), but indeed has done nothing. >>> >> > >>> >> > i've tried the same with 'sappnd' and that works as can be expecte= d. >>> >> > >>> >> > 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 w= ith EPERM. >>> >> >>> >> =A0 =A0 Fails for me when I call the syscall directly, as I would ex= pect, >>> >> and passes when I'm superuser: >>> >> >>> >> $ ./test_chflags >>> >> (uid, euid) =3D (1000, 1000) >>> >> test_chflags: chflags: Operation not permitted >>> >> test_chflags: lchflags: Operation not permitted >>> >> $ sudo ./test_chflags >>> >> (uid, euid) =3D (0, 0) >>> >> >>> >> =A0 =A0 According to my basic inspection in strtofflags >>> >> (.../lib/libc/gen/strtofflags.c), it works as well. >>> >> =A0 =A0 And last but not least, executing the commands directly on t= he CLI work: >>> >> >>> >> $ tmpfile=3D`mktemp /tmp/chflags.XXXXXX` >>> >> $ chflags arch $tmpfile >>> >> chflags: /tmp/chflags.nQm1IL: Operation not permitted >>> >> $ rm $tmpfile >>> >> $ tmpfile=3D`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 s= ure >>> > however you understood the problem. probably i didn't explain it righ= t: >>> > >>> > $ sudo rm -d /tmp/chflags.XXXXXX >>> > $ tmpfile=3D`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=3D`mktemp /tmp/chflags.XXXXXX` >>> $ chflags arch $tmpfile >>> chflags: /tmp/chflags.V2NpXR: Operation not permitted >>> $ chflags noarch $tmpfile >>> $ rm $tmpfile >>> >>> Currently chflags(2) states: >>> >>> =A0 =A0 =A0The SF_IMMUTABLE, SF_APPEND, SF_NOUNLINK, and SF_ARCHIVED fl= ags may only >>> =A0 =A0 =A0be set or unset by the super-user. =A0Attempts to set these = flags by non- >>> =A0 =A0 =A0super-users are rejected, >>> attempts by non-superusers to = clear >>> flags that >>> =A0 =A0 =A0are already unset are silently ignored. <<< =A0These flags m= ay be set at any >>> =A0 =A0 =A0time, but normally may only be unset when the system is in s= ingle-user >>> =A0 =A0 =A0mode. =A0(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 err= or 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 msdosf= s) _very_ interesting: [/sys]$ grep -r SF_ARCHIVED kern/ fs/ ufs/ | grep -v svn fs/msdosfs/msdosfs_vnops.c: vap->va_flags |=3D SF_ARCHIVED; fs/msdosfs/msdosfs_vnops.c: if (vap->va_flags & ~SF_ARCHIVED) fs/msdosfs/msdosfs_vnops.c: if (vap->va_flags & SF_ARCHIVED) The commit that introduced this change probably wasn't doing the right thing: http://svn.freebsd.org/viewvc/base/head/sys/fs/msdosfs/msdosfs= _vnops.c?revision=3D5241&view=3Dmarkup ; cp(1) probably should have been fixed in lieu of `fixing' msdosfs. > - ufs_setattr() does not handle unsetting SF_ARCHIVED, > =A0so all what it does is simply return zero. [EOPNOTSUPP] The underlying file system does not support file flags. So I would expect for invalid flags to return EOPNOTSUPP. ... $ ~/test_chflags_negative test_chflags_negative: should not get here $ sudo ~/test_chflags_negative test_chflags_negative: should not get here *facepalm* I think the problem in part is here (sys/stat.h): * * Super-user and owner changeable flags. */ #define UF_SETTABLE 0x0000ffff /* mask of owner changeable flags *= / #define UF_NODUMP 0x00000001 /* do not dump file */ #define UF_IMMUTABLE 0x00000002 /* file may not be changed */ #define UF_APPEND 0x00000004 /* writes to file may only append *= / #define UF_OPAQUE 0x00000008 /* directory is opaque wrt. union *= / #define UF_NOUNLINK 0x00000010 /* file may not be removed or renam= ed */ /* * Super-user changeable flags. */ #define SF_SETTABLE 0xffff0000 /* mask of superuser changeable fla= gs */ #define SF_ARCHIVED 0x00010000 /* file is archived */ #define SF_IMMUTABLE 0x00020000 /* file may not be changed */ #define SF_APPEND 0x00040000 /* writes to file may only append *= / #define SF_NOUNLINK 0x00100000 /* file may not be removed or renam= ed */ #define SF_SNAPSHOT 0x00200000 /* snapshot inode */ Note the *_SETTABLE macros, and the fact that they allow for more functionality than what's currently slotted with the one-hot encoded flags currently available. SF_ARCHIVED is not present in the other BSDs or Mac OSX either (I did some hunting for a python bug related to chflags a few weeks ago)... and I'm not even sure what this functionality really buys us because it's not well described (but I'd be happy to get an explanation/history lesson). > - /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, Yeah... but ideally tests should be written for this stuff and exercised on all filesystems and exercised whenever code in this particular path is changed, because that would potentially turn into a noticeable performance hit [depending on how it's implemented in chflags(1)]. And lo and behold it already does exist under .../tools/regression/fstest/tests/chflags . I'll audit this once I get back home... Thanks, -Garrett --0050450157037235620491fac75b Content-Type: application/octet-stream; name="test_chflags_negative.c" Content-Disposition: attachment; filename="test_chflags_negative.c" Content-Transfer-Encoding: base64 X-Attachment-Id: f_geyss8wh0 I2luY2x1ZGUgPHN5cy9zdGF0Lmg+CiNpbmNsdWRlIDxlcnIuaD4KI2luY2x1ZGUgPHVuaXN0ZC5o PgoKaW50Cm1haW4odm9pZCkKewoJaWYgKGNoZmxhZ3MoIi90bXAiLCAtMSkpIHsKCQl3YXJuKCJP ayIpOwoJCXJldHVybiAoMCk7Cgl9Cgl3YXJueCgic2hvdWxkIG5vdCBnZXQgaGVyZSIpOwoJcmV0 dXJuICgxKTsKfQo= --0050450157037235620491fac75b--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AANLkTimut3obh4VgKVv3PCgicwEKK4f0zg=W2OnSv86s>