mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-21 11:13:30 +00:00
Verify that '..' still exists with the same inode number after
VFS_VGET() has returned in ufs_lookup(). If the '..' lookup started immediately before the parent directory was removed, we might return either cleared or unrelated inode otherwise. Ufs_lookup() is split into new function ufs_lookup_() that either does lookup, or verifies that directory entry exists and references supplied inode number. Reviewed by: tegge Tested by: pho, Andreas Tobler <andreast-list fgznet ch> (previous version) MFC after: 1 month
This commit is contained in:
parent
28a1b4eb37
commit
71421dc116
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=191137
@ -77,6 +77,9 @@ SYSCTL_INT(_debug, OID_AUTO, dircheck, CTLFLAG_RW, &dirchk, 0, "");
|
|||||||
/* true if old FS format...*/
|
/* true if old FS format...*/
|
||||||
#define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0)
|
#define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0)
|
||||||
|
|
||||||
|
static int ufs_lookup_(struct vnode *, struct vnode **, struct componentname *,
|
||||||
|
ino_t);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert a component of a pathname into a pointer to a locked inode.
|
* Convert a component of a pathname into a pointer to a locked inode.
|
||||||
* This is a very central and rather complicated routine.
|
* This is a very central and rather complicated routine.
|
||||||
@ -130,7 +133,14 @@ ufs_lookup(ap)
|
|||||||
struct componentname *a_cnp;
|
struct componentname *a_cnp;
|
||||||
} */ *ap;
|
} */ *ap;
|
||||||
{
|
{
|
||||||
struct vnode *vdp; /* vnode for directory being searched */
|
|
||||||
|
return (ufs_lookup_(ap->a_dvp, ap->a_vpp, ap->a_cnp, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ufs_lookup_(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp,
|
||||||
|
ino_t dd_ino)
|
||||||
|
{
|
||||||
struct inode *dp; /* inode for directory being searched */
|
struct inode *dp; /* inode for directory being searched */
|
||||||
struct buf *bp; /* a buffer of directory entries */
|
struct buf *bp; /* a buffer of directory entries */
|
||||||
struct direct *ep; /* the current directory entry */
|
struct direct *ep; /* the current directory entry */
|
||||||
@ -150,8 +160,6 @@ ufs_lookup(ap)
|
|||||||
doff_t enduseful; /* pointer past last used dir slot */
|
doff_t enduseful; /* pointer past last used dir slot */
|
||||||
u_long bmask; /* block offset mask */
|
u_long bmask; /* block offset mask */
|
||||||
int namlen, error;
|
int namlen, error;
|
||||||
struct vnode **vpp = ap->a_vpp;
|
|
||||||
struct componentname *cnp = ap->a_cnp;
|
|
||||||
struct ucred *cred = cnp->cn_cred;
|
struct ucred *cred = cnp->cn_cred;
|
||||||
int flags = cnp->cn_flags;
|
int flags = cnp->cn_flags;
|
||||||
int nameiop = cnp->cn_nameiop;
|
int nameiop = cnp->cn_nameiop;
|
||||||
@ -164,9 +172,9 @@ ufs_lookup(ap)
|
|||||||
* XXX there was a soft-update diff about this I couldn't merge.
|
* XXX there was a soft-update diff about this I couldn't merge.
|
||||||
* I think this was the equiv.
|
* I think this was the equiv.
|
||||||
*/
|
*/
|
||||||
*vpp = NULL;
|
if (vpp != NULL)
|
||||||
|
*vpp = NULL;
|
||||||
|
|
||||||
vdp = ap->a_dvp;
|
|
||||||
dp = VTOI(vdp);
|
dp = VTOI(vdp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -363,7 +371,7 @@ ufs_lookup(ap)
|
|||||||
slotoffset = i_offset;
|
slotoffset = i_offset;
|
||||||
slotsize = ep->d_reclen;
|
slotsize = ep->d_reclen;
|
||||||
enduseful = dp->i_size;
|
enduseful = dp->i_size;
|
||||||
ap->a_cnp->cn_flags |= ISWHITEOUT;
|
cnp->cn_flags |= ISWHITEOUT;
|
||||||
numdirpasses--;
|
numdirpasses--;
|
||||||
goto notfound;
|
goto notfound;
|
||||||
}
|
}
|
||||||
@ -397,8 +405,8 @@ ufs_lookup(ap)
|
|||||||
*/
|
*/
|
||||||
if ((nameiop == CREATE || nameiop == RENAME ||
|
if ((nameiop == CREATE || nameiop == RENAME ||
|
||||||
(nameiop == DELETE &&
|
(nameiop == DELETE &&
|
||||||
(ap->a_cnp->cn_flags & DOWHITEOUT) &&
|
(cnp->cn_flags & DOWHITEOUT) &&
|
||||||
(ap->a_cnp->cn_flags & ISWHITEOUT))) &&
|
(cnp->cn_flags & ISWHITEOUT))) &&
|
||||||
(flags & ISLASTCN) && dp->i_effnlink != 0) {
|
(flags & ISLASTCN) && dp->i_effnlink != 0) {
|
||||||
/*
|
/*
|
||||||
* Access for write is interpreted as allowing
|
* Access for write is interpreted as allowing
|
||||||
@ -453,7 +461,7 @@ ufs_lookup(ap)
|
|||||||
* Insert name into cache (as non-existent) if appropriate.
|
* Insert name into cache (as non-existent) if appropriate.
|
||||||
*/
|
*/
|
||||||
if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
|
if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
|
||||||
cache_enter(vdp, *vpp, cnp);
|
cache_enter(vdp, NULL, cnp);
|
||||||
return (ENOENT);
|
return (ENOENT);
|
||||||
|
|
||||||
found:
|
found:
|
||||||
@ -479,6 +487,12 @@ ufs_lookup(ap)
|
|||||||
if ((flags & ISLASTCN) && nameiop == LOOKUP)
|
if ((flags & ISLASTCN) && nameiop == LOOKUP)
|
||||||
dp->i_diroff = i_offset &~ (DIRBLKSIZ - 1);
|
dp->i_diroff = i_offset &~ (DIRBLKSIZ - 1);
|
||||||
|
|
||||||
|
if (dd_ino != 0) {
|
||||||
|
if (ino != dd_ino)
|
||||||
|
return (ENOENT);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If deleting, and at end of pathname, return
|
* If deleting, and at end of pathname, return
|
||||||
* parameters which can be used to remove file.
|
* parameters which can be used to remove file.
|
||||||
@ -580,6 +594,18 @@ ufs_lookup(ap)
|
|||||||
error = vn_vget_ino(pdp, ino, cnp->cn_lkflags, &tdp);
|
error = vn_vget_ino(pdp, ino, cnp->cn_lkflags, &tdp);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recheck that ".." entry in the vdp directory points
|
||||||
|
* to the inode we looked up before vdp lock was
|
||||||
|
* dropped.
|
||||||
|
*/
|
||||||
|
error = ufs_lookup_(pdp, NULL, cnp, ino);
|
||||||
|
if (error) {
|
||||||
|
vput(tdp);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
*vpp = tdp;
|
*vpp = tdp;
|
||||||
} else if (dp->i_number == ino) {
|
} else if (dp->i_number == ino) {
|
||||||
VREF(vdp); /* we want ourself, ie "." */
|
VREF(vdp); /* we want ourself, ie "." */
|
||||||
|
Loading…
Reference in New Issue
Block a user