bin/61355: login(1) does not restore terminal ownership on exit

Dorr H. Clark dclark at applmath.scu.edu
Wed May 12 10:50:12 PDT 2004


The following reply was made to PR bin/61355; it has been noted by GNATS.

From: "Dorr H. Clark" <dclark at applmath.scu.edu>
To: freebsd-gnats-submit at FreeBSD.org, eugen at 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 <sys/types.h>
 +#include <utmp.h>
 +
  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


More information about the freebsd-bugs mailing list