[comp.unix.shell] Retaining file permissions

jlwestm@PacBell.COM (Jeff Westman) (02/22/91)

I have a script that replaces a string with another.  The file is executable, 
but when I run it through 'sed' I loose the executable attribute -- and I
don't want to change my umask.

Here's basically what I have:

        #  Replace one occurance with another
        
        print "Enter a \"from\" string:  \c" ;  read FROM
        print "Enter a \"to\"   string:  \c" ;  read TO
        
        sed s/$FROM/$TO/gp $i > xyzyx
        mv -f xyzyx $i

Any suggestions or improvements?

--
Jeff
        

tchrist@convex.COM (Tom Christiansen) (02/22/91)

From the keyboard of jlwestm@PacBell.COM (Jeff Westman):
:I have a script that replaces a string with another.  The file is executable, 
:but when I run it through 'sed' I loose the executable attribute -- and I
:don't want to change my umask.
:
:Here's basically what I have:
:
:        #  Replace one occurance with another
         #  Replace one occurance with occurrence :-)
:        
:        print "Enter a \"from\" string:  \c" ;  read FROM
:        print "Enter a \"to\"   string:  \c" ;  read TO
:        
:        sed s/$FROM/$TO/gp $i > xyzyx
:        mv -f xyzyx $i

% perl -p -i -e "s/$FROM/$TO/g" xyzyx

Did you know that your set duplicates the lines matching $FROM? 
I assume this to be an error.

--tom
-- 
"UNIX was not designed to stop you from doing stupid things, because
 that would also stop you from doing clever things." -- Doug Gwyn

 Tom Christiansen                tchrist@convex.com      convex!tchrist

jik@athena.mit.edu (Jonathan I. Kamens) (02/22/91)

In article <6039@ptsfa.PacBell.COM>, jlwestm@PacBell.COM (Jeff Westman) writes:
|>         #  Replace one occurance with another
|>         
|>         print "Enter a \"from\" string:  \c" ;  read FROM
|>         print "Enter a \"to\"   string:  \c" ;  read TO
|>         
|>         sed s/$FROM/$TO/gp $i > xyzyx
|>         mv -f xyzyx $i

  Tom Christiansen has already posted a perl version, but (believe it or not
:-) it is possible to do it without perl (although perhaps not in one
process).  If you don't have perl installed, you can probably get what you
want by using "cp" in the last line instead of "mv", since cp attempts to keep
file permissions on existing files (although it won't be able to keep setuid
bits; then again, neither will perl).

  Tom's probably right that you want to change the "gp" in the sed command to
"g".  You probably also want to change "occurance" to "occurrence" :-).

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/23/91)

In article <1991Feb22.041826.201@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes:
: If you don't have perl installed, you can probably get what you
: want by using "cp" in the last line instead of "mv", since cp attempts to keep
: file permissions on existing files (although it won't be able to keep setuid
: bits; then again, neither will perl).

Yes it will.  (When 4.0 comes out. :-)

Larry

jpr@jpradley.jpr.com (Jean-Pierre Radley) (02/25/91)

In article <6039@ptsfa.PacBell.COM> jlwestm@PacBell.COM (Jeff Westman) writes:
>I have a script that replaces a string with another.  The file is executable, 
>but when I run it through 'sed' I loose the executable attribute -- and I
>don't want to change my umask.
>
>Here's basically what I have:
>
>        #  Replace one occurance with another
>        
>        print "Enter a \"from\" string:  \c" ;  read FROM
>        print "Enter a \"to\"   string:  \c" ;  read TO
>        
>        sed s/$FROM/$TO/gp $i > xyzyx
>        mv -f xyzyx $i
>

Instead of that last 'mv', try
	
	cat xyzyx > $i
	rm xyzyx

BTW, iz xyzyx what you use for a temporary file name? Why not $0$$ ?

 Jean-Pierre Radley   NYC Public Unix   jpr@jpradley.jpr.com   CIS: 72160,1341

jik@athena.mit.edu (Jonathan I. Kamens) (02/26/91)

In article <1991Feb23.234242.812@am.sublink.org>, alex@am.sublink.org (Alex Martelli) writes:
|> But you *can* keep your setuid bits, as well as the others, with a
|> little known (:-) Unix utility called "cat"; the crafty feline does
|> keep the target's permission bits - "cat xyzyx>$i" will do (a tip: use
|> something like xyzyx.$$ or sometime you'll get bitten by two of these
|> scripts running together in the same directory... brrr!).

  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.

