mirror of
https://github.com/opnsense/src.git
synced 2026-04-29 01:59:38 -04:00
vfs: add NDREINIT to facilitate repeated namei calls
struct nameidata mixes caller arguments, internal state and output, which can be quite error prone. Recent addition of valdiating ni_resflags uncovered a caller which could repeatedly call namei, effectively operating on partially populated state. Add bare minimium validation this does not happen. The real fix would decouple aforementioned state. Reported by: pho Tested by: pho (different variant)
This commit is contained in:
parent
ac04cf18bb
commit
eebc2e450f
3 changed files with 37 additions and 1 deletions
|
|
@ -502,6 +502,11 @@ namei(struct nameidata *ndp)
|
|||
cnp = &ndp->ni_cnd;
|
||||
td = cnp->cn_thread;
|
||||
#ifdef INVARIANTS
|
||||
KASSERT((ndp->ni_debugflags & NAMEI_DBG_CALLED) == 0,
|
||||
("%s: repeated call to namei without NDREINIT", __func__));
|
||||
KASSERT(ndp->ni_debugflags == NAMEI_DBG_INITED,
|
||||
("%s: bad debugflags %d", __func__, ndp->ni_debugflags));
|
||||
ndp->ni_debugflags |= NAMEI_DBG_CALLED;
|
||||
/*
|
||||
* For NDVALIDATE.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@ restart:
|
|||
if ((error = vn_start_write(NULL, &mp,
|
||||
V_XSLEEP | PCATCH)) != 0)
|
||||
return (error);
|
||||
NDREINIT(ndp);
|
||||
goto restart;
|
||||
}
|
||||
if ((vn_open_flags & VN_OPEN_NAMECACHE) != 0)
|
||||
|
|
|
|||
|
|
@ -94,12 +94,16 @@ struct nameidata {
|
|||
* Results: flags returned from namei
|
||||
*/
|
||||
u_int ni_resflags;
|
||||
/*
|
||||
* Debug for validating API use by the callers.
|
||||
*/
|
||||
u_short ni_debugflags;
|
||||
/*
|
||||
* Shared between namei and lookup/commit routines.
|
||||
*/
|
||||
u_short ni_loopcnt; /* count of symlinks encountered */
|
||||
size_t ni_pathlen; /* remaining chars in path */
|
||||
char *ni_next; /* next location in pathname */
|
||||
u_int ni_loopcnt; /* count of symlinks encountered */
|
||||
/*
|
||||
* Lookup parameters: this structure describes the subset of
|
||||
* information from the nameidata structure that is passed
|
||||
|
|
@ -122,6 +126,14 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status,
|
|||
*
|
||||
* If modifying the list make sure to check whether NDVALIDATE needs updating.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Debug.
|
||||
*/
|
||||
#define NAMEI_DBG_INITED 0x0001
|
||||
#define NAMEI_DBG_CALLED 0x0002
|
||||
#define NAMEI_DBG_HADSTARTDIR 0x0004
|
||||
|
||||
/*
|
||||
* namei operational modifier flags, stored in ni_cnd.flags
|
||||
*/
|
||||
|
|
@ -215,8 +227,18 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status,
|
|||
*/
|
||||
#ifdef INVARIANTS
|
||||
#define NDINIT_PREFILL(arg) memset(arg, 0xff, sizeof(*arg))
|
||||
#define NDINIT_DBG(arg) { (arg)->ni_debugflags = NAMEI_DBG_INITED; }
|
||||
#define NDREINIT_DBG(arg) { \
|
||||
if (((arg)->ni_debugflags & NAMEI_DBG_INITED) == 0) \
|
||||
panic("namei data not inited"); \
|
||||
if (((arg)->ni_debugflags & NAMEI_DBG_HADSTARTDIR) != 0) \
|
||||
panic("NDREINIT on namei data with NAMEI_DBG_HADSTARTDIR"); \
|
||||
(arg)->ni_debugflags = NAMEI_DBG_INITED; \
|
||||
}
|
||||
#else
|
||||
#define NDINIT_PREFILL(arg) do { } while (0)
|
||||
#define NDINIT_DBG(arg) do { } while (0)
|
||||
#define NDREINIT_DBG(arg) do { } while (0)
|
||||
#endif
|
||||
|
||||
#define NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, startdir, rightsp, td) \
|
||||
|
|
@ -225,6 +247,7 @@ do { \
|
|||
cap_rights_t *_rightsp = (rightsp); \
|
||||
MPASS(_rightsp != NULL); \
|
||||
NDINIT_PREFILL(_ndp); \
|
||||
NDINIT_DBG(_ndp); \
|
||||
_ndp->ni_cnd.cn_nameiop = op; \
|
||||
_ndp->ni_cnd.cn_flags = flags; \
|
||||
_ndp->ni_segflg = segflg; \
|
||||
|
|
@ -237,6 +260,13 @@ do { \
|
|||
_ndp->ni_rightsneeded = _rightsp; \
|
||||
} while (0)
|
||||
|
||||
#define NDREINIT(ndp) do { \
|
||||
struct nameidata *_ndp = (ndp); \
|
||||
NDREINIT_DBG(_ndp); \
|
||||
_ndp->ni_resflags = 0; \
|
||||
_ndp->ni_startdir = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define NDF_NO_DVP_RELE 0x00000001
|
||||
#define NDF_NO_DVP_UNLOCK 0x00000002
|
||||
#define NDF_NO_DVP_PUT 0x00000003
|
||||
|
|
|
|||
Loading…
Reference in a new issue