summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2002-02-22 20:37:47 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2002-02-22 20:37:47 +0000
commitee9702d877ed9cc007f77da8cbcb7ea74f9f4dc0 (patch)
tree6a5edf89be5ae684d40781673d7ec545b4db57a2 /sys/kern
parentea91a65c1e79695fea7cb80d2acfa092fc947b3d (diff)
Extended Attribute support from FreeBSD/TrustedBSD ok art@, deraadt@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/syscalls.master32
-rw-r--r--sys/kern/vfs_default.c18
-rw-r--r--sys/kern/vfs_syscalls.c408
-rw-r--r--sys/kern/vnode_if.src26
4 files changed, 479 insertions, 5 deletions
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 1a6ead6a9ec..9a9a5e90afa 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -1,4 +1,4 @@
-; $OpenBSD: syscalls.master,v 1.47 2001/06/26 19:56:52 dugsong Exp $
+; $OpenBSD: syscalls.master,v 1.48 2002/02/22 20:37:45 drahn Exp $
; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@@ -534,4 +534,32 @@
271 STD { int sys_mlockall(int flags); }
272 STD { int sys_munlockall(void); }
273 STD { int sys_getpeereid(int fdes, uid_t *euid, gid_t *egid); }
-
+#ifdef UFS_EXTATTR
+274 STD { int sys_extattrctl(const char *path, int cmd, \
+ const char *filename, int attrnamespace, \
+ const char *attrname); }
+275 STD { int sys_extattr_set_file(const char *path, \
+ int attrnamespace, const char *attrname, \
+ void *data, size_t nbytes); }
+276 STD { ssize_t sys_extattr_get_file(const char *path, \
+ int attrnamespace, const char *attrname, \
+ void *data, size_t nbytes); }
+277 STD { int sys_extattr_delete_file(const char *path, \
+ int attrnamespace, const char *attrname); }
+278 STD { int sys_extattr_set_fd(int fd, int attrnamespace, \
+ const char *attrname, void *data, \
+ size_t nbytes); }
+279 STD { ssize_t sys_extattr_get_fd(int fd, \
+ int attrnamespace, const char *attrname, \
+ void *data, size_t nbytes); }
+280 STD { int sys_extattr_delete_fd(int fd, int attrnamespace, \
+ const char *attrname); }
+#else
+274 UNIMPL sys_extattrctl
+275 UNIMPL sys_extattr_set_file
+276 UNIMPL sys_extattr_get_file
+277 UNIMPL sys_extattr_delete_file
+278 UNIMPL sys_extattr_set_fd
+279 UNIMPL sys_extattr_get_fd
+280 UNIMPL sys_extattr_delete_fd
+#endif
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index d987b1a78ec..fc15c1619e7 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_default.c,v 1.16 2001/12/19 08:58:06 art Exp $ */
+/* $OpenBSD: vfs_default.c,v 1.17 2002/02/22 20:37:45 drahn Exp $ */
/*
@@ -310,3 +310,19 @@ lease_check(void *v)
{
return (0);
}
+/*
+ * vfs default ops
+ * used to fill the vfs fucntion table to get reasonable default return values.
+ */
+
+int
+vfs_stdextattrctl(mp, cmd, filename_vp, attrnamespace, attrname, td)
+ struct mount *mp;
+ int cmd;
+ struct vnode *filename_vp;
+ int attrnamespace;
+ const char *attrname;
+ struct proc *td;
+{
+ return(EOPNOTSUPP);
+}
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index b4aeb2e150c..7b92e02b0e6 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.93 2002/02/12 18:41:21 art Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.94 2002/02/22 20:37:45 drahn Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -54,6 +54,7 @@
#include <sys/uio.h>
#include <sys/malloc.h>
#include <sys/dirent.h>
+#include <sys/extattr.h>
#include <sys/syscallargs.h>
@@ -2804,3 +2805,408 @@ sys_pwritev(p, v, retval)
return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
&offset, retval));
}
+
+#ifdef UFS_EXTATTR
+/*
+ * Syscall to push extended attribute configuration information into the
+ * VFS. Accepts a path, which it converts to a mountpoint, as well as
+ * a command (int cmd), and attribute name and misc data. For now, the
+ * attribute name is left in userspace for consumption by the VFS_op.
+ * It will probably be changed to be copied into sysspace by the
+ * syscall in the future, once issues with various consumers of the
+ * attribute code have raised their hands.
+ *
+ * Currently this is used only by UFS Extended Attributes.
+ */
+int
+sys_extattrctl(struct proc *p, void *v, register_t *reval)
+{
+ struct sys_extattrctl_args /* {
+ syscallarg(const char *) path;
+ syscallarg(int) cmd;
+ syscallarg(const char *) filename;
+ syscallarg(int) attrnamespace;
+ syscallarg(const char *) attrname;
+ } */ *uap = v;
+ 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, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, filename), p);
+ if ((error = namei(&nd)) != 0)
+ return (error);
+ filename_vp = nd.ni_vp;
+ }
+
+ /* SCARG(uap, path) always defined. */
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if ((error = namei(&nd)) != 0) {
+ if (filename_vp != NULL)
+ vput(filename_vp);
+ return (error);
+ }
+
+ mp = nd.ni_vp->v_mount;
+ if (error) {
+ if (filename_vp != NULL)
+ vput(filename_vp);
+ return (error);
+ }
+
+ if (SCARG(uap, attrname) != NULL) {
+ error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp,
+ SCARG(uap, attrnamespace), attrname, p);
+ } else {
+ error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp,
+ SCARG(uap, attrnamespace), NULL, p);
+ }
+
+ /*
+ * 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);
+}
+
+/*-
+ * Set a named extended attribute on a file or directory
+ *
+ * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
+ * kernelspace string pointer "attrname", userspace buffer
+ * pointer "data", buffer length "nbytes", thread "td".
+ * Returns: 0 on success, an error number otherwise
+ * Locks: none
+ * References: vp must be a valid reference for the duration of the call
+ */
+static int
+extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
+ void *data, size_t nbytes, struct proc *p, register_t *retval)
+{
+ struct uio auio;
+ struct iovec aiov;
+ ssize_t cnt;
+ int error;
+
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+
+ aiov.iov_base = data;
+ aiov.iov_len = nbytes;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_offset = 0;
+ if (nbytes > INT_MAX) {
+ error = EINVAL;
+ goto done;
+ }
+ auio.uio_resid = nbytes;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_procp = p;
+ cnt = nbytes;
+
+ error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
+ p->p_ucred, p);
+ cnt -= auio.uio_resid;
+ retval[0] = cnt;
+
+done:
+ VOP_UNLOCK(vp, 0, p);
+ return (error);
+}
+
+int
+sys_extattr_set_file(struct proc *p, void *v, register_t *retval)
+{
+ struct sys_extattr_set_file_args /* {
+ syscallarg(const char *) path;
+ syscallarg(int) attrnamespace;
+ syscallarg(const char *) attrname;
+ syscallarg(void *) data;
+ syscallarg(size_t) nbytes;
+ } */ *uap = v;
+ struct nameidata nd;
+ char attrname[EXTATTR_MAXNAMELEN];
+ int error;
+
+ error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
+ NULL);
+ if (error)
+ return (error);
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if ((error = namei(&nd)) != 0)
+ return (error);
+
+ error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
+ SCARG(uap, data), SCARG(uap, nbytes), p, retval);
+
+ vrele(nd.ni_vp);
+ return (error);
+}
+
+int
+sys_extattr_set_fd(struct proc *p, void *v, register_t *retval)
+{
+ struct sys_extattr_set_fd_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) attrnamespace;
+ syscallarg(const char *) attrname;
+ syscallarg(struct iovec *) iovp;
+ syscallarg(int) iovcnt;
+ } */ *uap = v;
+ struct file *fp;
+ char attrname[EXTATTR_MAXNAMELEN];
+ int error;
+
+ error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
+ NULL);
+ if (error)
+ return (error);
+
+ if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
+ return (error);
+
+ FREF(fp);
+ error = extattr_set_vp((struct vnode *)fp->f_data,
+ SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
+ SCARG(uap, nbytes), p, retval);
+ FRELE(fp);
+
+ return (error);
+}
+
+/*-
+ * Get a named extended attribute on a file or directory
+ *
+ * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
+ * kernelspace string pointer "attrname", userspace buffer
+ * pointer "data", buffer length "nbytes", thread "td".
+ * Returns: 0 on success, an error number otherwise
+ * Locks: none
+ * References: vp must be a valid reference for the duration of the call
+ */
+static int
+extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
+ void *data, size_t nbytes, struct proc *p, register_t *retval)
+{
+ struct uio auio;
+ struct iovec aiov;
+ ssize_t cnt;
+ size_t size;
+ int error;
+
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_READ);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+
+ /*
+ * Slightly unusual semantics: if the user provides a NULL data
+ * pointer, they don't want to receive the data, just the
+ * maximum read length.
+ */
+ if (data != NULL) {
+ aiov.iov_base = data;
+ aiov.iov_len = nbytes;
+ auio.uio_iov = &aiov;
+ auio.uio_offset = 0;
+ if (nbytes > INT_MAX) {
+ error = EINVAL;
+ goto done;
+ }
+ auio.uio_resid = nbytes;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_procp = p;
+ cnt = nbytes;
+ error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio,
+ NULL, p->p_ucred, p);
+ cnt -= auio.uio_resid;
+ retval[0] = cnt;
+ } else {
+ error = VOP_GETEXTATTR(vp, attrnamespace, attrname, NULL,
+ &size, p->p_ucred, p);
+ retval[0] = size;
+ }
+done:
+ VOP_UNLOCK(vp, 0, p);
+ return (error);
+}
+
+int
+sys_extattr_get_file(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_extattr_get_file_args /* {
+ syscallarg(const char *) path;
+ syscallarg(int) attrnamespace;
+ syscallarg(const char *) attrname;
+ syscallarg(void *) data;
+ syscallarg(size_t) nbytes;
+ } */ *uap = v;
+ struct nameidata nd;
+ char attrname[EXTATTR_MAXNAMELEN];
+ int error;
+
+ error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
+ NULL);
+ if (error)
+ return (error);
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if ((error = namei(&nd)) != 0)
+ return (error);
+
+ error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
+ SCARG(uap, data), SCARG(uap, nbytes), p, retval);
+
+ vrele(nd.ni_vp);
+ return (error);
+}
+
+int
+sys_extattr_get_fd(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_extattr_get_fd_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) attrnamespace;
+ syscallarg(const char *) attrname;
+ syscallarg(void *) data;
+ syscallarg(size_t) nbytes;
+ } */ *uap = v;
+ struct file *fp;
+ char attrname[EXTATTR_MAXNAMELEN];
+ int error;
+
+ error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
+ NULL);
+ if (error)
+ return (error);
+
+ if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
+ return (error);
+
+ FREF(fp);
+ error = extattr_get_vp((struct vnode *)fp->f_data,
+ SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
+ SCARG(uap, nbytes), p, retval);
+ FRELE(fp);
+
+ return (error);
+}
+
+/*
+ * extattr_delete_vp(): Delete a named extended attribute on a file or
+ * directory
+ *
+ * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
+ * kernelspace string pointer "attrname", proc "p"
+ * Returns: 0 on success, an error number otherwise
+ * Locks: none
+ * References: vp must be a valid reference for the duration of the call
+ */
+static int
+extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
+ struct proc *p)
+{
+ int error;
+
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+
+ error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
+ p->p_ucred, p);
+
+ VOP_UNLOCK(vp, 0, p);
+ return (error);
+}
+
+int
+sys_extattr_delete_file(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_extattr_delete_file_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) attrnamespace;
+ syscallarg(const char *) attrname;
+ } */ *uap = v;
+ struct nameidata nd;
+ char attrname[EXTATTR_MAXNAMELEN];
+ int error;
+
+ error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
+ NULL);
+ if (error)
+ return(error);
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if ((error = namei(&nd)) != 0)
+ return(error);
+
+ error = extattr_delete_vp(nd.ni_vp, SCARG(uap, attrnamespace),
+ attrname, p);
+
+ vrele(nd.ni_vp);
+ return(error);
+}
+
+int
+sys_extattr_delete_fd(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_extattr_delete_fd_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) attrnamespace;
+ syscallarg(const char *) attrname;
+ } */ *uap = v;
+ struct file *fp;
+ char attrname[EXTATTR_MAXNAMELEN];
+ int error;
+
+ error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
+ NULL);
+ if (error)
+ return (error);
+
+ if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
+ return (error);
+
+ FREF(fp);
+ error = extattr_delete_vp((struct vnode *)fp->f_data,
+ SCARG(uap, attrnamespace), attrname, p);
+ FRELE(fp);
+
+ return (error);
+}
+#endif
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index a1cd5c5b9c5..4eb88e93191 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -1,4 +1,4 @@
-# $OpenBSD: vnode_if.src,v 1.18 2001/12/19 08:58:06 art Exp $
+# $OpenBSD: vnode_if.src,v 1.19 2002/02/22 20:37:45 drahn Exp $
# $NetBSD: vnode_if.src,v 1.10 1996/05/11 18:26:27 mycroft Exp $
#
# Copyright (c) 1992, 1993
@@ -467,3 +467,27 @@ vop_whiteout {
#vop_bwrite {
# IN struct buf *bp;
#};
+#
+#% getextattr vp L L L
+#
+vop_getextattr {
+ IN struct vnode *vp;
+ IN int attrnamespace;
+ IN const char *name;
+ INOUT struct uio *uio;
+ OUT size_t *size;
+ IN struct ucred *cred;
+ IN struct proc *p;
+};
+
+#
+#% setextattr vp L L L
+#
+vop_setextattr {
+ IN struct vnode *vp;
+ IN int attrnamespace;
+ IN const char *name;
+ INOUT struct uio *uio;
+ IN struct ucred *cred;
+ IN struct proc *p;
+};