[comp.std.unix] Retaining file permissions

alex@am.sublink.org (Alex Martelli) (03/02/91)

Submitted-by: alex@am.sublink.org (Alex Martelli)

jik@athena.mit.edu (Jonathan I. Kamens) writes:
	...
	(I assert that cat one>two keeps all permission bits on two)
:You must have a pretty strange version of cat on your system, or a
:brain-damaged kernel that does not clear the setuid bit when a file
:is written to.

It's not the cat-s (I've tried both /bin/cat and /usr/local/gnubin/cat
and I have the source to the latter so I can check), so it must be
what you describe as "brain-damage" in the kernel.  Personally, I
don't see why open() or write() should ever change the file's permission
bits; sure it allows you to do silly things, but then if you care
about security you won't keep files that are executable, and world
writable, at the same time, will you?
Anyway the allegedly-broken kernel is Interactive 2.2, but I believe
others will behave similarly; I'll check at work.

:|> What behavior will Posix.2 mandate?
:
:  I believe POSIX mandates that, for security reasons, the setuid and setgid
:bits on a file should be cleared whenever the file is written to.  If that
:isn't in the standard, then the standard is broken; then again, we already
:knew that, so it isn't a surprise.  Further, I would find it very hard to
:believe that POSIX says that cat is supposed to notice if stdout is a file and
:do an fstat on it before it writes to it to get the permission bits, and then
:do an fchmod afterwards to restore them to their initial conditions.

