summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Mooney <patrick.f.mooney@gmail.com>2015-05-20 14:43:00 +0000
committerPatrick Mooney <patrick.f.mooney@gmail.com>2015-05-21 13:10:13 +0000
commit9066c328856ca2a6fa5fc26a4c0b1d9e03bce48b (patch)
tree15eeda01749215d058d5fb479dc22c1db42a31c9
parent55768e18b63207acea873dbc6d769b79753553f9 (diff)
downloadillumos-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.c4
-rw-r--r--usr/src/uts/common/fs/hyprlofs/hyprlofs_vnops.c2
-rw-r--r--usr/src/uts/common/fs/lookup.c11
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv_ns.c5
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_server.c4
-rw-r--r--usr/src/uts/common/fs/vfs.c5
-rw-r--r--usr/src/uts/common/fs/vnode.c42
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_dir.c7
-rw-r--r--usr/src/uts/common/io/vscan/vscan_svc.c4
-rw-r--r--usr/src/uts/common/sys/vnode.h5
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.
*/