[670] in Kerberos-V5-bugs
k5b4 krlogind bugs
daemon@ATHENA.MIT.EDU (Scott Schwartz)
Sat Aug 20 22:40:47 1994
To: krb5-bugs@MIT.EDU
Cc: kerberos@MIT.EDU
Date: Sat, 20 Aug 1994 22:27:51 -0400
From: Scott Schwartz <schwartz@groucho.cse.psu.edu>
krlogind shipped with K5b4p2 has a few bugs. The enclosed patch fixes
three typos, and makes a stab at repairing a real defect. The code is a
twisty maze of ifdefs, so I'll tell you how the problem and its solution
look under SunOS 4.1; it's probably similar for other BSD flavored
systems, but your mileage will vary.
The problem is essentially this: in krlogind.c:doit() the process
becomes a process group leader with setsid, opens a pty and acquires it
as the controlling tty. Then rlogind forks. In the child it makes sure
that the pty shares the process group of the controlling tty and then
execs login. In the parent it tries to dissociate from the controlling
tty with setpgrp(0,0).
This procedure goes wrong in a couple of ways. First, the final setpgrp
fails because, in sunos at least, you can only become a process group or
session leader once, and we have already done a setsid. So the daemon
keeps the ctty. Next, the child, and hence the shell that the user
gets, is in the same process group as the parent, with the same ctty,
and is in the same process group. So when the user hits ctrl-c, rlogind
gets the signal and dies.
In order to get the right effect, the child process should be in its own
process group, and the parent should have no ctty. That's how Sun's
rlogind and the Kerberos 5 telnetd behange. In the patch below I
achieve this by arranging for the child to start a new session (with
setsid), and then grab the controlling tty away from the parent using
TIOCSCTTY. The latter function may be a SunOSism, but the man page
indicates that this is exactly the job it was intended for.
Most of the people reading this are probably wondering why they never
noticed this problem. The answer is that you use csh, which always
creates a new process group for itself. If you use sh or rc or some
other shell which eschews job control you don't get the new process
group, with dire consequences.
diff -u -r1.1 krlogind.c
--- 1.1 1994/08/19 17:16:41
+++ krlogind.c 1994/08/20 22:08:15
@@ -510,7 +510,7 @@
alarm(0);
fromp->sin_port = ntohs((u_short)fromp->sin_port);
- hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
+ hp = gethostbyaddr((char*)&fromp->sin_addr, sizeof (struct in_addr),
fromp->sin_family);
if (hp == 0) {
/*
@@ -578,7 +578,7 @@
if (vfd < 0)
fatalperror(f, line);
#ifdef NOFCHMOD
- if (chmod(vfd,0))
+ if (chmod(line,0))
#else
if (fchmod(vfd, 0))
#endif
@@ -652,12 +652,27 @@
It seems to work fine on 4.3BSD with this code enabled.
IMP's need both ioctl and setpgrp..
*/
+
+#ifdef sun /* XXX - need a more general ifdef */
+ /* The shell that this child will become needs to
+ start in its own process group with its own controlling
+ tty. setsid gives us a fresh process group and makes us
+ the leader, then we use ioctl to grab the slave side of
+ the pty and make it our controlling tty, taking it away
+ from any other process that was using it (our parent in
+ particular). */
+ if (setsid() < 0)
+ fatalperror(f, "setsid");
+ if (ioctl(t, TIOCSCTTY, 1) < 0)
+ fatalperror(f, "taking controlling tty");
+#endif
+
#if !defined(SYSV) || defined(sysvimp)
/* SYSV set process group prior to opening pty */
#ifdef sysvimp
pid = 0;
#else
-#ifdef GETGRP_ONEARG
+#ifndef GETGRP_ONEARG
pid = getpgrp();
#else
pid = getpgrp(getpid());