From owner-svn-src-head@freebsd.org Tue Apr 26 20:36:33 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id BE851B1D94C; Tue, 26 Apr 2016 20:36:33 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 99CCA13D9; Tue, 26 Apr 2016 20:36:33 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u3QKaWu2038437; Tue, 26 Apr 2016 20:36:32 GMT (envelope-from kp@FreeBSD.org) Received: (from kp@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u3QKaWto038435; Tue, 26 Apr 2016 20:36:32 GMT (envelope-from kp@FreeBSD.org) Message-Id: <201604262036.u3QKaWto038435@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kp set sender to kp@FreeBSD.org using -f From: Kristof Provost Date: Tue, 26 Apr 2016 20:36:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r298664 - head/sys/fs/msdosfs X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Apr 2016 20:36:33 -0000 Author: kp Date: Tue Apr 26 20:36:32 2016 New Revision: 298664 URL: https://svnweb.freebsd.org/changeset/base/298664 Log: msdosfs: Prevent buffer overflow when expanding win95 names In win2unixfn() we expand Windows 95 style long names. In some cases that requires moving the data in the nbp->nb_buf buffer backwards to make room. That code failed to check for overflows, leading to a stack overflow in win2unixfn(). We now check for this event, and mark the entire conversion as failed in that case. This means we present the 8 character, dos style, name instead. PR: 204643 Differential Revision: https://reviews.freebsd.org/D6015 Modified: head/sys/fs/msdosfs/direntry.h head/sys/fs/msdosfs/msdosfs_conv.c Modified: head/sys/fs/msdosfs/direntry.h ============================================================================== --- head/sys/fs/msdosfs/direntry.h Tue Apr 26 20:27:17 2016 (r298663) +++ head/sys/fs/msdosfs/direntry.h Tue Apr 26 20:36:32 2016 (r298664) @@ -145,7 +145,7 @@ struct msdosfsmount; char *mbnambuf_flush(struct mbnambuf *nbp, struct dirent *dp); void mbnambuf_init(struct mbnambuf *nbp); -void mbnambuf_write(struct mbnambuf *nbp, char *name, int id); +int mbnambuf_write(struct mbnambuf *nbp, char *name, int id); int dos2unixfn(u_char dn[11], u_char *un, int lower, struct msdosfsmount *pmp); int unix2dosfn(const u_char *un, u_char dn[12], size_t unlen, u_int gen, Modified: head/sys/fs/msdosfs/msdosfs_conv.c ============================================================================== --- head/sys/fs/msdosfs/msdosfs_conv.c Tue Apr 26 20:27:17 2016 (r298663) +++ head/sys/fs/msdosfs/msdosfs_conv.c Tue Apr 26 20:36:32 2016 (r298664) @@ -658,7 +658,9 @@ win2unixfn(struct mbnambuf *nbp, struct switch (code) { case 0: *np = '\0'; - mbnambuf_write(nbp, name, (wep->weCnt & WIN_CNT) - 1); + if (mbnambuf_write(nbp, name, + (wep->weCnt & WIN_CNT) - 1) != 0) + return -1; return chksum; case '/': *np = '\0'; @@ -676,7 +678,9 @@ win2unixfn(struct mbnambuf *nbp, struct switch (code) { case 0: *np = '\0'; - mbnambuf_write(nbp, name, (wep->weCnt & WIN_CNT) - 1); + if (mbnambuf_write(nbp, name, + (wep->weCnt & WIN_CNT) - 1) != 0) + return -1; return chksum; case '/': *np = '\0'; @@ -694,7 +698,9 @@ win2unixfn(struct mbnambuf *nbp, struct switch (code) { case 0: *np = '\0'; - mbnambuf_write(nbp, name, (wep->weCnt & WIN_CNT) - 1); + if (mbnambuf_write(nbp, name, + (wep->weCnt & WIN_CNT) - 1) != 0) + return -1; return chksum; case '/': *np = '\0'; @@ -708,7 +714,8 @@ win2unixfn(struct mbnambuf *nbp, struct cp += 2; } *np = '\0'; - mbnambuf_write(nbp, name, (wep->weCnt & WIN_CNT) - 1); + if (mbnambuf_write(nbp, name, (wep->weCnt & WIN_CNT) - 1) != 0) + return -1; return chksum; } @@ -1005,7 +1012,7 @@ mbnambuf_init(struct mbnambuf *nbp) * This only penalizes portions of substrings that contain more than * WIN_CHARS bytes when they are first encountered. */ -void +int mbnambuf_write(struct mbnambuf *nbp, char *name, int id) { char *slot; @@ -1016,7 +1023,7 @@ mbnambuf_write(struct mbnambuf *nbp, cha printf("msdosfs: non-decreasing id: id %d, last id %d\n", id, nbp->nb_last_id); #endif - return; + return (EINVAL); } /* Will store this substring in a WIN_CHARS-aligned slot. */ @@ -1027,17 +1034,24 @@ mbnambuf_write(struct mbnambuf *nbp, cha #ifdef MSDOSFS_DEBUG printf("msdosfs: file name length %zu too large\n", newlen); #endif - return; + return (ENAMETOOLONG); } /* Shift suffix upwards by the amount length exceeds WIN_CHARS. */ - if (count > WIN_CHARS && nbp->nb_len != 0) + if (count > WIN_CHARS && nbp->nb_len != 0) { + if ((id * WIN_CHARS + count + nbp->nb_len) > + sizeof(nbp->nb_buf)) + return (ENAMETOOLONG); + bcopy(slot + WIN_CHARS, slot + count, nbp->nb_len); + } /* Copy in the substring to its slot and update length so far. */ bcopy(name, slot, count); nbp->nb_len = newlen; nbp->nb_last_id = id; + + return (0); } /*