It would definitely make sense that cat a>b "do the natural thing" - IF
the kernel must muck with permission bit on write()s to b, then it
would hardly make sense for cat to have to undo it, and viceversa, if
the kernel leaves b's permission bits alone, then so should cat 
(should the SHELL try to change permission bits in the redirected-to
file before exec'ing cat??? I would DEFINITELY hope not!).  I have
redirected followups to comp.std.unix since it seems more of a standard
related question.  So, what DOES Posix say about this (open(), write(),
cat, shell redirection, and permission bits), and what SHOULD it say?
-- 
Alex Martelli - (home snailmail:) v. Barontini 27, 40138 Bologna, ITALIA
Email: (work:) martelli@cadlab.sublink.org, (home:) alex@am.sublink.org
Phone: (work:) ++39 (51) 371099, (home:) ++39 (51) 250434; 
Fax: ++39 (51) 366964 (work only), Fidonet: 332/401.3 (home only).

Volume-Number: Volume 22, Number 137

karish@mindcraft.com (Chuck Karish) (03/06/91)

Submitted-by: karish@mindcraft.com (Chuck Karish)

In article <18296@cs.utexas.edu> alex@am.sublink.org (Alex Martelli) writes:
>So, what DOES Posix say about this (open(), write(),
>cat, shell redirection, and permission bits), and what SHOULD it say?

POSIX.1 clause 5.6.1.2, descriptions of S_ISUID and S_ISGID bits:  "On
a regular file, this bit should be cleared on any write."

Note the word "should".  This is a recommendation to implementors, not
a requirement.

BSD 4.3 write(2) man page: "If the real user is not the super-user,
then write() clears the set-user-id bit on a file."

Interactive man pages for stat(2), write(2), and chmod(2) are silent on
this issue.

POSIX.2 is pretty much constrained to accept as valid behavior that's
allowed/suggested by POSIX.1.  I don't think there are any requirements
that the utilities second-guess and defeat the file access policies
that could legitimately be imposed by an underlying POSIX.1 operating
system.

	Chuck Karish		karish@mindcraft.com
	Mindcraft, Inc.		(415) 323-9000

Volume-Number: Volume 22, Number 140

donn@hpfcrn.fc.hp.com (Donn Terry) (03/07/91)

Submitted-by: donn@hpfcrn.fc.hp.com (Donn Terry)

In article <18296@cs.utexas.edu> alex@am.sublink.org (Alex Martelli) writes:

>It would definitely make sense that cat a>b "do the natural thing" - IF
>the kernel must muck with permission bit on write()s to b, then it
>would hardly make sense for cat to have to undo it, and viceversa, if
>the kernel leaves b's permission bits alone, then so should cat 
>(should the SHELL try to change permission bits in the redirected-to
>file before exec'ing cat??? I would DEFINITELY hope not!).  I have
>redirected followups to comp.std.unix since it seems more of a standard
>related question.  So, what DOES Posix say about this (open(), write(),
>cat, shell redirection, and permission bits), and what SHOULD it say?

POSIX.2 (where cat is discussed) is silent on the subject, because it
relies on the underlying system behavior, which doesn't have to be
POSIX.1.  (It could be <your favorite absurd OS name here> as long
as some specific requirements for minimal similarity to POSIX.1 are met.)

POSIX.1 says "On a regular file, [the S_ISUID] bit should be cleared
on any write."  (P102, L684 and 688).  

Two key things here:  "should" (not "shall") and "write" (not write() in
italics). 

"Should" is a recommendation, not a requirement.  Thus, a conforming
system doesn't have to do it.  This is compromise wording, as some
existing implementations would not conform if that was a requirement.
(This is a consequence of the definition of "should".)

"Write" means any write operation, not specifically the write() system
call.  (This is a judgement call on my part, and should not be taken
as in any way official.)

There are those who would (and did) argue that it's "brain-damaged" to
clear the bit, and those who would (and did) argue the other way.

A relevant digression into the use of a standard as a tool for 
purchasing, and how it fits into this kind of problem.

If you care, it's perfectly reasonable in a RFP (or any other purchase)
to specify any "should" as a "shall" (or "shall not").  NIST did that in
one place in FIPS 151-1.  X/Open has done it in several places.  In the
long run, if a clear consensus develops that some "should" is always or
never required, the standard can change to make it a "shall" or "shall
not".  (Someone has to care enough to make that happen during the
next revision, but if the consensus is there, it's not hard.)

When you specify a bunch of options, it can be called a "profile".
There is work on both de-facto standard profiles (X/Open and NIST
qualify here) and on formal ones (IEEE 1003.<several>).  Since profiles
can often be "lighter weight" documents than a typical POSIX standard,
some of the should/shall issues can be addressed in them more rapidly
than in the base standards.  (This might be either because the
marketplace consensus has formed, or that for the narrower market niche
that the profile addresses, there already is a consensus.)

In this specific case, the profile for the folks who think not clearing
the set user ID bit is brain-dead would require a shall; for others
they could leave it alone, or maybe even require "shall not".

Sidelight:  Because I work for a vendor, I shudder to think that "shall
not" would ever actually be required for this case; this makes a problem
for vendors in that now we have to have another implementation option (or two
different implementations!).  It also makes problems for users because
it will cost more to implement the option (OK, not much, but they add
up) which will be passed on to the user, and the costs of administering
go up (again, they add up in complexity, probably geometrically).
Formal profiles (again, such as X/Open or NIST or IEEE) help assure
consistency in the choice of options, making it easier to lower the cost
of implementation, which translates into lower costs for the customer.

Donn Terry
Chair, IEEE 1003.1

Speaking only for myself; no part of this should be construed as anything
but my opinion, and specifically not as the opinion of either IEEE or
my employer.  (I have to say this to keep IEEE happy; I don't blame
them for requiring it, given the consequences.)

Volume-Number: Volume 22, Number 141

martelli@cadlab.sublink.ORG (Alex Martelli) (03/08/91)

Submitted-by: martelli@cadlab.sublink.ORG (Alex Martelli)

Thanks to Donn Terry and the others responding, both here and by Email;
now I understand the S_ISUID/S_ISGID issue better!

donn@hpfcrn.fc.hp.com (Donn Terry) writes:
	...
:POSIX.1 says "On a regular file, [the S_ISUID] bit should be cleared
:on any write."  (P102, L684 and 688).  
:
:Two key things here:  "should" (not "shall") and "write" (not write() in
:italics). 
:
:"Should" is a recommendation, not a requirement.  Thus, a conforming
:system doesn't have to do it.  This is compromise wording, as some
:existing implementations would not conform if that was a requirement.
:(This is a consequence of the definition of "should".)
	...
:If you care, it's perfectly reasonable in a RFP (or any other purchase)
:to specify any "should" as a "shall" (or "shall not").  NIST did that in
:one place in FIPS 151-1.  X/Open has done it in several places.  In the

...but NOT here; indeed, digging into XPG3 I find in vol 2 pg 519 at the
end of the Description of write():  "...and if the file is a regular
file, the S_ISUID and S_ISGID bits of the file mode may be cleared".

Indeed, the "may" sounds to my non-native-speaker ears as even weaker
than the "should"...  so I guess that as a multiplatform application
developer I definitely HAVE TO learn to live with both behaviors (the
chmod() page of XPG3 also has threateninly mysterious caveats about what
is or is not done with S_ISUID/S_ISGID, so it won't necessarily be easy
to compensate for varying behavior of write() in this respect, alas...).

-- 
Alex Martelli - CAD.LAB s.p.a., v. Stalingrado 53, Bologna, Italia
Email: (work:) martelli@cadlab.sublink.org, (home:) alex@am.sublink.org
Phone: (work:) ++39 (51) 371099, (home:) ++39 (51) 250434; 
Fax: ++39 (51) 366964 (work only), Fidonet: 332/401.3 (home only).

Volume-Number: Volume 23, Number 3