% cp ~/.login frep
% chmod u+s frep
% ls -l frep
-rwsr--r--  1 jik          1820 Feb 26 10:36 frep
% cat ~/.login > frep
% ls -l frep
-rw-r--r--  1 jik          1820 Feb 26 10:37 frep

|> 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.

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

stuart@amc-gw.amc.com (Stuart Poulin) (02/28/91)

You can edit the file in place using ex and `here'.  Ex has options to
suppress it's informative output if you want (I think).

#!/bin/sh
File=$1
echo -n "From "
read FROM
echo -n "To "
read TO

ex $File <<!E!O!F!
g/$FROM/s//$TO/g
w
q
!E!O!F!

-----------------------------------------------------------------------
Stuart Poulin                             DNS: stuart@amc.com
Applied Microsystems Corporation         UUCP: amc-gw!stuart
Redmond, Washington  98073               Dial: 800-ASK-4AMC,206-882-2000 

oz@yunexus.yorku.ca (Ozan Yigit) (03/01/91)

In article <see ref> jik@athena.mit.edu (Jonathan I. Kamens) writes:

>  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.

Any file, or just those files that are also executable?

>If that
>isn't in the standard, then the standard is broken; then again, we already
>knew that, so it isn't a surprise.

Really? How about a list of all those things you already knew to be
broken in the standard? I am much interested.

oz
---
We only know ... what we know, and    |    Internet: oz@nexus.yorku.ca 
that is very little. -- Dan Rather    |    UUCP: utzoo/utai!yunexus!oz

jik@athena.mit.edu (Jonathan I. Kamens) (03/01/91)

In article <21789@yunexus.YorkU.CA>, oz@yunexus.yorku.ca (Ozan Yigit) writes:
|> In article <see ref> jik@athena.mit.edu (Jonathan I. Kamens) writes:
|> >  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.
|> Any file, or just those files that are also executable?

  From write(2):

     If the real user is not the super-user, then write clears
     the set-user-id bit on a file.  This prevents penetration of
     system security by a user who captures a writable set-user-
     id file owned by the super-user.

  If it only did it on executable files, then if there were a file on the disk
that was setuid but not executable, a not-nice person could (a) figure out
some way to write his own program into the file, and (b) use chmod to make it
executable.  this defeats the purpose of the clearing of the set-user-id bit.

|> >If that
|> >isn't in the standard, then the standard is broken; then again, we already
|> >knew that, so it isn't a surprise.
|> Really? How about a list of all those things you already knew to be
|> broken in the standard? I am much interested.

  I can't tell whether or not you're being sarcastic here, but let me clue you
in on something -- I was.

  In any case, one thing I consider broken about POSIX is that there's no
st_blocks field in its stat structure; more generally, there is no standard
way in POSIX to find out how much space a file actually occupies on the disk
(i.e. taking into account holes in the file that don't take up any space on
the disk).  I consider this a major lose.

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

asg@sage.cc.purdue.edu (The Grand Master) (03/01/91)

In article <1991Feb28.205734.26484@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes:
}
}  From write(2):
}
}     If the real user is not the super-user, then write clears
}     the set-user-id bit on a file.  This prevents penetration of
}     system security by a user who captures a writable set-user-
}     id file owned by the super-user.
}
}  If it only did it on executable files, then if there were a file on the disk
}that was setuid but not executable, a not-nice person could (a) figure out
}some way to write his own program into the file, and (b) use chmod to make it
}executable.  this defeats the purpose of the clearing of the set-user-id bit.

WAKE UP. You have got to be kidding. use chmod to make it executable???
If he could use chmod to make it executable, he could use chmod to turn
the suid bit on, which defeats the entire purpose of file ownership, 
system security, etc. 
Gee - I am glad you are not MY sysadmin
ANY modification to a suid file turns the suid bit off - this is handled
by the kernal. (unless root makes the modification). You cannot use cat,
cp, mv, write(2), or ANYTHING to keep the suid bit on. AHHHHGGG.
I am glad the designers of UNIX were not interested in doing this, 
or there would be NO security.
From the pages of chmod(2)
     Only the owner of a file (or the super-user) may change the
     mode.
So, if I can cat > file, then chmod it to executable, It must be
my file!!! In which case it is not really any risk to system security.

}
}-- 
}Jonathan Kamens			              USnail:
}MIT Project Athena				11 Ashford Terrace
}jik@Athena.MIT.EDU				Allston, MA  02134
}Office: 617-253-8085			      Home: 617-782-0710
And I thoug MIT taught people to think before they speak.

			The Grand Master
			   Bruce Varney

jik@athena.mit.edu (Jonathan I. Kamens) (03/01/91)

In article <7120@mentor.cc.purdue.edu>, asg@sage.cc.purdue.edu (The Grand Master) writes:
|> [a vitriolic flame criticizing my intelligence and understanding of Unix]

  Sigh.  It's amazing how people find it necessary to flame where a simple
question would suffice.

  Taking your posting and translating it into polite terms, you're asking,
"Why are you saying that someone could chmod it if they don't own it."

  Among other things, the reason writes to a file turn off the set-user-id bit
is to protect Unix from security holes that we *don't* know about.  There may
be a way that we *don't* know about yet for a user to modify or change the
permissions on a file when he should not be able to.  We *don't know about the
hole yet*, so we *don't know what form it takes*.  In other words, we don't
know what conditions would allow the user to do this.  We don't know whether
it's a user space bug or a kernel but that would allow the user to do this. 
And we don't know what to to prevent the user from being allowed to do this.

  For this reason, there is a very *low-level* safety valve in the kernel. 
"If the file is set-user-id (or set-group-id, I believe), and any sort of
write is attempted, the set-user-id or set-group-id bits are turned off.  This
prevents users from taking advantage of *other bugs that we don't know about*
to use the set-user-id or set-group-id bits to their advantage.

  If we assume that the system is secure, then we do not need to turn off the
setuid and setgid bits on writes to files, since obviously only people who are
allowed to do the writes and who are allowed to use the setuid and setgid bits
are doing it.  If, on the other hand, we assume that the system is not secure,
then we must turn off the setuid and setgid bits when writing to *any* file,
executable or not, as a simple security precaution.

|> And I thoug MIT taught people to think before they speak.

  Preacher, heal thyself.

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

asg@sage.cc.purdue.edu (The Grand Master) (03/01/91)

In article <1991Feb28.221952.29685@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes:
}In article <7120@mentor.cc.purdue.edu>, asg@sage.cc.purdue.edu (The Grand Master) writes:
}|> [a vitriolic flame criticizing my intelligence and understanding of Unix]
}
}  Sigh.  It's amazing how people find it necessary to flame where a simple
}question would suffice.
}
}  Taking your posting and translating it into polite terms, you're asking,
}"Why are you saying that someone could chmod it if they don't own it."
}
}  Among other things, the reason writes to a file turn off the set-user-id bit
}is to protect Unix from security holes that we *don't* know about.  There may
}be a way that we *don't* know about yet for a user to modify or change the
}permissions on a file when he should not be able to.  We *don't know about the
}hole yet*, so we *don't know what form it takes*.  In other words, we don't
}know what conditions would allow the user to do this.  We don't know whether
}it's a user space bug or a kernel but that would allow the user to do this. 
}And we don't know what to to prevent the user from being allowed to do this.
}
You said (paraphrased) that we must turn off the suid bit upon write to 
a non-executable file less someone chmod that file to make it executable.
I said (now listen, this is very simple)
If they can chmod it to executable, they can chmod it to suid. 
Your reasoning is therefore faulty
Or is that too hard for an MIT student to understand
		Bruce Varney
		   The Grand Master

jik@athena.mit.edu (Jonathan I. Kamens) (03/02/91)

In article <7191@mentor.cc.purdue.edu>, asg@sage.cc.purdue.edu (The Grand Master) writes:
|> You said (paraphrased) that we must turn off the suid bit upon write to 
|> a non-executable file less someone chmod that file to make it executable.
|> I said (now listen, this is very simple)
|> If they can chmod it to executable, they can chmod it to suid. 

  This is an ASSUMPTION.  Can you prove, exhaustively, that if a user can,
through some security hole, make a file executable on a Unix system, it
follows that they can also make it setuid?

  I'll say it again, because apparently you didn't read it the first time
(despite the fact that you quoted all of it in your posting) -- WE DON'T KNOW
WHAT FORM SECURITY HOLES TAKE.  If we knew their form, we would FIX THEM.  It
is QUITE POSSIBLE that there is a security hole which would allow someone to
make a file that they do not own executable, while not allowing them to make
it setuid.  Can you PROVE that such a hole does not exist?  If you can, I
suspect there's a job at the NCSC with your name written on it.

|> Your reasoning is therefore faulty

  My reasoning is fine.  You appear to have absolutely no grasp of the concept
of "hedging your bets."  Your argument appears to be that we don't need to
protect ourselves against security holes we don't know about because we know
there aren't any security holes we don't know about.  That just doesn't wash.

|> Or is that too hard for an MIT student to understand

  Please, spare the insults.  They're unnecessary, and to be honest, in this
particular situation, I think they're making you look like a fool.

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

oz@yunexus.yorku.ca (Ozan Yigit) (03/02/91)

[this discussion is no longer relevant to comp.unix.shell. see followup]

In article <see ref> jik@athena.mit.edu (Jonathan I. Kamens) writes:
>In article <21789@yunexus.YorkU.CA>, oz@yunexus.yorku.ca (Ozan Yigit) writes:
>|> In article <see ref> jik@athena.mit.edu (Jonathan I. Kamens) writes:
>|> >  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.
>|> Any file, or just those files that are also executable?

>  From write(2):
	[a fragment of write man page related to suid-bit clearing]

That man page portion probably dates to 4.2BSD, and unfortunately fails to
explain to you [nor answer] the point I was trying to make. Sure enough,
your example of setting suid bit of an ordinary (non-executable) file and
how write clears that suid bit will not work on on many systems, although
you may [sometimes] find the very same write man page on those systems.

Say, brain-damage ;-), or could there possibly be another reason for it?

>  If it only did it on executable files, then if there were a file on the disk
>that was setuid but not executable, a not-nice person could (a) figure out
>some way to write his own program into the file, and (b) use chmod to make it
>executable.  this defeats the purpose of the clearing of the set-user-id bit.

Ah, a sufficiently detailed, didactic paragraph that just happens to be 
erroneous given certain chmod semantics. See your chmod(2) for details.

[I trust someone with enough involvement in the POSIX 1003.1/.n will
describe the treatment/rationale of S_ISUID and S_ISGID bits under various
conditions.]

>|> >If that
>|> >isn't in the standard, then the standard is broken; then again, we already
>|> >knew that, so it isn't a surprise.
>|> Really? How about a list of all those things you already knew to be
>|> broken in the standard? I am much interested.

>	      ... one thing I consider broken about POSIX is that there's no
>st_blocks field in its stat structure; more generally, there is no standard
>way in POSIX to find out how much space a file actually occupies on the disk
> ...

Interesting consideration, though I fail to see why this amounts to POSIX
being broken. I take ``broken'' to mean internally inconsistent, or simply
erroneous, and instead you present your views on something that is not a
part of the standard [along with many other things] and is yet to be shown
indispensible within the its scope. If a strong argument could be made for
such a thing, that would make POSIX incomplete, [which may, as often
happens with other standards, be completed via implementation agreements
or other supplements] but not necessarily broken.

Let me ask again: what is it that you know to be broken?

oz
---
We only know ... what we know, and    |   Internet: oz@nexus.yorku.ca 
that is very little. -- Dan Rather    |   UUCP: utzoo/utai!yunexus!oz

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (03/02/91)

Rather than thinking about security holes, think about user mistakes. If
the kernel turns off the setuid bit upon write, it is much less likely
for a setuid program to be accidentally corrupted than it would be
otherwise. End of discussion.

(User mistakes aren't always the end of the story; sometimes you have to
consider denial-of-service attacks before you see why something reduces
security. But this case is relatively simple.)

---Dan

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

asg@sage.cc.purdue.edu (The Grand Master) (03/03/91)

In article <6227:Mar201:22:4391@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
}Rather than thinking about security holes, think about user mistakes. If
}the kernel turns off the setuid bit upon write, it is much less likely
}for a setuid program to be accidentally corrupted than it would be
}otherwise. End of discussion.
That was not my point. I never disagreed with resetting the suid bit
upon a write - just the his expaination of the reason was not
well-thought-out. In fact, I believe that the suid bit should be unsettable
if the file is writable by anyone.
}
}---Dan

			Bruce