diff options
author | Patrick Mooney <patrick.f.mooney@gmail.com> | 2015-05-20 14:43:00 +0000 |
---|---|---|
committer | Patrick Mooney <patrick.f.mooney@gmail.com> | 2015-05-21 13:10:13 +0000 |
commit | 9066c328856ca2a6fa5fc26a4c0b1d9e03bce48b (patch) | |
tree | 15eeda01749215d058d5fb479dc22c1db42a31c9 | |
parent | 55768e18b63207acea873dbc6d769b79753553f9 (diff) | |
download | illumos-joyent-9066c328856ca2a6fa5fc26a4c0b1d9e03bce48b.tar.gz |
OS-4317 v_path accesses can race
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r-- | usr/src/uts/common/dtrace/dtrace.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/fs/hyprlofs/hyprlofs_vnops.c | 2 | ||||
-rw-r--r-- | usr/src/uts/common/fs/lookup.c | 11 | ||||
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs4_srv_ns.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs_server.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/fs/vfs.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/fs/vnode.c | 42 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_dir.c | 7 | ||||
-rw-r--r-- | usr/src/uts/common/io/vscan/vscan_svc.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/sys/vnode.h | 5 |
10 files changed, 51 insertions, 38 deletions
diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c index 8c741a7d06..1a7876ca57 100644 --- a/usr/src/uts/common/dtrace/dtrace.c +++ b/usr/src/uts/common/dtrace/dtrace.c @@ -785,8 +785,8 @@ dtrace_canload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, if (DTRACE_INRANGE(addr, sz, &vp->v_path, psz)) return (1); - if (vp->v_path != NULL && DTRACE_INRANGE(addr, sz, - vp->v_path, strlen(vp->v_path) + 1)) { + if (DTRACE_INRANGE(addr, sz, vp->v_path, + strlen(vp->v_path) + 1)) { return (1); } diff --git a/usr/src/uts/common/fs/hyprlofs/hyprlofs_vnops.c b/usr/src/uts/common/fs/hyprlofs/hyprlofs_vnops.c index 2ca44a841d..a2064dfa1f 100644 --- a/usr/src/uts/common/fs/hyprlofs/hyprlofs_vnops.c +++ b/usr/src/uts/common/fs/hyprlofs/hyprlofs_vnops.c @@ -867,7 +867,7 @@ hyprlofs_get_all_entries(vnode_t *dvp, hyprlofs_curr_entry_t *hcp, } tvp = REALVP(HLNTOV(fndhp)); - if (tvp->v_path == NULL) { + if (tvp->v_path == vn_vpath_empty) { p = "<unknown>"; } else { p = tvp->v_path; diff --git a/usr/src/uts/common/fs/lookup.c b/usr/src/uts/common/fs/lookup.c index 2fd2bbeb0b..59ec5d1829 100644 --- a/usr/src/uts/common/fs/lookup.c +++ b/usr/src/uts/common/fs/lookup.c @@ -986,8 +986,8 @@ static void vnode_clear_vpath(vnode_t *vp, char *vpath_old) { mutex_enter(&vp->v_lock); - if (vp->v_path != NULL && vp->v_path == vpath_old) { - vp->v_path = NULL; + if (vp->v_path != vn_vpath_empty && vp->v_path == vpath_old) { + vp->v_path = vn_vpath_empty; mutex_exit(&vp->v_lock); kmem_free(vpath_old, strlen(vpath_old) + 1); } else { @@ -1185,7 +1185,7 @@ dirtopath(vnode_t *vrootp, vnode_t *vp, char *buf, size_t buflen, int flags, vpath_cached = NULL; vpath_stale = B_FALSE; mutex_enter(&vp->v_lock); - if ((vp->v_path != NULL) && + if (vp->v_path != vn_vpath_empty && pn_set(&pn, vp->v_path) == 0) { vpath_cached = vp->v_path; mutex_exit(&vp->v_lock); @@ -1266,8 +1266,9 @@ dirtopath(vnode_t *vrootp, vnode_t *vp, char *buf, size_t buflen, int flags, *--bufloc = '/'; /* Clear vp->v_path if it was found to be stale. */ - if (vpath_stale == B_TRUE) + if (vpath_stale == B_TRUE) { vnode_clear_vpath(vp, vpath_cached); + } /* And continue with the next component */ VN_RELE(vp); @@ -1366,7 +1367,7 @@ vnodetopath_common(vnode_t *vrootp, vnode_t *vp, char *buf, size_t buflen, */ pn_alloc(&pn); mutex_enter(&vp->v_lock); - if (vp->v_path != NULL) { + if (vp->v_path != vn_vpath_empty) { (void) pn_set(&pn, vp->v_path); mutex_exit(&vp->v_lock); diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c b/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c index ce0c9485a6..3ee41939ac 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c +++ b/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c @@ -22,6 +22,7 @@ /* * Copyright 2014 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. */ #include <sys/systm.h> @@ -178,12 +179,12 @@ pseudo_exportfs(vnode_t *vp, fid_t *fid, struct exp_visible *vis_head, kex = &exi->exi_export; kex->ex_flags = EX_PSEUDO; - vpathlen = vp->v_path ? strlen(vp->v_path) : 0; + vpathlen = strlen(vp->v_path); kex->ex_pathlen = vpathlen + strlen(PSEUDOFS_SUFFIX); kex->ex_path = kmem_alloc(kex->ex_pathlen + 1, KM_SLEEP); if (vpathlen) - (void) strcpy(kex->ex_path, vp->v_path); + (void) strncpy(kex->ex_path, vp->v_path, vpathlen); (void) strcpy(kex->ex_path + vpathlen, PSEUDOFS_SUFFIX); /* Transfer the secinfo data from exdata to this new pseudo node */ diff --git a/usr/src/uts/common/fs/nfs/nfs_server.c b/usr/src/uts/common/fs/nfs/nfs_server.c index 93ccd28122..dcc64def59 100644 --- a/usr/src/uts/common/fs/nfs/nfs_server.c +++ b/usr/src/uts/common/fs/nfs/nfs_server.c @@ -23,7 +23,7 @@ * Copyright (c) 2011 Bayard G. Bell. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2014 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2012 Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. */ /* @@ -3212,7 +3212,7 @@ nfs_getflabel(vnode_t *vp, struct exportinfo *exi) char *path; mutex_enter(&vp->v_lock); - if (vp->v_path != NULL) { + if (vp->v_path != vn_vpath_empty) { zone = zone_find_by_any_path(vp->v_path, B_FALSE); mutex_exit(&vp->v_lock); } else { diff --git a/usr/src/uts/common/fs/vfs.c b/usr/src/uts/common/fs/vfs.c index 3f14df9add..b680b1168c 100644 --- a/usr/src/uts/common/fs/vfs.c +++ b/usr/src/uts/common/fs/vfs.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -235,7 +235,8 @@ fsop_root(vfs_t *vfsp, vnode_t **vpp) * Make sure this root has a path. With lofs, it is possible to have * a NULL mountpoint. */ - if (ret == 0 && vfsp->vfs_mntpt != NULL && (*vpp)->v_path == NULL) { + if (ret == 0 && vfsp->vfs_mntpt != NULL && + (*vpp)->v_path == vn_vpath_empty) { mntpt = vfs_getmntpoint(vfsp); vn_setpath_str(*vpp, refstr_value(mntpt), strlen(refstr_value(mntpt))); diff --git a/usr/src/uts/common/fs/vnode.c b/usr/src/uts/common/fs/vnode.c index 561fb1bd02..9fb1ea702a 100644 --- a/usr/src/uts/common/fs/vnode.c +++ b/usr/src/uts/common/fs/vnode.c @@ -21,7 +21,7 @@ /* * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -103,6 +103,9 @@ kmutex_t vskstat_tree_lock; /* Global variable which enables/disables the vopstats collection */ int vopstats_enabled = 1; +/* Global used for empty/invalid v_path */ +char *vn_vpath_empty = ""; + /* * forward declarations for internal vnode specific data (vsd) */ @@ -2290,7 +2293,7 @@ vn_cache_constructor(void *buf, void *cdrarg, int kmflags) cv_init(&vp->v_cv, NULL, CV_DEFAULT, NULL); rw_init(&vp->v_nbllock, NULL, RW_DEFAULT, NULL); vp->v_femhead = NULL; /* Must be done before vn_reinit() */ - vp->v_path = NULL; + vp->v_path = vn_vpath_empty; vp->v_mpssdata = NULL; vp->v_vsd = NULL; vp->v_fopdata = NULL; @@ -2337,6 +2340,7 @@ void vn_recycle(vnode_t *vp) { ASSERT(vp->v_pages == NULL); + VERIFY(vp->v_path != NULL); /* * XXX - This really belongs in vn_reinit(), but we have some issues @@ -2359,9 +2363,9 @@ vn_recycle(vnode_t *vp) kmem_free(vp->v_femhead, sizeof (*(vp->v_femhead))); vp->v_femhead = NULL; } - if (vp->v_path) { + if (vp->v_path != vn_vpath_empty) { kmem_free(vp->v_path, strlen(vp->v_path) + 1); - vp->v_path = NULL; + vp->v_path = vn_vpath_empty; } if (vp->v_fopdata != NULL) { @@ -2433,9 +2437,10 @@ vn_free(vnode_t *vp) */ ASSERT((vp->v_count == 0) || (vp->v_count == 1)); ASSERT(vp->v_count_dnlc == 0); - if (vp->v_path != NULL) { + VERIFY(vp->v_path != NULL); + if (vp->v_path != vn_vpath_empty) { kmem_free(vp->v_path, strlen(vp->v_path) + 1); - vp->v_path = NULL; + vp->v_path = vn_vpath_empty; } /* If FEM was in use, make sure everything gets cleaned up */ @@ -2959,7 +2964,7 @@ vn_setpath(vnode_t *rootvp, struct vnode *startvp, struct vnode *vp, * the potential for deadlock. */ mutex_enter(&base->v_lock); - if (base->v_path == NULL) { + if (base->v_path == vn_vpath_empty) { mutex_exit(&base->v_lock); return; } @@ -2986,7 +2991,8 @@ vn_setpath(vnode_t *rootvp, struct vnode *startvp, struct vnode *vp, rpath = kmem_alloc(rpathalloc, KM_SLEEP); mutex_enter(&base->v_lock); - if (base->v_path == NULL || strlen(base->v_path) != rpathlen) { + if (base->v_path == vn_vpath_empty || + strlen(base->v_path) != rpathlen) { mutex_exit(&base->v_lock); kmem_free(rpath, rpathalloc); return; @@ -3000,7 +3006,7 @@ vn_setpath(vnode_t *rootvp, struct vnode *startvp, struct vnode *vp, rpath[rpathlen + plen] = '\0'; mutex_enter(&vp->v_lock); - if (vp->v_path != NULL) { + if (vp->v_path != vn_vpath_empty) { mutex_exit(&vp->v_lock); kmem_free(rpath, rpathalloc); } else { @@ -3020,7 +3026,7 @@ vn_setpath_str(struct vnode *vp, const char *str, size_t len) char *buf = kmem_alloc(len + 1, KM_SLEEP); mutex_enter(&vp->v_lock); - if (vp->v_path != NULL) { + if (vp->v_path != vn_vpath_empty) { mutex_exit(&vp->v_lock); kmem_free(buf, len + 1); return; @@ -3044,10 +3050,10 @@ vn_renamepath(vnode_t *dvp, vnode_t *vp, const char *nm, size_t len) mutex_enter(&vp->v_lock); tmp = vp->v_path; - vp->v_path = NULL; + vp->v_path = vn_vpath_empty; mutex_exit(&vp->v_lock); vn_setpath(rootdir, dvp, vp, nm, len); - if (tmp != NULL) + if (tmp != vn_vpath_empty) kmem_free(tmp, strlen(tmp) + 1); } @@ -3062,7 +3068,7 @@ vn_copypath(struct vnode *src, struct vnode *dst) int alloc; mutex_enter(&src->v_lock); - if (src->v_path == NULL) { + if (src->v_path == vn_vpath_empty) { mutex_exit(&src->v_lock); return; } @@ -3072,7 +3078,7 @@ vn_copypath(struct vnode *src, struct vnode *dst) mutex_exit(&src->v_lock); buf = kmem_alloc(alloc, KM_SLEEP); mutex_enter(&src->v_lock); - if (src->v_path == NULL || strlen(src->v_path) + 1 != alloc) { + if (src->v_path == vn_vpath_empty || strlen(src->v_path) + 1 != alloc) { mutex_exit(&src->v_lock); kmem_free(buf, alloc); return; @@ -3081,7 +3087,7 @@ vn_copypath(struct vnode *src, struct vnode *dst) mutex_exit(&src->v_lock); mutex_enter(&dst->v_lock); - if (dst->v_path != NULL) { + if (dst->v_path != vn_vpath_empty) { mutex_exit(&dst->v_lock); kmem_free(buf, alloc); return; @@ -3520,7 +3526,7 @@ fop_lookup( } if (ret == 0 && *vpp) { VOPSTATS_UPDATE(*vpp, lookup); - if ((*vpp)->v_path == NULL) { + if ((*vpp)->v_path == vn_vpath_empty) { vn_setpath(rootdir, dvp, *vpp, nm, strlen(nm)); } } @@ -3562,7 +3568,7 @@ fop_create( (dvp, name, vap, excl, mode, vpp, cr, flags, ct, vsecp); if (ret == 0 && *vpp) { VOPSTATS_UPDATE(*vpp, create); - if ((*vpp)->v_path == NULL) { + if ((*vpp)->v_path == vn_vpath_empty) { vn_setpath(rootdir, dvp, *vpp, name, strlen(name)); } } @@ -3684,7 +3690,7 @@ fop_mkdir( (dvp, dirname, vap, vpp, cr, ct, flags, vsecp); if (ret == 0 && *vpp) { VOPSTATS_UPDATE(*vpp, mkdir); - if ((*vpp)->v_path == NULL) { + if ((*vpp)->v_path == vn_vpath_empty) { vn_setpath(rootdir, dvp, *vpp, dirname, strlen(dirname)); } diff --git a/usr/src/uts/common/fs/zfs/zfs_dir.c b/usr/src/uts/common/fs/zfs/zfs_dir.c index bd7424b55b..2adb297937 100644 --- a/usr/src/uts/common/fs/zfs/zfs_dir.c +++ b/usr/src/uts/common/fs/zfs/zfs_dir.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2014 by Delphix. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. */ #include <sys/types.h> @@ -847,9 +848,9 @@ zfs_link_destroy(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag, if (zp->z_links <= zp_is_dir) { zfs_panic_recover("zfs: link count on %s is %u, " "should be at least %u", - zp->z_vnode->v_path ? zp->z_vnode->v_path : - "<unknown>", (int)zp->z_links, - zp_is_dir + 1); + zp->z_vnode->v_path != vn_vpath_empty ? + zp->z_vnode->v_path : "<unknown>", + (int)zp->z_links, zp_is_dir + 1); zp->z_links = zp_is_dir + 1; } if (--zp->z_links == zp_is_dir) { diff --git a/usr/src/uts/common/io/vscan/vscan_svc.c b/usr/src/uts/common/io/vscan/vscan_svc.c index e26fa9e292..b5efbb3a99 100644 --- a/usr/src/uts/common/io/vscan/vscan_svc.c +++ b/usr/src/uts/common/io/vscan/vscan_svc.c @@ -22,6 +22,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2015, Joyent, Inc. */ #include <sys/stat.h> @@ -461,7 +462,7 @@ vscan_svc_scan_file(vnode_t *vp, cred_t *cr, int async) boolean_t allow; clock_t timeout, time_left; - if ((vp == NULL) || (vp->v_path == NULL) || cr == NULL) + if ((vp == NULL) || (vp->v_path == vn_vpath_empty) || cr == NULL) return (0); DTRACE_PROBE2(vscan__scan__file, char *, vp->v_path, int, async); @@ -1080,7 +1081,6 @@ vscan_svc_exempt_file(vnode_t *vp, boolean_t *allow) struct vattr attr; ASSERT(vp != NULL); - ASSERT(vp->v_path != NULL); attr.va_mask = AT_SIZE; diff --git a/usr/src/uts/common/sys/vnode.h b/usr/src/uts/common/sys/vnode.h index c1c12a084e..28145636f3 100644 --- a/usr/src/uts/common/sys/vnode.h +++ b/usr/src/uts/common/sys/vnode.h @@ -21,7 +21,7 @@ /* * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -1325,6 +1325,9 @@ u_longlong_t fs_new_caller_id(); int vn_vmpss_usepageio(vnode_t *); +/* Empty v_path placeholder */ +extern char *vn_vpath_empty; + /* * Needed for use of IS_VMODSORT() in kernel. */ |