From owner-freebsd-bugs@FreeBSD.ORG Wed May 12 10:50:12 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id A234A16A4CE for ; Wed, 12 May 2004 10:50:12 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1D06A43D2D for ; Wed, 12 May 2004 10:50:12 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) i4CHoCn8065339 for ; Wed, 12 May 2004 10:50:12 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.11/8.12.11/Submit) id i4CHoBtW065338; Wed, 12 May 2004 10:50:11 -0700 (PDT) (envelope-from gnats) Date: Wed, 12 May 2004 10:50:11 -0700 (PDT) Message-Id: <200405121750.i4CHoBtW065338@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: "Dorr H. Clark" Subject: Re: bin/61355: login(1) does not restore terminal ownership on exit X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: "Dorr H. Clark" List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 12 May 2004 17:50:12 -0000 The following reply was made to PR bin/61355; it has been noted by GNATS. From: "Dorr H. Clark" To: freebsd-gnats-submit@FreeBSD.org, eugen@kuzbass.ru Cc: Subject: Re: bin/61355: login(1) does not restore terminal ownership on exit Date: Wed, 12 May 2004 10:45:47 -0700 The fix is presented: --- ../login_bak/login.c Fri Apr 25 19:51:03 2003 +++ ./login.c Sun May 2 04:16:06 2004 @@ -82,6 +82,9 @@ #include "login.h" #include "pathnames.h" +#include +#include + static int auth_pam(void); static void bail(int, int); static int export(const char *); @@ -172,7 +175,16 @@ const char *shell = NULL; login_cap_t *lc = NULL; pid_t pid; + gid_t curr_gid; + char* login; + struct ttyent *tyTmp; + int fdAlt; + int ttyAlt; + struct utmp ut; + unsigned short int found_ut = 0; + FILE* utFile; + (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGHUP, SIG_IGN); @@ -230,6 +242,9 @@ setproctitle("-%s", getprogname()); + curr_gid = getgid(); + login = getlogin(); + for (cnt = getdtablesize(); cnt > 2; cnt--) (void)close(cnt); @@ -246,6 +261,28 @@ else tty = ttyn; + /* set the current login's information so that we can come back to it when the new user logs out*/ + if ((utFile = fopen(_PATH_UTMP, "r")) == NULL) + syslog(LOG_ERR, "failed opening (%s): may not be able to reset user properly", _PATH_UTMP); + if(utFile) + { + while(fread(&ut, sizeof(ut), 1, utFile)) + { + if(!strcmp(ut.ut_line, tty)) + { + found_ut = 1; + break; + } + } + if(!found_ut) + { + strncpy(ut.ut_line, tty, UT_LINESIZE); + strncpy(ut.ut_name, login, UT_NAMESIZE); + strncpy(ut.ut_host, "", UT_HOSTSIZE); + ut.ut_time = 0; + } + (void)fclose(utFile); + } /* * Get "login-retries" & "login-backoff" from default class */ @@ -509,6 +546,40 @@ int status; setproctitle("-%s [pam]", getprogname()); waitpid(pid, &status, 0); + pam_cleanup(); + + /*now change the login back to the original user*/ + //set the tty devices back to the original owner + if (ttyn != tname && chflags(ttyn, 0)) if (errno != EOPNOTSUPP && errno != EROFS) + { + syslog(LOG_ERR, "chflags(%s): %m", ttyn); + printf("chflags(%s): %m", ttyn); + } + if (ttyn != tname && chown(ttyn, uid, (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : curr_gid)) + { + if (errno != EROFS) + { + syslog(LOG_ERR, "chown(%s): %m", ttyn); + printf("chown(%s): %m", ttyn); + } + } + + /* set the tty session */ + setttyent(); + for (ttyAlt = 1; (tyTmp = getttyent()) != NULL; ++ttyAlt) + if (strcmp(tyTmp->ty_name, ut.ut_line) == 0) + break; + endttyent(); + if (ttyAlt > 0 && (fdAlt = open(_PATH_UTMP, O_WRONLY|O_CREAT, 0644)) >= 0) + { + (void)lseek(fdAlt, (off_t)(ttyAlt * sizeof(struct utmp)), L_SET); + (void)write(fdAlt, &ut, sizeof(struct utmp)); + (void)close(fdAlt); + } + + /*set the login back to the initial user*/ + setlogin(login); + bail(NO_SLEEP_EXIT, 0); } This bug occurs when a user session is launched through the "login" binary at a shell prompt and then terminated, the system persists in tracking the tty ownership as the departed user (who has already logged off). To fix the problem, we maintain the original loginid and set that to be the owner of the tty, using the utmp structure as tracked in the file /var/run/utmp so when the login session exits the original owner of the tty is restored. This fix should be evaluated carefully for potential exploits, although this risk can be balanced against the fact that the bug itself represents a security issue. Anirban Kundu, Engineer Dorr H. Clark, Advisor, Graduate School of Engineering Santa Clara University