[net.bugs.4bsd] su in crontab

wls@astrovax.UUCP (William L. Sebok) (01/11/86)

I just tripped over a rather puzzling anomaly.  If I insert 

08 * * * * su wls % exec /usr/ucb/whoami >>/mnt/wls/TST/Errors 2>&1

I get "root" in the file /mnt/wls/TST/Errors, while if instead I insert

12 * * * * echo /usr/ucb/whoami | su wls >>/mnt/wls/TST/Errors 2>&1

Then /mnt/wls/TST/Errors  contains "wls".  Can any one tell me what is
going on?  This is on a Vax running 4.2 BSD.  I ran into this when trying
to use rsh to transfer news to another machine.  I am aware that the
whoami manual entry lies, that it uses the real uid rather than the
effective uid.  I don't know in that case whether the man entry or the
code behavior is correct.
-- 
Bill Sebok			Princeton University, Astrophysics
{allegra,akgua,cbosgd,decvax,ihnp4,noao,philabs,princeton,vax135}!astrovax!wls

kre@munnari.OZ (Robert Elz) (01/13/86)

In article <706@astrovax.UUCP>, wls@astrovax.UUCP (William L. Sebok) writes:
> I just tripped over a rather puzzling anomaly.  If I insert 
> 
> 08 * * * * su wls % exec /usr/ucb/whoami >>/mnt/wls/TST/Errors 2>&1
> 
> I get "root" in the file /mnt/wls/TST/Errors...

% in a crontab line is replaced by a newline.  Cron executes
the resulting line with "sh -c <line>"

In 6th edition, the shell would run commands, and hand them its
standard input as their standard input, so the \n in cron lines
could (sometimes) be useful for passsing data to commands.

Since then, the standard input of the commands run by sh has been
the standard input of the shell.  For commands run by cron, standard
input is "/" (as is standard output, and standard error), so your
"su" would have been handed the contents of "/" as its input.  I
doubt if it executed many useful commands...  (But try making a file
in / with a name like "\nrm /etc/passwd\n" ...:-).  Then the "exec..."
command would have been executed by the shell after the su finally
gave up (as root).

What this all means is that the only way to pass data to commands run
by cron, is to put the data in a file, and redirect stdin, or use your
"echo" trick for simple input.  I doubt that there's any remaining use
for the '%' construct really, it could probably vanish without anyone
realizing it had gone.  4.3 has added a user name field to crontab,
so you can run commands from there as any user you like, and won't need
"su".  Not as general purpose as the SysV user crontabs, but better
than it was.

Robert Elz		seismo!munnari!kre  kre%munnari.oz@seismo.css.gov

wls@astrovax.UUCP (William L. Sebok) (01/13/86)

In article <706@astrovax.UUCP> I wrote:

>I just tripped over a rather puzzling anomaly.  If I insert
(in /usr/lib/crontab)
>
>08 * * * * su wls % exec /usr/ucb/whoami >>/mnt/wls/TST/Errors 2>&1
>
>I get "root" in the file /mnt/wls/TST/Errors,

gatech!wan (Peter N Wan) and mcvax!tjalk!sjoerd (Sjoerd Mullender) sent me
what I believe to be the correct answer.  Peter Wan writes:

	"Since 'cron' runs as root, it cranks up a shell which does:

		su wls
		exec /usr/ucb/whoami >>/mnt/wls/TST/Errors 2>&1

	The 'su' dies without executing anything as "wls", and the second line
	is executed as "root" again."

The problem was that I had believed the man entry for crontab, which says:
 
"The sixth field is a string that is executed by the Shell at the specified
times.  A percent character in this field is translated to a newline character.
Only the first line (up to a % or end of line) of the command field is executed
by the Shell.  The other lines are made available to the command as standard
input."

I have now glanced at the code for cron.  All it does is translate the percent
characters to newline characters and then pass the whole string to a sh -c.
Thus the man entry for cron is incorrect and cron behaves like was indicated to
me above.  Each line separated by a % is executed as a separate line by the
shell and there is no standard input.

I could have achieved the intended result with the line (I have tested it):

08 * * * * su wls <<'EOT' >>/mnt/wls/TST/Errors 2>&1 % exec /usr/ucb/whoami %EOT

Personally I believe that it is cron rather than the man entry that should be
fixed.  The above contruction is cumbersome.  Generally with this behavior (the
above construction excepted) the '%' feature isn't needed as a ';' would
achieve the same effect.

Of course it would be even better if there was a way in which one could tell
cron directly under what uid an entry is to be run.  The System V cron and the
Version 8 cron (I think) already can do this.
-- 
Bill Sebok			Princeton University, Astrophysics
{allegra,akgua,cbosgd,decvax,ihnp4,noao,philabs,princeton,vax135}!astrovax!wls

stan@tikal.UUCP (Stan Tazuma) (01/14/86)

In article <706@astrovax.UUCP> wls@astrovax.UUCP (William L. Sebok) writes:
>I just tripped over a rather puzzling anomaly.  If I insert 
>
>08 * * * * su wls % exec /usr/ucb/whoami >>/mnt/wls/TST/Errors 2>&1
>
>I get "root" in the file /mnt/wls/TST/Errors, while if instead I insert
>
>12 * * * * echo /usr/ucb/whoami | su wls >>/mnt/wls/TST/Errors 2>&1
>

The problem is that the man page for Berkeley cron lies.  The man page says
that when the '%' is used, following 'line's are passed to the command as input.
This is false.  When cron starts up a shell for the entire command
line, it first replaces all '%'s by new-lines.  Basically, your first
example above would be executed like:
	$ su wls
	$ exec /usr/ucb/whoami >> .....
The first command (su) would start up a setuid shell; the shell
would see EOF, and promptly exit (uid then reverts back to cron's uid).
Then, the exec line would be executed, and the user-id would be cron's
user-id, namely root in your case.

The second of your crontab lines would be executed as expected, and
that's why it works.

To properly use the '%' char. in a crontab command line, try:
	su wls <<x % /usr/ucb/whoami %x
or, since EOF (EOT) is sufficient for the su shell,
	su wls <<x % /usr/ucb/whoami
will work.
Notice that this is just the 'here' document.  I.e.,
	$ su wls <<x
	$ /usr/ucb/whoami
	$ x
so 'x' can be any string.

Important:  the System V cron interprets the '%' operator as documented
in the cron man page.
For those with Pyramid computers, the System V cron is being used.

berliner@convex.UUCP (01/16/86)

> /* Written 12:59 pm  Jan 13, 1986 by wls@astrovax.UUCP in net.bugs.4bsd */
> Of course it would be even better if there was a way in which one could tell
> cron directly under what uid an entry is to be run.  The System V cron and 
> the Version 8 cron (I think) already can do this.

If I remember correctly, the 4.3 BSD version of cron added a field which
would specify the user that the command would be run as.  For example:

00 05 * * * root find /usr/preserve -mtime +7 -a -exec rm -f {} \;
30  * * * * adm  /usr/adm/accounting > /dev/console

These crontab lines would execute the find as root and the accounting as adm
(no flames, please -- these are for examples only).

Brian Berliner
CONVEX Computer Corporation
{ihnp4,uiucdcs}!convex!berliner