Author: des
Date: Tue Nov  4 23:29:29 2014
New Revision: 274106
URL: https://svnweb.freebsd.org/changeset/base/274106

Log:
  [SA-14:25] Fix kernel stack disclosure in setlogin(2) / getlogin(2).
  [SA-14:26] Fix remote command execution in ftp(1).
  
  Approved by:  so (des)

Modified:
  head/contrib/tnftp/src/fetch.c
  head/sys/kern/kern_prot.c

Modified: head/contrib/tnftp/src/fetch.c
==============================================================================
--- head/contrib/tnftp/src/fetch.c      Tue Nov  4 23:10:58 2014        
(r274105)
+++ head/contrib/tnftp/src/fetch.c      Tue Nov  4 23:29:29 2014        
(r274106)
@@ -547,7 +547,7 @@ fetch_url(const char *url, const char *p
        url_decode(decodedpath);
 
        if (outfile)
-               savefile = ftp_strdup(outfile);
+               savefile = outfile;
        else {
                cp = strrchr(decodedpath, '/');         /* find savefile */
                if (cp != NULL)
@@ -571,8 +571,7 @@ fetch_url(const char *url, const char *p
        rangestart = rangeend = entitylen = -1;
        mtime = -1;
        if (restartautofetch) {
-               if (strcmp(savefile, "-") != 0 && *savefile != '|' &&
-                   stat(savefile, &sb) == 0)
+               if (stat(savefile, &sb) == 0)
                        restart_point = sb.st_size;
        }
        if (urltype == FILE_URL_T) {            /* file:// URLs */
@@ -1098,17 +1097,25 @@ fetch_url(const char *url, const char *p
        }               /* end of ftp:// or http:// specific setup */
 
                        /* Open the output file. */
-       if (strcmp(savefile, "-") == 0) {
-               fout = stdout;
-       } else if (*savefile == '|') {
-               oldintp = xsignal(SIGPIPE, SIG_IGN);
-               fout = popen(savefile + 1, "w");
-               if (fout == NULL) {
-                       warn("Can't execute `%s'", savefile + 1);
-                       goto cleanup_fetch_url;
+
+       /*
+        * Only trust filenames with special meaning if they came from
+        * the command line
+        */
+       if (outfile == savefile) {
+               if (strcmp(savefile, "-") == 0) {
+                       fout = stdout;
+               } else if (*savefile == '|') {
+                       oldintp = xsignal(SIGPIPE, SIG_IGN);
+                       fout = popen(savefile + 1, "w");
+                       if (fout == NULL) {
+                               warn("Can't execute `%s'", savefile + 1);
+                               goto cleanup_fetch_url;
+                       }
+                       closefunc = pclose;
                }
-               closefunc = pclose;
-       } else {
+       }
+       if (fout == NULL) {
                if ((rangeend != -1 && rangeend <= restart_point) ||
                    (rangestart == -1 && filesize != -1 && filesize <= 
restart_point)) {
                        /* already done */
@@ -1318,7 +1325,8 @@ fetch_url(const char *url, const char *p
                (*closefunc)(fout);
        if (res0)
                freeaddrinfo(res0);
-       FREEPTR(savefile);
+       if (savefile != outfile)
+               FREEPTR(savefile);
        FREEPTR(uuser);
        if (pass != NULL)
                memset(pass, 0, strlen(pass));

Modified: head/sys/kern/kern_prot.c
==============================================================================
--- head/sys/kern/kern_prot.c   Tue Nov  4 23:10:58 2014        (r274105)
+++ head/sys/kern/kern_prot.c   Tue Nov  4 23:29:29 2014        (r274106)
@@ -2066,21 +2066,20 @@ struct getlogin_args {
 int
 sys_getlogin(struct thread *td, struct getlogin_args *uap)
 {
-       int error;
        char login[MAXLOGNAME];
        struct proc *p = td->td_proc;
+       size_t len;
 
        if (uap->namelen > MAXLOGNAME)
                uap->namelen = MAXLOGNAME;
        PROC_LOCK(p);
        SESS_LOCK(p->p_session);
-       bcopy(p->p_session->s_login, login, uap->namelen);
+       len = strlcpy(login, p->p_session->s_login, uap->namelen) + 1;
        SESS_UNLOCK(p->p_session);
        PROC_UNLOCK(p);
-       if (strlen(login) + 1 > uap->namelen)
+       if (len > uap->namelen)
                return (ERANGE);
-       error = copyout(login, uap->namebuf, uap->namelen);
-       return (error);
+       return (copyout(login, uap->namebuf, len));
 }
 
 /*
@@ -2099,21 +2098,23 @@ sys_setlogin(struct thread *td, struct s
        int error;
        char logintmp[MAXLOGNAME];
 
+       CTASSERT(sizeof(p->p_session->s_login) >= sizeof(logintmp));
+
        error = priv_check(td, PRIV_PROC_SETLOGIN);
        if (error)
                return (error);
        error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL);
-       if (error == ENAMETOOLONG)
-               error = EINVAL;
-       else if (!error) {
-               PROC_LOCK(p);
-               SESS_LOCK(p->p_session);
-               (void) memcpy(p->p_session->s_login, logintmp,
-                   sizeof(logintmp));
-               SESS_UNLOCK(p->p_session);
-               PROC_UNLOCK(p);
+       if (error != 0) {
+               if (error == ENAMETOOLONG)
+                       error = EINVAL;
+               return (error);
        }
-       return (error);
+       PROC_LOCK(p);
+       SESS_LOCK(p->p_session);
+       strcpy(p->p_session->s_login, logintmp);
+       SESS_UNLOCK(p->p_session);
+       PROC_UNLOCK(p);
+       return (0);
 }
 
 void
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to