diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/syscalls.master | 13 | ||||
-rw-r--r-- | sys/kern/vfs_default.c | 5 | ||||
-rw-r--r-- | sys/kern/vfs_extattr.c | 63 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 63 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 17 | ||||
-rw-r--r-- | sys/kern/vnode_if.src | 2 |
6 files changed, 129 insertions, 34 deletions
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 2c54df2..6e834d4 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -508,15 +508,16 @@ 354 STD BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \ struct acl *aclp); } 355 STD BSD { int extattrctl(const char *path, int cmd, \ - const char *attrname, char *arg); } + const char *filename, int namespace, \ + const char *attrname); } 356 STD BSD { int extattr_set_file(const char *path, \ - const char *attrname, struct iovec *iovp, \ - unsigned iovcnt); } + int namespace, const char *attrname, \ + struct iovec *iovp, unsigned iovcnt); } 357 STD BSD { int extattr_get_file(const char *path, \ - const char *attrname, struct iovec *iovp, \ - unsigned iovcnt); } + int namespace, const char *attrname, \ + struct iovec *iovp, unsigned iovcnt); } 358 STD BSD { int extattr_delete_file(const char *path, \ - const char *attrname); } + int namespace, const char *attrname); } 359 STD BSD { int aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); } 360 STD BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } 361 STD BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 3e9fc75..ee56c83 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -739,11 +739,12 @@ vfs_stduninit (vfsp) } int -vfs_stdextattrctl(mp, cmd, attrname, arg, p) +vfs_stdextattrctl(mp, cmd, filename_vp, namespace, attrname, p) struct mount *mp; int cmd; + struct vnode *filename_vp; + int namespace; const char *attrname; - caddr_t arg; struct proc *p; { return(EOPNOTSUPP); diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index a6c9887..79abaf4 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.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); 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); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 760df67..6c8c0f9 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -808,8 +808,8 @@ vn_kqfilter(struct file *fp, struct knote *kn) * Set IO_NODELOCKED in ioflg if the vnode is already locked. */ int -vn_extattr_get(struct vnode *vp, int ioflg, const char *attrname, int *buflen, - char *buf, struct proc *p) +vn_extattr_get(struct vnode *vp, int ioflg, int namespace, + const char *attrname, int *buflen, char *buf, struct proc *p) { struct uio auio; struct iovec iov; @@ -830,7 +830,7 @@ vn_extattr_get(struct vnode *vp, int ioflg, const char *attrname, int *buflen, vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* authorize attribute retrieval as kernel */ - error = VOP_GETEXTATTR(vp, attrname, &auio, NULL, p); + error = VOP_GETEXTATTR(vp, namespace, attrname, &auio, NULL, p); if ((ioflg & IO_NODELOCKED) == 0) VOP_UNLOCK(vp, 0, p); @@ -846,8 +846,8 @@ vn_extattr_get(struct vnode *vp, int ioflg, const char *attrname, int *buflen, * XXX failure mode if partially written? */ int -vn_extattr_set(struct vnode *vp, int ioflg, const char *attrname, int buflen, - char *buf, struct proc *p) +vn_extattr_set(struct vnode *vp, int ioflg, int namespace, + const char *attrname, int buflen, char *buf, struct proc *p) { struct uio auio; struct iovec iov; @@ -872,7 +872,7 @@ vn_extattr_set(struct vnode *vp, int ioflg, const char *attrname, int buflen, } /* authorize attribute setting as kernel */ - error = VOP_SETEXTATTR(vp, attrname, &auio, NULL, p); + error = VOP_SETEXTATTR(vp, namespace, attrname, &auio, NULL, p); if ((ioflg & IO_NODELOCKED) == 0) { vn_finished_write(mp); @@ -883,7 +883,8 @@ vn_extattr_set(struct vnode *vp, int ioflg, const char *attrname, int buflen, } int -vn_extattr_rm(struct vnode *vp, int ioflg, const char *attrname, struct proc *p) +vn_extattr_rm(struct vnode *vp, int ioflg, int namespace, const char *attrname, + struct proc *p) { struct mount *mp; int error; @@ -895,7 +896,7 @@ vn_extattr_rm(struct vnode *vp, int ioflg, const char *attrname, struct proc *p) } /* authorize attribute removal as kernel */ - error = VOP_SETEXTATTR(vp, attrname, NULL, NULL, p); + error = VOP_SETEXTATTR(vp, namespace, attrname, NULL, NULL, p); if ((ioflg & IO_NODELOCKED) == 0) { vn_finished_write(mp); diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 87fe31c..9cbe079 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -529,6 +529,7 @@ vop_aclcheck { # vop_getextattr { IN struct vnode *vp; + IN int namespace; IN const char *name; INOUT struct uio *uio; IN struct ucred *cred; @@ -540,6 +541,7 @@ vop_getextattr { # vop_setextattr { IN struct vnode *vp; + IN int namespace; IN const char *name; INOUT struct uio *uio; IN struct ucred *cred; |