Fix bug that would result in a kernel crash in some cases involving

a symlink and an autofs mount request.  The crash was caused by namei()
calling bcopy() with a negative length, caused by numeric underflow:
in lookup(), in the relookup path, the ni_pathlen was decremented too
many times.  The bug was introduced in r296715.

Big thanks to Alex Deiter for his help with debugging this.

Reviewed by:	kib@
Tested by:	Alex Deiter <alex.deiter at gmail.com>
MFC after:	1 month
This commit is contained in:
Edward Tomasz Napierala 2017-01-04 14:43:57 +00:00
parent 3a408ce90d
commit 5ec7cde488
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=311284

View File

@ -621,11 +621,13 @@ needs_exclusive_leaf(struct mount *mp, int flags)
int
lookup(struct nameidata *ndp)
{
char *cp; /* pointer into pathname argument */
char *cp; /* pointer into pathname argument */
char *prev_ni_next; /* saved ndp->ni_next */
struct vnode *dp = NULL; /* the directory we are searching */
struct vnode *tdp; /* saved dp */
struct mount *mp; /* mount table entry */
struct prison *pr;
size_t prev_ni_pathlen; /* saved ndp->ni_pathlen */
int docache; /* == 0 do not cache last component */
int wantparent; /* 1 => wantparent or lockparent flag */
int rdonly; /* lookup read-only flag bit */
@ -687,7 +689,11 @@ lookup(struct nameidata *ndp)
printf("{%s}: ", cnp->cn_nameptr);
*cp = c; }
#endif
prev_ni_pathlen = ndp->ni_pathlen;
ndp->ni_pathlen -= cnp->cn_namelen;
KASSERT(ndp->ni_pathlen <= PATH_MAX,
("%s: ni_pathlen underflow to %zd\n", __func__, ndp->ni_pathlen));
prev_ni_next = ndp->ni_next;
ndp->ni_next = cp;
/*
@ -1008,6 +1014,8 @@ lookup(struct nameidata *ndp)
("lookup: invalid path state."));
if (relookup) {
relookup = 0;
ndp->ni_pathlen = prev_ni_pathlen;
ndp->ni_next = prev_ni_next;
if (ndp->ni_dvp != dp)
vput(ndp->ni_dvp);
else