cvs commit: src/lib/libc/sys chown.2

Bruce Evans bde at zeta.org.au
Wed Dec 13 09:33:54 PST 2006


On Wed, 13 Dec 2006, Pawel Jakub Dawidek wrote:

> On Thu, Dec 14, 2006 at 02:31:52AM +1100, Bruce Evans wrote:
>> On Wed, 13 Dec 2006, Pawel Jakub Dawidek wrote:
>>
>>> pjd         2006-12-13 11:46:38 UTC
>>>
>>> FreeBSD src repository
>>>
>>> Modified files:
>>>   lib/libc/sys         chown.2
>>> Log:
>>> Be more precise with EPERM description. When chown(2) is a no-op, it will
>>> return 0.
>>
>> VADMIN access is still required for null changes.  This normally means
>> that the the caller must own the file, but there are complications for
>> ACLs. [...]
>
> Right, my testing wasn't precise.
>
> But still, if I pass uid=-1 and gid=-1 it works always (I don't have to
> have VADMIN access).

I forget about these.  They are magic and mean "don't change, and (?)
succeed in some permisions checks based on ids".  Hmm, their operation is
tricky:

First, the -1's are excessively magic.  They just happen to be identical
to VNOVAL when converted to ids.  setfown() depends on this when it
copies the userland values to vattr.  This isn't a problem in practice
of course -- VNOVAL is the same magic -1.

When both ids are VNOVAL, the VOP_SETATTR() call is already null and
doesn't do anything (for ffs, it doesn't even call ufs_chown()).
POSIX allows it to either update or not update the ctime, but I think
allowing the update is a bug in POSIX -- it lets anyone clobber the
ctime of any file, at least with my interpretation of null changes to
gids.

When at least one id is not VNOVAL, for ffs ufs_chown() is called and
it does the VADMIN check after replacing uid == VNOVAL with the file uid.
This prevents further problems.  In this case, POSIX requires the ctime
to be be marked for update even for null changes, and FreeBSD implements
this.  The VADMIN check prevents anyone clobbering ctime of any file
using this type of null change.

>> The details for this are hard to describe. They are at least as complicated
>> as:
>> - the effective uid must be the super-user, unless all of the following:
>>   . it is the same as the file's uid, or [complications for ACLs]
>>   . the change to the uids of the file is null
>>   . [permission is never granted based solely on the egid-- check this]
>>   . the change to the gids is either null or the new file gid is in the
>>     same group as the egid.
>>   . [nothing is required or the old file gid -- check this]
>> I used fine print in POSIX to justify permitting null changes to the
>> gid.  FreeBSD-1 doesn't allow this.  My reasoning was something like
>> "non-null changes (from a gid not in our group to one in our group)
>> are permitted (if euid == old file uid == new file uid), so why disallow
>> null changes?  The uid checks should be sufficient."  McKusick agreed
>> with this.
>
> Do you have a suggestion how we can describe it properly?

Write your regression tests for all cases first :-).  Check POSIX.  I'm
too tired to understand the details that POSIX gives now.  It gives more
details than I remember, and still requires a subtle interpretation of
"change" as "non-null change" to permit certain null changes of gids.

Bruce


More information about the cvs-src mailing list