Page MenuHomeFreeBSD

D13209.diff
No OneTemporary

D13209.diff

Index: sys/amd64/linux/linux_dummy.c
===================================================================
--- sys/amd64/linux/linux_dummy.c
+++ sys/amd64/linux/linux_dummy.c
@@ -155,24 +155,3 @@
DUMMY(pkey_mprotect);
DUMMY(pkey_alloc);
DUMMY(pkey_free);
-
-#define DUMMY_XATTR(s) \
-int \
-linux_ ## s ## xattr( \
- struct thread *td, struct linux_ ## s ## xattr_args *arg) \
-{ \
- \
- return (ENOATTR); \
-}
-DUMMY_XATTR(set);
-DUMMY_XATTR(lset);
-DUMMY_XATTR(fset);
-DUMMY_XATTR(get);
-DUMMY_XATTR(lget);
-DUMMY_XATTR(fget);
-DUMMY_XATTR(list);
-DUMMY_XATTR(llist);
-DUMMY_XATTR(flist);
-DUMMY_XATTR(remove);
-DUMMY_XATTR(lremove);
-DUMMY_XATTR(fremove);
Index: sys/amd64/linux32/linux32_dummy.c
===================================================================
--- sys/amd64/linux32/linux32_dummy.c
+++ sys/amd64/linux32/linux32_dummy.c
@@ -163,24 +163,3 @@
DUMMY(pkey_mprotect);
DUMMY(pkey_alloc);
DUMMY(pkey_free);
-
-#define DUMMY_XATTR(s) \
-int \
-linux_ ## s ## xattr( \
- struct thread *td, struct linux_ ## s ## xattr_args *arg) \
-{ \
- \
- return (ENOATTR); \
-}
-DUMMY_XATTR(set);
-DUMMY_XATTR(lset);
-DUMMY_XATTR(fset);
-DUMMY_XATTR(get);
-DUMMY_XATTR(lget);
-DUMMY_XATTR(fget);
-DUMMY_XATTR(list);
-DUMMY_XATTR(llist);
-DUMMY_XATTR(flist);
-DUMMY_XATTR(remove);
-DUMMY_XATTR(lremove);
-DUMMY_XATTR(fremove);
Index: sys/bsm/audit_kevents.h
===================================================================
--- sys/bsm/audit_kevents.h
+++ sys/bsm/audit_kevents.h
@@ -770,8 +770,12 @@
#define AUE_INITGROUPS AUE_NULL
#define AUE_IOPOLICYSYS AUE_NULL
#define AUE_ISSETUGID AUE_NULL
+#define AUE_LGETXATTR AUE_NULL
#define AUE_LIOLISTIO AUE_NULL
#define AUE_LISTXATTR AUE_NULL
+#define AUE_LLISTXATTR AUE_NULL
+#define AUE_LREMOVEXATTR AUE_NULL
+#define AUE_LSETXATTR AUE_NULL
#define AUE_LSTATV AUE_NULL
#define AUE_LSTAT64 AUE_NULL
#define AUE_LSTAT64_EXTENDED AUE_NULL
Index: sys/compat/linux/linux_xattr.h
===================================================================
--- /dev/null
+++ sys/compat/linux/linux_xattr.h
@@ -0,0 +1,40 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2017 Fedor Uporov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define XATTR_NAME_MAX 255 /* Chars in an xattr name */
+#define XATTR_SIZE_MAX 65536 /* Size of an extended attribute value (64k). */
+
+#define XATTR_NAMESPACE_SECURITY_STRING "security"
+#define LINUX_BSD_USER_NAMESPACE EXTATTR_NAMESPACE_USER
+
+static const char linux_xattr_name_separator = '.';
+
+#define XATTR_CREATE 0x1 /* Set value, fail if attr already exists. */
+#define XATTR_REPLACE 0x2 /* Set value, fail if attr does not exist. */
Index: sys/compat/linux/linux_xattr.c
===================================================================
--- /dev/null
+++ sys/compat/linux/linux_xattr.c
@@ -0,0 +1,695 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2017 Fedor Uporov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/capsicum.h>
+#include <sys/conf.h>
+#include <sys/dirent.h>
+#include <sys/extattr.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/sx.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/tty.h>
+#include <sys/unistd.h>
+#include <sys/vnode.h>
+
+#include <security/audit/audit.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_xattr.h>
+
+static int
+linux_xattr_namespace_from_linux(const char *linux_name, int *attrnamespace,
+ const char **bsd_name)
+{
+ int prefix_len;
+
+ /*
+ * The only 'user.' linux namespace is supported for now.
+ */
+ if (bcmp(linux_name, EXTATTR_NAMESPACE_USER_STRING,
+ strlen(EXTATTR_NAMESPACE_USER_STRING)) == 0 &&
+ linux_name[strlen(EXTATTR_NAMESPACE_USER_STRING)] ==
+ linux_xattr_name_separator) {
+ *attrnamespace = EXTATTR_NAMESPACE_USER;
+ prefix_len = strlen(EXTATTR_NAMESPACE_USER_STRING) + 1;
+ *bsd_name = &linux_name[prefix_len];
+ return (0);
+ }
+
+ return (EOPNOTSUPP);
+}
+
+static int
+linux_setxattr_common(struct vnode *vp, const char *attrname,
+ char *value, size_t size, int flags, struct thread *td)
+{
+ struct mount *mp;
+ struct uio auio;
+ struct iovec aiov;
+ const char *bsd_attrname;
+ struct vattr vattr;
+ int attrnamespace, error;
+
+ /*
+ * Validate fs objects types according LTP requirements
+ * for 'user.' namespace xattrs.
+ */
+ if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
+ return (EPERM);
+
+ /* Validate xattr value size. */
+ if (size > XATTR_SIZE_MAX)
+ return (E2BIG);
+
+ /* Validate create/replace flags. */
+ if (flags && (flags != XATTR_CREATE && flags != XATTR_REPLACE))
+ return (EINVAL);
+
+ error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
+ if (error)
+ return (error);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+
+ /*
+ * Check stat immutable/append flags.
+ */
+ vattr.va_birthtime.tv_sec = -1;
+ vattr.va_birthtime.tv_nsec = 0;
+ vattr.va_fsid = VNOVAL;
+ vattr.va_rdev = NODEV;
+ error = VOP_GETATTR(vp, &vattr, NOCRED);
+ if (error)
+ goto done;
+
+ if (vattr.va_flags & (IMMUTABLE | APPEND)) {
+ error = EPERM;
+ goto done;
+ }
+
+ error = linux_xattr_namespace_from_linux(attrname, &attrnamespace,
+ &bsd_attrname);
+ if (error)
+ goto done;
+
+ /*
+ * Check create/replace file flags.
+ */
+ if (flags) {
+ error = VOP_GETEXTATTR(vp, attrnamespace, bsd_attrname, NULL, NULL,
+ td->td_ucred, td);
+ if (error && error != ENOATTR)
+ goto done;
+ else if (error == ENOATTR && (flags & XATTR_REPLACE))
+ goto done;
+ else if (error == 0 && !(flags & XATTR_REPLACE)) {
+ error = EEXIST;
+ goto done;
+ }
+ }
+
+ aiov.iov_base = value;
+ aiov.iov_len = size;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_offset = 0;
+ if (size > IOSIZE_MAX) {
+ error = ERANGE;
+ goto done;
+ }
+ auio.uio_resid = size;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_td = td;
+
+ error = VOP_SETEXTATTR(vp, attrnamespace, bsd_attrname, &auio,
+ td->td_ucred, td);
+
+done:
+ VOP_UNLOCK(vp, 0);
+ vn_finished_write(mp);
+ return (error);
+}
+
+int
+linux_setxattr(struct thread *td, struct linux_setxattr_args *args)
+{
+ struct nameidata nd;
+ char attrname[EXTATTR_MAXNAMELEN];
+ int error;
+
+ error = copyinstr(args->name, attrname, EXTATTR_MAXNAMELEN, NULL);
+ if (error && error == ENAMETOOLONG)
+ return (ERANGE);
+ else if (error)
+ return (error);
+
+ AUDIT_ARG_TEXT(attrname);
+
+ NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE,
+ args->path, td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = linux_setxattr_common(nd.ni_vp, attrname, args->value,
+ args->size, args->flags, td);
+
+ vrele(nd.ni_vp);
+ return (error);
+}
+
+int
+linux_lsetxattr(struct thread *td, struct linux_lsetxattr_args *args)
+{
+ struct nameidata nd;
+ char attrname[EXTATTR_MAXNAMELEN];
+ int error;
+
+ error = copyinstr(args->name, attrname, EXTATTR_MAXNAMELEN, NULL);
+ if (error && error == ENAMETOOLONG)
+ return (ERANGE);
+ else if (error)
+ return (error);
+
+ AUDIT_ARG_TEXT(attrname);
+
+ NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
+ args->path, td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = linux_setxattr_common(nd.ni_vp, attrname, args->value,
+ args->size, args->flags, td);
+
+ vrele(nd.ni_vp);
+ return (error);
+}
+
+int
+linux_fsetxattr(struct thread *td, struct linux_fsetxattr_args *args)
+{
+ struct file *fp;
+ char attrname[EXTATTR_MAXNAMELEN];
+ cap_rights_t rights;
+ int error;
+
+ AUDIT_ARG_FD(args->fd);
+ error = copyinstr(args->name, attrname, EXTATTR_MAXNAMELEN, NULL);
+ if (error && error == ENAMETOOLONG)
+ return (ERANGE);
+ else if (error)
+ return (error);
+
+ AUDIT_ARG_TEXT(attrname);
+
+ error = getvnode(td, args->fd,
+ cap_rights_init(&rights, CAP_EXTATTR_SET), &fp);
+ if (error)
+ return (error);
+
+ error = linux_setxattr_common(fp->f_vnode, attrname, args->value,
+ args->size, args->flags, td);
+
+ fdrop(fp, td);
+ return (error);
+}
+
+static int
+linux_getxattr_common(struct vnode *vp, const char *attrname,
+ char *value, size_t size, struct thread *td)
+{
+ struct uio auio;
+ struct iovec aiov;
+ const char *bsd_attrname;
+ size_t bsd_size = 0;
+ int attrnamespace, error;
+
+ error = linux_xattr_namespace_from_linux(attrname, &attrnamespace,
+ &bsd_attrname);
+ if (error)
+ return (error);
+
+ /*
+ * The only files and directories can have 'user.' xattrs.
+ */
+ if (attrnamespace == EXTATTR_NAMESPACE_USER &&
+ vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
+ return (EPERM);
+
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+
+ /*
+ * Request xattr value size and check that the input buffer size is
+ * not less then xattr value size.
+ */
+ error = VOP_GETEXTATTR(vp, attrnamespace, bsd_attrname, NULL, &bsd_size,
+ td->td_ucred, td);
+ if (error)
+ goto done;
+
+ if (size && bsd_size > size) {
+ error = ERANGE;
+ goto done;
+ }
+ else if(value == NULL)
+ goto done;
+
+ aiov.iov_base = value;
+ aiov.iov_len = bsd_size;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_offset = 0;
+ if (bsd_size > IOSIZE_MAX) {
+ error = ERANGE;
+ goto done;
+ }
+ auio.uio_resid = bsd_size;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_td = td;
+
+ error = VOP_GETEXTATTR(vp, attrnamespace, bsd_attrname, &auio, NULL,
+ td->td_ucred, td);
+
+done:
+ if (bsd_size)
+ td->td_retval[0] = bsd_size;
+ else
+ td->td_retval[0] = 0;
+
+ VOP_UNLOCK(vp, 0);
+ return (error);
+}
+
+int
+linux_getxattr(struct thread *td, struct linux_getxattr_args *args)
+{
+ struct nameidata nd;
+ char attrname[EXTATTR_MAXNAMELEN];
+ int error;
+
+ error = copyinstr(args->name, attrname, EXTATTR_MAXNAMELEN, NULL);
+ if (error)
+ return (error);
+ AUDIT_ARG_TEXT(attrname);
+
+ NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, args->path, td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = linux_getxattr_common(nd.ni_vp, attrname, args->value,
+ args->size, td);
+
+ vrele(nd.ni_vp);
+ return (error);
+}
+
+int
+linux_lgetxattr(struct thread *td, struct linux_lgetxattr_args *args)
+{
+ struct nameidata nd;
+ char attrname[EXTATTR_MAXNAMELEN];
+ int error;
+
+ error = copyinstr(args->name, attrname, EXTATTR_MAXNAMELEN, NULL);
+ if (error)
+ return (error);
+ AUDIT_ARG_TEXT(attrname);
+
+ NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, args->path, td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = linux_getxattr_common(nd.ni_vp, attrname, args->value,
+ args->size, td);
+
+ vrele(nd.ni_vp);
+ return (error);
+}
+
+int
+linux_fgetxattr(struct thread *td, struct linux_fgetxattr_args *args)
+{
+ struct file *fp;
+ char attrname[EXTATTR_MAXNAMELEN];
+ cap_rights_t rights;
+ int error;
+
+ AUDIT_ARG_FD(args->fd);
+ error = copyinstr(args->name, attrname, EXTATTR_MAXNAMELEN, NULL);
+ if (error)
+ return (error);
+ AUDIT_ARG_TEXT(attrname);
+
+ error = getvnode(td, args->fd,
+ cap_rights_init(&rights, CAP_EXTATTR_GET), &fp);
+ if (error)
+ return (error);
+
+ error = linux_getxattr_common(fp->f_vnode, attrname, args->value,
+ args->size, td);
+
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * This function is used to convert bsd attr names list to linux compatible.
+ * The conversion consist of the next steps:
+ * 1) Adding the terminating zero in the end of the string.
+ * 2) Removing byte with characters number.
+ * 3) Adding namespace prefix.
+ *
+ * <name0_len>name0<name1_len>name1 ...
+ * to
+ * user.name0\0user.name1\0 ...
+ *
+ * Also, this function could be used to retrieve the size
+ * of linux attr names buffer form bsd-compatible one.
+ * Let's pass the linux_buf == NULL in this case.
+ */
+static int
+linux_xattrs_names_convert_to_linux(int attrnamespace,
+ const char *bsd_buf, size_t bsd_buf_size,
+ char *linux_buf, size_t* linux_buf_size)
+{
+ const char *attrnamespace_prefix, *bsd_p;
+ char *linux_p;
+ unsigned int size;
+
+ bsd_p = bsd_buf;
+ linux_p = linux_buf;
+ size = 0;
+
+ if (linux_buf_size == NULL)
+ return (EINVAL);
+
+ *linux_buf_size = 0;
+
+ if (attrnamespace == EXTATTR_NAMESPACE_USER)
+ attrnamespace_prefix = EXTATTR_NAMESPACE_USER_STRING;
+ else if (attrnamespace == EXTATTR_NAMESPACE_SYSTEM)
+ attrnamespace_prefix = EXTATTR_NAMESPACE_SYSTEM_STRING;
+ else
+ return (EINVAL);
+
+ while (bsd_p < bsd_buf + bsd_buf_size) {
+ /* Add namespace prefix. */
+ size = strlen(attrnamespace_prefix);
+
+ /* Add separator. */
+ size += sizeof(linux_xattr_name_separator);
+
+ /* Fill the name. */
+ size += *bsd_p;
+
+ /* Add terminating zero. */
+ size += 1;
+
+ /* Fill name if linux_buf was passed. */
+ if (linux_p != NULL) {
+ snprintf(linux_p, size, "%s%c%s",
+ attrnamespace_prefix, linux_xattr_name_separator,
+ bsd_p + 1);
+ linux_p[size] = '\0';
+ linux_p += size;
+ }
+
+ bsd_p += *bsd_p;
+ bsd_p += 1;
+ *linux_buf_size += size;
+ }
+
+ return (0);
+}
+
+static int
+linux_listxattr_common(struct vnode *vp, char *buf, size_t size, struct thread *td)
+{
+ struct uio auio;
+ struct iovec aiov;
+ char *bsd_buf = NULL;
+ size_t bsd_size, linux_size;
+ int error;
+
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+
+ /*
+ * Unfortunately we should do two listxattr() calls per one system call,
+ * because it is impossible to get linux compatible xattrs list size
+ * without bsd list reading.
+ */
+ error = VOP_LISTEXTATTR(vp, LINUX_BSD_USER_NAMESPACE, NULL, &bsd_size,
+ td->td_ucred, td);
+ if (error)
+ goto done;
+
+ bsd_buf = malloc(bsd_size, M_TEMP, M_WAITOK);
+ if (bsd_buf == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
+
+ aiov.iov_base = bsd_buf;
+ aiov.iov_len = bsd_size;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_offset = 0;
+ if (bsd_size > IOSIZE_MAX) {
+ error = ERANGE;
+ goto done;
+ }
+ auio.uio_resid = bsd_size;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_td = td;
+
+ error = VOP_LISTEXTATTR(vp, LINUX_BSD_USER_NAMESPACE, &auio, NULL,
+ td->td_ucred, td);
+ if (error)
+ goto done;
+
+ error = linux_xattrs_names_convert_to_linux(LINUX_BSD_USER_NAMESPACE,
+ bsd_buf, bsd_size, buf, &linux_size);
+ if (error) {
+ td->td_retval[0] = 0;
+ } else {
+ /* Check, that we have space in the input buffer. */
+ if (size && size < linux_size) {
+ td->td_retval[0] = 0;
+ error = ERANGE;
+ } else
+ td->td_retval[0] = linux_size;
+ }
+
+done:
+ free(bsd_buf, M_TEMP);
+ VOP_UNLOCK(vp, 0);
+ return (error);
+}
+
+int
+linux_listxattr(struct thread *td, struct linux_listxattr_args *args)
+{
+ struct nameidata nd;
+ int error;
+
+ NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, args->path, td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = linux_listxattr_common(nd.ni_vp, args->list, args->size, td);
+
+ vrele(nd.ni_vp);
+ return (error);
+}
+
+int
+linux_llistxattr(struct thread *td, struct linux_llistxattr_args *args)
+{
+ struct nameidata nd;
+ int error;
+
+ NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, args->path,
+ td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = linux_listxattr_common(nd.ni_vp, args->list, args->size, td);
+
+ vrele(nd.ni_vp);
+ return (error);
+}
+
+int
+linux_flistxattr(struct thread *td, struct linux_flistxattr_args *args)
+{
+ struct file *fp;
+ cap_rights_t rights;
+ int error;
+
+ AUDIT_ARG_FD(args->fd);
+ error = getvnode(td, args->fd,
+ cap_rights_init(&rights, CAP_EXTATTR_LIST), &fp);
+ if (error)
+ return (error);
+
+ error = linux_listxattr_common(fp->f_vnode, args->list, args->size, td);
+
+ fdrop(fp, td);
+ return (error);
+}
+
+int
+linux_removexattr(struct thread *td, struct linux_removexattr_args *args)
+{
+ struct nameidata nd;
+ char attrname[EXTATTR_MAXNAMELEN];
+ const char *bsd_attrname;
+ int attrnamespace, error;
+
+ error = copyinstr(args->name, attrname, EXTATTR_MAXNAMELEN, NULL);
+ if (error)
+ return (error);
+ AUDIT_ARG_TEXT(attrname);
+
+ NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, args->path, td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = linux_xattr_namespace_from_linux(attrname, &attrnamespace,
+ &bsd_attrname);
+ if (error)
+ goto done;
+
+ error = extattr_delete_vp(nd.ni_vp, attrnamespace, bsd_attrname, td);
+
+done:
+ vrele(nd.ni_vp);
+ return (error);
+}
+
+int
+linux_lremovexattr(struct thread *td, struct linux_lremovexattr_args *args)
+{
+ struct nameidata nd;
+ char attrname[EXTATTR_MAXNAMELEN];
+ const char *bsd_attrname;
+ int attrnamespace, error;
+
+ error = copyinstr(args->name, attrname, EXTATTR_MAXNAMELEN, NULL);
+ if (error)
+ return (error);
+ AUDIT_ARG_TEXT(attrname);
+
+ NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, args->path, td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = linux_xattr_namespace_from_linux(attrname, &attrnamespace,
+ &bsd_attrname);
+ if (error)
+ goto done;
+
+ error = extattr_delete_vp(nd.ni_vp, attrnamespace, bsd_attrname, td);
+
+done:
+ vrele(nd.ni_vp);
+ return (error);
+}
+
+int
+linux_fremovexattr(struct thread *td, struct linux_fremovexattr_args *args)
+{
+ struct file *fp;
+ char attrname[EXTATTR_MAXNAMELEN];
+ cap_rights_t rights;
+ const char *bsd_attrname;
+ int attrnamespace, error;
+
+ AUDIT_ARG_FD(args->fd);
+ error = copyinstr(args->name, attrname, EXTATTR_MAXNAMELEN, NULL);
+ if (error)
+ return (error);
+ AUDIT_ARG_TEXT(attrname);
+
+ error = getvnode(td, args->fd,
+ cap_rights_init(&rights, CAP_EXTATTR_GET), &fp);
+ if (error)
+ return (error);
+
+ error = linux_xattr_namespace_from_linux(attrname, &attrnamespace,
+ &bsd_attrname);
+ if (error)
+ goto done;
+
+ error = extattr_delete_vp(fp->f_vnode, attrnamespace, bsd_attrname, td);
+
+done:
+ fdrop(fp, td);
+ return (error);
+}
Index: sys/conf/files.amd64
===================================================================
--- sys/conf/files.amd64
+++ sys/conf/files.amd64
@@ -632,6 +632,7 @@
compat/linux/linux_uid16.c optional compat_linux32
compat/linux/linux_util.c optional compat_linux32
compat/linux/linux_vdso.c optional compat_linux32
+compat/linux/linux_xattr.c optional compat_linux32
compat/linux/linux_common.c optional compat_linux32
compat/linux/linux_event.c optional compat_linux32
compat/linux/linux.c optional compat_linux32
Index: sys/conf/files.i386
===================================================================
--- sys/conf/files.i386
+++ sys/conf/files.i386
@@ -106,6 +106,7 @@
compat/linux/linux_uid16.c optional compat_linux
compat/linux/linux_util.c optional compat_linux
compat/linux/linux_vdso.c optional compat_linux
+compat/linux/linux_xattr.c optional compat_linux
compat/linux/linux.c optional compat_linux
compat/ndis/kern_ndis.c optional ndisapi pci
compat/ndis/kern_windrv.c optional ndisapi pci
Index: sys/i386/linux/linux_dummy.c
===================================================================
--- sys/i386/linux/linux_dummy.c
+++ sys/i386/linux/linux_dummy.c
@@ -159,24 +159,3 @@
DUMMY(pkey_mprotect);
DUMMY(pkey_alloc);
DUMMY(pkey_free);
-
-#define DUMMY_XATTR(s) \
-int \
-linux_ ## s ## xattr( \
- struct thread *td, struct linux_ ## s ## xattr_args *arg) \
-{ \
- \
- return (ENOATTR); \
-}
-DUMMY_XATTR(set);
-DUMMY_XATTR(lset);
-DUMMY_XATTR(fset);
-DUMMY_XATTR(get);
-DUMMY_XATTR(lget);
-DUMMY_XATTR(fget);
-DUMMY_XATTR(list);
-DUMMY_XATTR(llist);
-DUMMY_XATTR(flist);
-DUMMY_XATTR(remove);
-DUMMY_XATTR(lremove);
-DUMMY_XATTR(fremove);
Index: sys/modules/linux/Makefile
===================================================================
--- sys/modules/linux/Makefile
+++ sys/modules/linux/Makefile
@@ -15,7 +15,7 @@
linux${SFX}_machdep.c linux_misc.c linux_signal.c \
linux_socket.c linux_stats.c linux_sysctl.c linux${SFX}_sysent.c \
linux${SFX}_sysvec.c linux_uid16.c linux_time.c \
- linux_timer.c linux_vdso.c \
+ linux_timer.c linux_vdso.c linux_xattr.c \
opt_inet6.h opt_compat.h opt_posix.h opt_usb.h vnode_if.h \
device_if.h bus_if.h assym.s \
linux${SFX}_support.s
Index: sys/modules/linux64/Makefile
===================================================================
--- sys/modules/linux64/Makefile
+++ sys/modules/linux64/Makefile
@@ -9,7 +9,8 @@
linux_futex.c linux_getcwd.c linux_ioctl.c linux_ipc.c \
linux_machdep.c linux_misc.c linux_ptrace.c linux_signal.c \
linux_socket.c linux_stats.c linux_sysctl.c linux_sysent.c \
- linux_sysvec.c linux_time.c linux_vdso.c linux_timer.c \
+ linux_sysvec.c linux_time.c linux_timer.c linux_vdso.c \
+ linux_xattr.c \
opt_inet6.h opt_compat.h opt_posix.h opt_usb.h \
vnode_if.h device_if.h bus_if.h assym.s \
linux_support.s

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 6, 2:15 PM (2 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14488585
Default Alt Text
D13209.diff (23 KB)

Event Timeline