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/linux/linux_proto.h =================================================================== --- sys/amd64/linux/linux_proto.h +++ sys/amd64/linux/linux_proto.h @@ -618,40 +618,70 @@ register_t dummy; }; struct linux_setxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; + char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_lsetxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; + char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_fsetxattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; + char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_getxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_lgetxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_fgetxattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_listxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char list_l_[PADL_(const char *)]; char * list; char list_r_[PADR_(const char *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_llistxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char list_l_[PADL_(const char *)]; char * list; char list_r_[PADR_(const char *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_flistxattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char list_l_[PADL_(const char *)]; char * list; char list_r_[PADR_(const char *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_removexattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct linux_lremovexattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct linux_fremovexattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct linux_tkill_args { char tid_l_[PADL_(int)]; int tid; char tid_r_[PADR_(int)]; Index: sys/amd64/linux/linux_sysent.c =================================================================== --- sys/amd64/linux/linux_sysent.c +++ sys/amd64/linux/linux_sysent.c @@ -205,18 +205,18 @@ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 185 = security */ { 0, (sy_call_t *)linux_gettid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 186 = linux_gettid */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 187 = linux_readahead */ - { 0, (sy_call_t *)linux_setxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 188 = linux_setxattr */ - { 0, (sy_call_t *)linux_lsetxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 189 = linux_lsetxattr */ - { 0, (sy_call_t *)linux_fsetxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 190 = linux_fsetxattr */ - { 0, (sy_call_t *)linux_getxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 191 = linux_getxattr */ - { 0, (sy_call_t *)linux_lgetxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 192 = linux_lgetxattr */ - { 0, (sy_call_t *)linux_fgetxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 193 = linux_fgetxattr */ - { 0, (sy_call_t *)linux_listxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 194 = linux_listxattr */ - { 0, (sy_call_t *)linux_llistxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 195 = linux_llistxattr */ - { 0, (sy_call_t *)linux_flistxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 196 = linux_flistxattr */ - { 0, (sy_call_t *)linux_removexattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 197 = linux_removexattr */ - { 0, (sy_call_t *)linux_lremovexattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 198 = linux_lremovexattr */ - { 0, (sy_call_t *)linux_fremovexattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 199 = linux_fremovexattr */ + { AS(linux_setxattr_args), (sy_call_t *)linux_setxattr, AUE_SETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 188 = linux_setxattr */ + { AS(linux_lsetxattr_args), (sy_call_t *)linux_lsetxattr, AUE_LSETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 189 = linux_lsetxattr */ + { AS(linux_fsetxattr_args), (sy_call_t *)linux_fsetxattr, AUE_FSETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 190 = linux_fsetxattr */ + { AS(linux_getxattr_args), (sy_call_t *)linux_getxattr, AUE_GETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 191 = linux_getxattr */ + { AS(linux_lgetxattr_args), (sy_call_t *)linux_lgetxattr, AUE_LGETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 192 = linux_lgetxattr */ + { AS(linux_fgetxattr_args), (sy_call_t *)linux_fgetxattr, AUE_FGETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 193 = linux_fgetxattr */ + { AS(linux_listxattr_args), (sy_call_t *)linux_listxattr, AUE_LISTXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 194 = linux_listxattr */ + { AS(linux_llistxattr_args), (sy_call_t *)linux_llistxattr, AUE_LLISTXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 195 = linux_llistxattr */ + { AS(linux_flistxattr_args), (sy_call_t *)linux_flistxattr, AUE_FLISTXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 196 = linux_flistxattr */ + { AS(linux_removexattr_args), (sy_call_t *)linux_removexattr, AUE_REMOVEXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 197 = linux_removexattr */ + { AS(linux_lremovexattr_args), (sy_call_t *)linux_lremovexattr, AUE_LREMOVEXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 198 = linux_lremovexattr */ + { AS(linux_fremovexattr_args), (sy_call_t *)linux_fremovexattr, AUE_FREMOVEXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 199 = linux_fremovexattr */ { AS(linux_tkill_args), (sy_call_t *)linux_tkill, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 200 = linux_tkill */ { AS(linux_time_args), (sy_call_t *)linux_time, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 201 = linux_time */ { AS(linux_sys_futex_args), (sy_call_t *)linux_sys_futex, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 202 = linux_sys_futex */ Index: sys/amd64/linux/linux_sysvec.c =================================================================== --- sys/amd64/linux/linux_sysvec.c +++ sys/amd64/linux/linux_sysvec.c @@ -147,7 +147,7 @@ -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, - -6, -6, -43, -42, -75,-125, -84, -95, -16, -74, + -6, -6, -43, -42, -75,-125, -84, -61, -16, -74, -72, -67, -71 }; 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/amd64/linux32/linux32_proto.h =================================================================== --- sys/amd64/linux32/linux32_proto.h +++ sys/amd64/linux32/linux32_proto.h @@ -693,40 +693,70 @@ register_t dummy; }; struct linux_setxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; + char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_lsetxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; + char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_fsetxattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; + char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_getxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_lgetxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_fgetxattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_listxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char list_l_[PADL_(const char *)]; char * list; char list_r_[PADR_(const char *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_llistxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char list_l_[PADL_(const char *)]; char * list; char list_r_[PADR_(const char *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_flistxattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char list_l_[PADL_(const char *)]; char * list; char list_r_[PADR_(const char *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_removexattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct linux_lremovexattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct linux_fremovexattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct linux_tkill_args { char tid_l_[PADL_(int)]; int tid; char tid_r_[PADR_(int)]; Index: sys/amd64/linux32/linux32_sysvec.c =================================================================== --- sys/amd64/linux32/linux32_sysvec.c +++ sys/amd64/linux32/linux32_sysvec.c @@ -146,7 +146,7 @@ -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, - -6, -6, -43, -42, -75,-125, -84, -95, -16, -74, + -6, -6, -43, -42, -75,-125, -84, -61, -16, -74, -72, -67, -71 }; Index: sys/bsm/audit_kevents.h =================================================================== --- sys/bsm/audit_kevents.h +++ sys/bsm/audit_kevents.h @@ -772,6 +772,10 @@ #define AUE_ISSETUGID AUE_NULL #define AUE_LIOLISTIO AUE_NULL #define AUE_LISTXATTR AUE_NULL +#define AUE_LGETXATTR 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,38 @@ +/*- + * 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 EXTATTR_MAXNAMELEN /* 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,696 @@ +/*- + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef COMPAT_LINUX32 +#include +#include +#else +#include +#include +#endif + +#include +#include + +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, *vap; + bool do_write_finish = false; + int attrnamespace, error; + + /* Validate fs objects types. */ + 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); + + vn_lock(vp, LK_SHARED | LK_RETRY); + + /* + * Check stat immutable/append flags. + */ + vap = &vattr; + vap->va_birthtime.tv_sec = -1; + vap->va_birthtime.tv_nsec = 0; + vap->va_fsid = VNOVAL; + vap->va_rdev = NODEV; + error = VOP_GETATTR(vp, vap, NOCRED); + if (error) + goto done; + + if (vap->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; + } + } + + error = vn_start_write(vp, &mp, V_WAIT | PCATCH); + if (error) + goto done; + else + do_write_finish = true; + vn_lock(vp, LK_TRYUPGRADE); + + 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); + do_write_finish ? vn_finished_write(mp) : 0; + 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 covert 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. + * + * name0name1 ... + * 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/i386/linux/linux_proto.h =================================================================== --- sys/i386/linux/linux_proto.h +++ sys/i386/linux/linux_proto.h @@ -694,40 +694,70 @@ register_t dummy; }; struct linux_setxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; const void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; + char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_lsetxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; const void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; + char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_fsetxattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; const void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; + char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_getxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_lgetxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_fgetxattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_listxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char list_l_[PADL_(const char *)]; char * list; char list_r_[PADR_(const char *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_llistxattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char list_l_[PADL_(const char *)]; char * list; char list_r_[PADR_(const char *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_flistxattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char list_l_[PADL_(const char *)]; char * list; char list_r_[PADR_(const char *)]; + char size_l_[PADL_(l_size_t)]; l_size_t size; char size_r_[PADR_(l_size_t)]; }; struct linux_removexattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct linux_lremovexattr_args { - register_t dummy; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct linux_fremovexattr_args { - register_t dummy; + char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; + char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct linux_tkill_args { char tid_l_[PADL_(int)]; int tid; char tid_r_[PADR_(int)]; Index: sys/i386/linux/linux_sysent.c =================================================================== --- sys/i386/linux/linux_sysent.c +++ sys/i386/linux/linux_sysent.c @@ -243,18 +243,18 @@ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 223 = */ { 0, (sy_call_t *)linux_gettid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 224 = linux_gettid */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 225 = linux_readahead */ - { 0, (sy_call_t *)linux_setxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 226 = linux_setxattr */ - { 0, (sy_call_t *)linux_lsetxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 227 = linux_lsetxattr */ - { 0, (sy_call_t *)linux_fsetxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 228 = linux_fsetxattr */ - { 0, (sy_call_t *)linux_getxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 229 = linux_getxattr */ - { 0, (sy_call_t *)linux_lgetxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 230 = linux_lgetxattr */ - { 0, (sy_call_t *)linux_fgetxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 231 = linux_fgetxattr */ - { 0, (sy_call_t *)linux_listxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 232 = linux_listxattr */ - { 0, (sy_call_t *)linux_llistxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 233 = linux_llistxattr */ - { 0, (sy_call_t *)linux_flistxattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 234 = linux_flistxattr */ - { 0, (sy_call_t *)linux_removexattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 235 = linux_removexattr */ - { 0, (sy_call_t *)linux_lremovexattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 236 = linux_lremovexattr */ - { 0, (sy_call_t *)linux_fremovexattr, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 237 = linux_fremovexattr */ + { AS(linux_setxattr_args), (sy_call_t *)linux_setxattr, AUE_SETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 226 = linux_setxattr */ + { AS(linux_lsetxattr_args), (sy_call_t *)linux_lsetxattr, AUE_LSETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 227 = linux_lsetxattr */ + { AS(linux_fsetxattr_args), (sy_call_t *)linux_fsetxattr, AUE_FSETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 228 = linux_fsetxattr */ + { AS(linux_getxattr_args), (sy_call_t *)linux_getxattr, AUE_GETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 229 = linux_getxattr */ + { AS(linux_lgetxattr_args), (sy_call_t *)linux_lgetxattr, AUE_LGETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 230 = linux_lgetxattr */ + { AS(linux_fgetxattr_args), (sy_call_t *)linux_fgetxattr, AUE_FGETXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 231 = linux_fgetxattr */ + { AS(linux_listxattr_args), (sy_call_t *)linux_listxattr, AUE_LISTXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 232 = linux_listxattr */ + { AS(linux_llistxattr_args), (sy_call_t *)linux_llistxattr, AUE_LLISTXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 233 = linux_llistxattr */ + { AS(linux_flistxattr_args), (sy_call_t *)linux_flistxattr, AUE_FLISTXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 234 = linux_flistxattr */ + { AS(linux_removexattr_args), (sy_call_t *)linux_removexattr, AUE_REMOVEXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 235 = linux_removexattr */ + { AS(linux_lremovexattr_args), (sy_call_t *)linux_lremovexattr, AUE_LREMOVEXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 236 = linux_lremovexattr */ + { AS(linux_fremovexattr_args), (sy_call_t *)linux_fremovexattr, AUE_FREMOVEXATTR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 237 = linux_fremovexattr */ { AS(linux_tkill_args), (sy_call_t *)linux_tkill, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 238 = linux_tkill */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 239 = linux_sendfile64 */ { AS(linux_sys_futex_args), (sy_call_t *)linux_sys_futex, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 240 = linux_sys_futex */ Index: sys/i386/linux/linux_sysvec.c =================================================================== --- sys/i386/linux/linux_sysvec.c +++ sys/i386/linux/linux_sysvec.c @@ -145,7 +145,7 @@ -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, - -6, -6, -43, -42, -75,-125, -84, -95, -16, -74, + -6, -6, -43, -42, -75,-125, -84, -61, -16, -74, -72, -67, -71 }; Index: sys/kern/vfs_extattr.c =================================================================== --- sys/kern/vfs_extattr.c +++ sys/kern/vfs_extattr.c @@ -155,9 +155,9 @@ * Locks: none * References: vp must be a valid reference for the duration of the call */ -static int +int extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, - void *data, size_t nbytes, struct thread *td) + void *data, size_t nbytes, enum uio_seg segflg, struct thread *td) { struct mount *mp; struct uio auio; @@ -181,7 +181,7 @@ } auio.uio_resid = nbytes; auio.uio_rw = UIO_WRITE; - auio.uio_segflg = UIO_USERSPACE; + auio.uio_segflg = segflg; auio.uio_td = td; cnt = nbytes; @@ -232,7 +232,7 @@ return (error); error = extattr_set_vp(fp->f_vnode, uap->attrnamespace, - attrname, uap->data, uap->nbytes, td); + attrname, uap->data, uap->nbytes, UIO_USERSPACE, td); fdrop(fp, td); return (error); @@ -267,7 +267,7 @@ NDFREE(&nd, NDF_ONLY_PNBUF); error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname, - uap->data, uap->nbytes, td); + uap->data, uap->nbytes, UIO_USERSPACE, td); vrele(nd.ni_vp); return (error); @@ -302,7 +302,7 @@ NDFREE(&nd, NDF_ONLY_PNBUF); error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname, - uap->data, uap->nbytes, td); + uap->data, uap->nbytes, UIO_USERSPACE, td); vrele(nd.ni_vp); return (error); @@ -318,9 +318,9 @@ * Locks: none * References: vp must be a valid reference for the duration of the call */ -static int +int extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, - void *data, size_t nbytes, struct thread *td) + void *data, size_t nbytes, enum uio_seg segflg, struct thread *td) { struct uio auio, *auiop; struct iovec aiov; @@ -350,7 +350,7 @@ } auio.uio_resid = nbytes; auio.uio_rw = UIO_READ; - auio.uio_segflg = UIO_USERSPACE; + auio.uio_segflg = segflg; auio.uio_td = td; auiop = &auio; cnt = nbytes; @@ -407,7 +407,7 @@ return (error); error = extattr_get_vp(fp->f_vnode, uap->attrnamespace, - attrname, uap->data, uap->nbytes, td); + attrname, uap->data, uap->nbytes, UIO_USERSPACE, td); fdrop(fp, td); return (error); @@ -441,7 +441,7 @@ NDFREE(&nd, NDF_ONLY_PNBUF); error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname, - uap->data, uap->nbytes, td); + uap->data, uap->nbytes, UIO_USERSPACE, td); vrele(nd.ni_vp); return (error); @@ -476,7 +476,7 @@ NDFREE(&nd, NDF_ONLY_PNBUF); error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname, - uap->data, uap->nbytes, td); + uap->data, uap->nbytes, UIO_USERSPACE, td); vrele(nd.ni_vp); return (error); @@ -492,7 +492,7 @@ * Locks: none * References: vp must be a valid reference for the duration of the call */ -static int +int extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname, struct thread *td) { @@ -626,9 +626,9 @@ * Locks: none * References: vp must be a valid reference for the duration of the call */ -static int +int extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, - size_t nbytes, struct thread *td) + size_t nbytes, enum uio_seg segflg, struct thread *td) { struct uio auio, *auiop; size_t size, *sizep; @@ -653,7 +653,7 @@ } auio.uio_resid = nbytes; auio.uio_rw = UIO_READ; - auio.uio_segflg = UIO_USERSPACE; + auio.uio_segflg = segflg; auio.uio_td = td; auiop = &auio; cnt = nbytes; @@ -680,7 +680,6 @@ return (error); } - int sys_extattr_list_fd(td, uap) struct thread *td; @@ -703,7 +702,7 @@ return (error); error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data, - uap->nbytes, td); + uap->nbytes, UIO_USERSPACE, td); fdrop(fp, td); return (error); @@ -730,7 +729,7 @@ NDFREE(&nd, NDF_ONLY_PNBUF); error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data, - uap->nbytes, td); + uap->nbytes, UIO_USERSPACE, td); vrele(nd.ni_vp); return (error); @@ -758,7 +757,7 @@ NDFREE(&nd, NDF_ONLY_PNBUF); error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data, - uap->nbytes, td); + uap->nbytes, UIO_USERSPACE, td); vrele(nd.ni_vp); return (error); 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 Index: sys/sys/extattr.h =================================================================== --- sys/sys/extattr.h +++ sys/sys/extattr.h @@ -61,13 +61,23 @@ #ifdef _KERNEL #include +#include struct thread; struct ucred; struct vnode; int extattr_check_cred(struct vnode *vp, int attrnamespace, struct ucred *cred, struct thread *td, accmode_t accmode); - +int extattr_delete_vp(struct vnode *vp, int attrnamespace, + const char *attrname, struct thread *td); +int extattr_get_vp(struct vnode *vp, int attrnamespace, + const char *attrname, void *data, size_t nbytes, + enum uio_seg segflg, struct thread *td); +int extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, + size_t nbytes, enum uio_seg segflg, struct thread *td); +int extattr_set_vp(struct vnode *vp, int attrnamespace, + const char *attrname, void *data, size_t nbytes, + enum uio_seg segflg, struct thread *td); #else #include