[comp.unix.ultrix] Ultrix 4.1 TIOCSPGRP peculiarities -- is this correct behaviour?

D. Allen [CGL]" <idallen@watcgl.waterloo.edu> (03/05/91)

You cannot use TIOCSPGRP to set a tty into a process group N that has
any other processes in it, unless your controlling terminal matches the
controlling terminal of some process that is also in process group N.
You can't even do it if you're running as root.  Is this useful?

This means if some user somewhere on the system happens to have a
process in a process group that you want to use, you can't do an ioctl
on a tty to set that process group unless you first yourself create some
dummy process in the process group.

Examine the following.  I have a command that uses TIOCSPGRP to set a tty
process group.  When given a process id, it uses setpgrp on the pid.

    % setpgrp 6612 /dev/ttyq6       -- this doesn't work
    /dev/ttyq6: Not owner
    % sleep 999 &
    [1] 5585
    % setpgrp 6612 5585             -- put the sleep in pgrp 6612
    % setpgrp 6612 /dev/ttyq6       -- this works now (?!)
    % kill 5585
    [1] 5585 Terminated sleep 999
    % setpgrp 6612 /dev/ttyq6       -- now it fails again
    /dev/ttyq6: Not owner

What is happening is that the initial setpgrp on ttyq6 is failing because
the kernel can't find any processes with my current controlling tty and
the 6612 process group.  So, to make the ioctl succeed, I simply create a
silly process (thus, it inherits my current controlling tty) and put it
in the 6612 process group.  I re-issue the setpgrp against ttyq6, the kernel
finds a match for process and control tty, and lets the ioctl succeed.

Is this useful?  Since it is trivial to bypass the "security" this
provides, why restrict the ioctl at all?

RISC/os (UMIPS) 4.51 and BSD4.3 do not restrict the ioctl, and
programs I've ported from these systems don't work unmodified on Ultrix.

SunOS 4.1 has some even stranger rules about TIOCSPGRP.

This has been around since at least Ultrix 3.1C.  I posted this
observation last December; now we have kernel sources so I know what is
going on, and it's still going on in Ultrix 4.1.

#include <standard wish for an electronic SPR form>

Note:
    Anyone can still use TIOCSPGRP to set any readable or writable tty to
    any *unused* process group.  This can really foul up your friends who
    leave their terminals unprotected; but then, so can "stty 0".
-- 
-IAN! (Ian! D. Allen) idallen@watcgl.uwaterloo.ca idallen@watcgl.waterloo.edu
 [129.97.128.64]  Computer Graphics Lab/University of Waterloo/Ontario/Canada

ronnie@sos.com (Ron Schnell) (03/05/91)

This behavior is due to the POSIX session/pgrp requirements.  If I
remember correctly, the reason for the change was to fix the security
bug which allowed a user to set his terminal pgrp to something that
was unused at the moment, wait for someone else to login with that
pgrp, and then be able to send group signals by hitting control-c,
control-z, etc.

I may not have it right exactly.

#Ron
(ronnie@sos.com)

metcalf@masala.lcs.mit.edu (Chris Metcalf) (03/07/91)

As a result of the funny Ultrix requirements for getting a control
tty, if you are writing or porting your own rlogind.c be aware that
you have to reset the pgrp after calling vhangup().  The following
diff applies to the Kerberos code we're running here.

Thanks to Ian Allen for tracking down the problem; TFM certainly
doesn't help.

Chris Metcalf

*** /tmp/,RCSt1001681	Wed Mar  6 11:04:31 1991
--- rlogind.c	Wed Mar  6 08:49:08 1991
***************
*** 256,267 ****
   		fatalperror(f, line);
   	if (fchmod(t, 0))
   		fatalperror(f, line);
   	(void)signal(SIGHUP, SIG_IGN);
   	vhangup();
   	(void)signal(SIGHUP, SIG_DFL);
   	t = open(line, O_RDWR);
   	if (t < 0)
   		fatalperror(f, line);
   	{
   		struct sgttyb b;
   
--- 264,285 ----
   		fatalperror(f, line);
   	if (fchmod(t, 0))
   		fatalperror(f, line);
   	(void)signal(SIGHUP, SIG_IGN);
   	vhangup();
   	(void)signal(SIGHUP, SIG_DFL);
+ #ifdef ultrix
+ 	/*
+ 	 * In Ultrix 4.1 (and maybe 4.0), you have to have pgrp = 0 to
+ 	 * get a controlling tty; it doesn't suffice just to have no
+ 	 * controlling terminal at open time (yes, the man page lies).
+ 	 * 	Chris Metcalf
+ 	 */
+ 	if (setpgrp(0,0))
+ 		perror("setpgrp(0,0)");
+ #endif ultrix
   	t = open(line, O_RDWR);
   	if (t < 0)
   		fatalperror(f, line);
   	{
   		struct sgttyb b;
   
--
			Chris Metcalf --- MIT Laboratory for Computer Science
			email to metcalf@lcs.mit.edu, or phone (617) 253-7766

D. Allen [CGL]) (03/07/91)

>This behavior is due to the POSIX session/pgrp requirements.

I'd believe that, except I wasn't running anything in POSIX mode.
-- 
-IAN! (Ian! D. Allen) idallen@watcgl.uwaterloo.ca idallen@watcgl.waterloo.edu
 [129.97.128.64]  Computer Graphics Lab/University of Waterloo/Ontario/Canada