summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_syscalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r--sys/kern/vfs_syscalls.c63
1 files changed, 54 insertions, 9 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index a6c9887..79abaf4 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -3681,20 +3681,65 @@ extattrctl(p, uap)
struct proc *p;
struct extattrctl_args *uap;
{
+ struct vnode *filename_vp;
struct nameidata nd;
struct mount *mp;
+ char attrname[EXTATTR_MAXNAMELEN];
int error;
+ /*
+ * SCARG(uap, attrname) not always defined. We check again later
+ * when we invoke the VFS call so as to pass in NULL there if needed.
+ */
+ if (SCARG(uap, attrname) != NULL) {
+ error = copyinstr(SCARG(uap, attrname), attrname,
+ EXTATTR_MAXNAMELEN, NULL);
+ if (error)
+ return (error);
+ }
+
+ /*
+ * SCARG(uap, filename) not always defined. If it is, grab
+ * a vnode lock, which VFS_EXTATTRCTL() will later release.
+ */
+ filename_vp = NULL;
+ if (SCARG(uap, filename) != NULL) {
+ NDINIT(&nd, LOOKUP | LOCKLEAF, FOLLOW, UIO_USERSPACE,
+ SCARG(uap, filename), p);
+ if ((error = namei(&nd)) != 0)
+ return (error);
+ filename_vp = nd.ni_vp;
+ NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
+ }
+
+ /* SCARG(uap, path) always defined. */
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
if ((error = namei(&nd)) != 0)
return (error);
error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
NDFREE(&nd, 0);
- if (error)
+ if (error) {
+ if (filename_vp)
+ vrele(filename_vp);
return (error);
- error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), SCARG(uap, attrname),
- SCARG(uap, arg), p);
+ }
+
+ if (SCARG(uap, attrname) != NULL) {
+ error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp,
+ SCARG(uap, namespace), attrname, p);
+ } else {
+ error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp,
+ SCARG(uap, namespace), NULL, p);
+ }
+
vn_finished_write(mp);
+ /*
+ * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
+ * filename_vp, so vrele it if it is defined.
+ */
+ if (filename_vp != NULL)
+ vrele(filename_vp);
+
return (error);
}
@@ -3756,8 +3801,8 @@ extattr_set_file(p, uap)
iov++;
}
cnt = auio.uio_resid;
- error = VOP_SETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred,
- p);
+ error = VOP_SETEXTATTR(nd.ni_vp, SCARG(uap, namespace), attrname,
+ &auio, p->p_cred->pc_ucred, p);
cnt -= auio.uio_resid;
p->p_retval[0] = cnt;
done:
@@ -3823,8 +3868,8 @@ extattr_get_file(p, uap)
iov++;
}
cnt = auio.uio_resid;
- error = VOP_GETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred,
- p);
+ error = VOP_GETEXTATTR(nd.ni_vp, SCARG(uap, namespace), attrname,
+ &auio, p->p_cred->pc_ucred, p);
cnt -= auio.uio_resid;
p->p_retval[0] = cnt;
done:
@@ -3859,8 +3904,8 @@ extattr_delete_file(p, uap)
NDFREE(&nd, 0);
return (error);
}
- error = VOP_SETEXTATTR(nd.ni_vp, attrname, NULL, p->p_cred->pc_ucred,
- p);
+ error = VOP_SETEXTATTR(nd.ni_vp, SCARG(uap, namespace), attrname,
+ NULL, p->p_cred->pc_ucred, p);
NDFREE(&nd, 0);
vn_finished_write(mp);
return(error);
OpenPOWER on IntegriCloud