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
This commit is contained in:
parent
5abde16df3
commit
b91af2a23d
@ -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,
|
||||
|
@ -658,7 +658,9 @@ win2unixfn(struct mbnambuf *nbp, struct winentry *wep, int chksum,
|
||||
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 winentry *wep, int chksum,
|
||||
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 winentry *wep, int chksum,
|
||||
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 winentry *wep, int chksum,
|
||||
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, char *name, int id)
|
||||
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, char *name, int id)
|
||||
#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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user