summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/dev/sdev_vnops.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/dev/sdev_vnops.c')
-rw-r--r--usr/src/uts/common/fs/dev/sdev_vnops.c64
1 files changed, 58 insertions, 6 deletions
diff --git a/usr/src/uts/common/fs/dev/sdev_vnops.c b/usr/src/uts/common/fs/dev/sdev_vnops.c
index 9103a538c1..4cad8b53e8 100644
--- a/usr/src/uts/common/fs/dev/sdev_vnops.c
+++ b/usr/src/uts/common/fs/dev/sdev_vnops.c
@@ -370,11 +370,16 @@ static int
sdev_lookup(struct vnode *dvp, char *nm, struct vnode **vpp,
struct pathname *pnp, int flags, struct vnode *rdir, struct cred *cred)
{
- struct sdev_node *parent;
+ struct sdev_node *parent;
+ int error;
parent = VTOSDEV(dvp);
ASSERT(parent);
+ /* execute access is required to search the directory */
+ if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0)
+ return (error);
+
if (!SDEV_IS_GLOBAL(parent))
return (prof_lookup(dvp, nm, vpp, cred));
return (devname_lookup_func(parent, nm, vpp, cred, NULL, 0));
@@ -414,7 +419,10 @@ sdev_create(struct vnode *dvp, char *nm, struct vattr *vap, vcexcl_t excl,
}
rw_exit(&parent->sdev_dotdot->sdev_contents);
-again:
+ /* execute access is required to search the directory */
+ if ((error = VOP_ACCESS(dvp, VEXEC|VWRITE, 0, cred)) != 0)
+ return (error);
+
/* check existing name */
error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cred);
@@ -526,6 +534,12 @@ sdev_remove(struct vnode *dvp, char *nm, struct cred *cred)
return (ENOTSUP);
}
+ /* execute access is required to search the directory */
+ if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0) {
+ rw_exit(&parent->sdev_contents);
+ return (error);
+ }
+
/* check existence first */
dv = sdev_cache_lookup(parent, nm);
if (dv == NULL) {
@@ -541,6 +555,13 @@ sdev_remove(struct vnode *dvp, char *nm, struct cred *cred)
return (ENOENT);
}
+ /* write access is required to remove an entry */
+ if ((error = VOP_ACCESS(dvp, VWRITE, 0, cred)) != 0) {
+ rw_exit(&parent->sdev_contents);
+ VN_RELE(vp);
+ return (error);
+ }
+
/* the module may record/reject removing a device node */
map = sdev_get_map(parent, 0);
dirops = map ? map->dir_ops : NULL;
@@ -663,7 +684,7 @@ sdev_rename(struct vnode *odvp, char *onm, struct vnode *ndvp, char *nnm,
rw_exit(&toparent->sdev_dotdot->sdev_contents);
/*
- * grabbing the global lock to prevent
+ * acquire the global lock to prevent
* mount/unmount/other rename activities.
*/
mutex_enter(&sdev_lock);
@@ -885,6 +906,10 @@ sdev_symlink(struct vnode *dvp, char *lnm, struct vattr *tva,
}
rw_exit(&parent->sdev_dotdot->sdev_contents);
+ /* execute access is required to search a directory */
+ if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0)
+ return (error);
+
/* find existing name */
error = VOP_LOOKUP(dvp, lnm, &vp, NULL, 0, NULL, cred);
if (error == 0) {
@@ -893,10 +918,12 @@ sdev_symlink(struct vnode *dvp, char *lnm, struct vattr *tva,
sdcmn_err2(("sdev_symlink: node %s already exists\n", lnm));
return (EEXIST);
}
+ if (error != ENOENT)
+ return (error);
- if (error != ENOENT) {
+ /* write access is required to create a symlink */
+ if ((error = VOP_ACCESS(dvp, VWRITE, 0, cred)) != 0)
return (error);
- }
/* put it into memory cache */
rw_enter(&parent->sdev_contents, RW_WRITER);
@@ -951,16 +978,25 @@ sdev_mkdir(struct vnode *dvp, char *nm, struct vattr *va, struct vnode **vpp,
}
rw_exit(&parent->sdev_dotdot->sdev_contents);
+ /* execute access is required to search the directory */
+ if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0) {
+ return (error);
+ }
+
/* find existing name */
error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cred);
if (error == 0) {
VN_RELE(vp);
return (EEXIST);
}
-
if (error != ENOENT)
return (error);
+ /* require write access to create a directory */
+ if ((error = VOP_ACCESS(dvp, VWRITE, 0, cred)) != 0) {
+ return (error);
+ }
+
/* put it into memory */
rw_enter(&parent->sdev_contents, RW_WRITER);
error = sdev_mknode(parent, nm, &self,
@@ -1016,6 +1052,10 @@ sdev_rmdir(struct vnode *dvp, char *nm, struct vnode *cdir, struct cred *cred)
}
rw_exit(&parent->sdev_dotdot->sdev_contents);
+ /* execute access is required to search the directory */
+ if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0)
+ return (error);
+
/* check existing name */
rw_enter(&parent->sdev_contents, RW_WRITER);
self = sdev_cache_lookup(parent, nm);
@@ -1032,6 +1072,13 @@ sdev_rmdir(struct vnode *dvp, char *nm, struct vnode *cdir, struct cred *cred)
return (ENOENT);
}
+ /* write access is required to remove a directory */
+ if ((error = VOP_ACCESS(dvp, VWRITE, 0, cred)) != 0) {
+ rw_exit(&parent->sdev_contents);
+ VN_RELE(vp);
+ return (error);
+ }
+
/* some sanity checks */
if (vp == dvp || vp == cdir) {
rw_exit(&parent->sdev_contents);
@@ -1130,6 +1177,11 @@ static int
sdev_readdir(struct vnode *dvp, struct uio *uiop, struct cred *cred, int *eofp)
{
struct sdev_node *parent = VTOSDEV(dvp);
+ int error;
+
+ /* execute access is required to search the directory */
+ if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0)
+ return (error);
ASSERT(parent);
if (!SDEV_IS_GLOBAL(parent))