Skip to content

Commit

Permalink
Implements zfs native NFSv4 ACL support by providing an xattr handler
Browse files Browse the repository at this point in the history
for the system.nfs4_acl attribute. ACLs can be manipulated using the
existing nfs4-acl-tools package.

Closes #4966

Signed-off-by: Paul B. Henson <[email protected]>
  • Loading branch information
pbhenson committed Apr 28, 2020
1 parent 10f31ea commit e24fd00
Show file tree
Hide file tree
Showing 19 changed files with 1,141 additions and 38 deletions.
1 change: 1 addition & 0 deletions cmd/nfsidmap.zfs/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist_sbin_SCRIPTS = nfsidmap.zfs
4 changes: 4 additions & 0 deletions cmd/nfsidmap.zfs/nfsidmap.zfs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh

mount --bind /etc/idmapd-zfs.conf /etc/idmapd.conf
/usr/sbin/nfsidmap "$@"
168 changes: 168 additions & 0 deletions config/kernel-acl.m4
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,82 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [
])
])

dnl #
dnl # 3.17 API change,
dnl # check whether generic_key_instantiate() exists
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_KEY_INSTANTIATE], [
ZFS_LINUX_TEST_SRC([generic_key_instantiate], [
#include <linux/key-type.h>
],[
struct key_type k;
k.instantiate = generic_key_instantiate;
])
])

AC_DEFUN([ZFS_AC_KERNEL_GENERIC_KEY_INSTANTIATE], [
AC_MSG_CHECKING([whether generic_key_instantiate() exists])
ZFS_LINUX_TEST_RESULT([generic_key_instantiate], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_KERNEL_GENERIC_KEY_INSTANTIATE, 1,
[generic_key_instantiate() exists])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # 3.17 API change,
dnl # check whether KEY_FLAG_ROOT_CAN_INVAL exists
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_KEY_FLAG_ROOT_CAN_INVAL_EXISTS], [
ZFS_LINUX_TEST_SRC([KEY_FLAG_ROOT_CAN_INVAL], [
#include <linux/key.h>
],[
unsigned long addr;
set_bit(KEY_FLAG_ROOT_CAN_INVAL, &addr);
])
])

AC_DEFUN([ZFS_AC_KERNEL_KEY_FLAG_ROOT_CAN_INVAL_EXISTS], [
AC_MSG_CHECKING([whether HAVE_KEY_FLAG_ROOT_CAN_INVAL exists])
ZFS_LINUX_TEST_RESULT([KEY_FLAG_ROOT_CAN_INVAL], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_KERNEL_KEY_FLAG_ROOT_CAN_INVAL, 1,
[HAVE_KEY_FLAG_ROOT_CAN_INVAL exists])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # 4.4 API change,
dnl # check whether user_key_payload() exists
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_USER_KEY_PAYLOAD], [
ZFS_LINUX_TEST_SRC([user_key_payload], [
#include <keys/user-type.h>
],[
const struct user_key_payload *ukp;
const struct key *k = NULL;
ukp = user_key_payload(k);
])
])

AC_DEFUN([ZFS_AC_KERNEL_USER_KEY_PAYLOAD], [
AC_MSG_CHECKING([whether user_key_payload() exists])
ZFS_LINUX_TEST_RESULT([user_key_payload], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_KERNEL_USER_KEY_PAYLOAD, 1,
[user_key_payload() exists])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # 4.7 API change,
dnl # The kernel get_acl will now check cache before calling i_op->get_acl and
Expand All @@ -239,6 +315,86 @@ AC_DEFUN([ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE], [
])
])

dnl #
dnl # 4.7 API change,
dnl # keyring_alloc() takes 8 args instead of 7
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_KEYRING_ALLOC_8_ARGS], [
ZFS_LINUX_TEST_SRC([keyring_alloc_8_args], [
#include <linux/cred.h>
#include <linux/key.h>
],[
struct key *k;
struct cred c;
k = keyring_alloc("", GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, &c, 0,
0, NULL, NULL);
])
])

AC_DEFUN([ZFS_AC_KERNEL_KEYRING_ALLOC_8_ARGS], [
AC_MSG_CHECKING([whether keyring_alloc() takes 8 args])
ZFS_LINUX_TEST_RESULT([keyring_alloc_8_args], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_KERNEL_KEYRING_ALLOC_WITH_8_ARGS, 1,
[keyring_alloc() takes 8 args])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # 4.11 API change,
dnl # check whether user_key_payload_rcu() exists
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_USER_KEY_PAYLOAD_RCU], [
ZFS_LINUX_TEST_SRC([user_key_payload_rcu], [
#include <keys/user-type.h>
],[
const struct user_key_payload *ukp;
const struct key *k = NULL;
ukp = user_key_payload_rcu(k);
])
])

AC_DEFUN([ZFS_AC_KERNEL_USER_KEY_PAYLOAD_RCU], [
AC_MSG_CHECKING([whether user_key_payload_rcu() exists])
ZFS_LINUX_TEST_RESULT([user_key_payload_rcu], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_KERNEL_USER_KEY_PAYLOAD_RCU, 1,
[user_key_payload_rcu() exists])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # 4.13.10 API change,
dnl # check whether key_is_positive() exists
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_KEY_IS_POSITIVE], [
ZFS_LINUX_TEST_SRC([key_is_positive], [
#include <linux/key.h>
],[
struct key *k = NULL;
bool v;
v = key_is_positive(k);
])
])

AC_DEFUN([ZFS_AC_KERNEL_KEY_IS_POSITIVE], [
AC_MSG_CHECKING([whether key_is_positive() exists])
ZFS_LINUX_TEST_RESULT([key_is_positive], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_KERNEL_KEY_IS_POSITIVE, 1,
[key_is_positive() exists])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # 4.16 kernel: check if struct posix_acl acl.a_refcount is a refcount_t.
dnl # It's an atomic_t on older kernels.
Expand Down Expand Up @@ -272,7 +428,13 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_ACL], [
ZFS_AC_KERNEL_SRC_POSIX_ACL_VALID_WITH_NS
ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL
ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL
ZFS_AC_KERNEL_SRC_GENERIC_KEY_INSTANTIATE
ZFS_AC_KERNEL_SRC_KEY_FLAG_ROOT_CAN_INVAL_EXISTS
ZFS_AC_KERNEL_SRC_USER_KEY_PAYLOAD
ZFS_AC_KERNEL_SRC_GET_ACL_HANDLE_CACHE
ZFS_AC_KERNEL_SRC_KEYRING_ALLOC_8_ARGS
ZFS_AC_KERNEL_SRC_USER_KEY_PAYLOAD_RCU
ZFS_AC_KERNEL_SRC_KEY_IS_POSITIVE
ZFS_AC_KERNEL_SRC_ACL_HAS_REFCOUNT
])

Expand All @@ -284,6 +446,12 @@ AC_DEFUN([ZFS_AC_KERNEL_ACL], [
ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS
ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL
ZFS_AC_KERNEL_GENERIC_KEY_INSTANTIATE
ZFS_AC_KERNEL_KEY_FLAG_ROOT_CAN_INVAL_EXISTS
ZFS_AC_KERNEL_USER_KEY_PAYLOAD
ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE
ZFS_AC_KERNEL_KEYRING_ALLOC_8_ARGS
ZFS_AC_KERNEL_USER_KEY_PAYLOAD_RCU
ZFS_AC_KERNEL_KEY_IS_POSITIVE
ZFS_AC_KERNEL_ACL_HAS_REFCOUNT
])
35 changes: 35 additions & 0 deletions config/kernel-config-defined.m4
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEFINED], [
ZFS_AC_KERNEL_SRC_CONFIG_TRIM_UNUSED_KSYMS
ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_INFLATE
ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_DEFLATE
ZFS_AC_KERNEL_SRC_ZFS_NFS4_ACL
AC_MSG_CHECKING([for kernel config option compatibility])
ZFS_LINUX_TEST_COMPILE_ALL([config])
Expand All @@ -34,6 +35,7 @@ AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEFINED], [
ZFS_AC_KERNEL_CONFIG_TRIM_UNUSED_KSYMS
ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE
ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE
ZFS_AC_KERNEL_ZFS_NFS4_ACL
])

dnl #
Expand Down Expand Up @@ -181,3 +183,36 @@ AC_DEFUN([ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE], [
*** Rebuild the kernel with CONFIG_ZLIB_DEFLATE=y|m set.])
])
])

dnl #
dnl # Check if ZFS_NFS4_ACL should be defined
dnl #
dnl # This requires CONFIG_KEYS to be enabled and
dnl # CONFIG_PREEMPT_RCU to be disabled. The key subsystem is used
dnl # to map between uid/gid values and user/group names, and
dnl # if CONFIG_PREEMPT_RCU compiling will result in the error:
dnl #
dnl # FATAL: modpost: GPL-incompatible module zfs.ko uses GPL-only symbol
dnl # __rcu_read_lock'
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_ZFS_NFS4_ACL], [
ZFS_LINUX_TEST_SRC([zfs_nfs4_acl], [
#if !defined(CONFIG_KEYS)
#error CONFIG_KEYS required for ZFS ACL support
#endif
#if defined(CONFIG_PREEMPT_RCU)
#error CONFIG_PREEMPT_RCU not compatible with ZFS ACL support
#endif
],[])
])

AC_DEFUN([ZFS_AC_KERNEL_ZFS_NFS4_ACL], [
AC_MSG_CHECKING([whether kernel options for ZFS ACLs are set])
ZFS_LINUX_TEST_RESULT([zfs_nfs4_acl], [
AC_MSG_RESULT([yes])
AC_DEFINE(ZFS_NFS4_ACL, 1, [kernel options for ZFS ACLs are set])
],[
AC_MSG_RESULT([no])
])
])

17 changes: 17 additions & 0 deletions include/os/linux/kernel/linux/xattr_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
#ifndef _ZFS_XATTR_H
#define _ZFS_XATTR_H

#include <linux/key.h>
#include <linux/keyctl.h>
#include <linux/key-type.h>
#include <keys/user-type.h>
#include <linux/posix_acl_xattr.h>

/*
Expand Down Expand Up @@ -164,6 +168,19 @@ fn(struct dentry *dentry, const char *name, const void *buffer, \
#error "Unsupported kernel"
#endif

/*
* Linux 4.4 and 4.11 API changes; rcu_dereference_key became
* user_key_payload in 4.4 and then changed to user_key_payload_rcu
* in 4.11.
*/
#if defined(HAVE_KERNEL_USER_KEY_PAYLOAD)
#define zpl_user_key_payload_rcu(k) user_key_payload(k)
#elif defined(HAVE_KERNEL_USER_KEY_PAYLOAD_RCU)
#define zpl_user_key_payload_rcu(k) user_key_payload_rcu(k)
#else
#define zpl_user_key_payload_rcu(k) rcu_dereference_key(k)
#endif

/*
* Linux 3.7 API change. posix_acl_{from,to}_xattr gained the user_ns
* parameter. All callers are expected to pass the &init_user_ns which
Expand Down
25 changes: 25 additions & 0 deletions include/os/linux/spl/sys/acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ typedef struct ace_object {
#define ACE_READ_NAMED_ATTRS 0x00000008
#define ACE_WRITE_NAMED_ATTRS 0x00000010
#define ACE_EXECUTE 0x00000020
#define ACE_TRAVERSE 0x00000020
#define ACE_DELETE_CHILD 0x00000040
#define ACE_READ_ATTRIBUTES 0x00000080
#define ACE_WRITE_ATTRIBUTES 0x00000100
Expand Down Expand Up @@ -109,6 +110,30 @@ typedef struct ace_object {
ACE_WRITE_NAMED_ATTRS|ACE_EXECUTE|ACE_DELETE_CHILD|ACE_READ_ATTRIBUTES| \
ACE_WRITE_ATTRIBUTES|ACE_DELETE|ACE_READ_ACL|ACE_WRITE_ACL| \
ACE_WRITE_OWNER|ACE_SYNCHRONIZE)

#define ACE_ALL_WRITE_PERMS (ACE_WRITE_DATA|ACE_APPEND_DATA| \
ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS|ACE_WRITE_ACL| \
ACE_WRITE_OWNER|ACE_DELETE|ACE_DELETE_CHILD)

#define ACE_READ_PERMS (ACE_READ_DATA|ACE_READ_ACL|ACE_READ_ATTRIBUTES| \
ACE_READ_NAMED_ATTRS)

#define ACE_WRITE_PERMS (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES| \
ACE_WRITE_NAMED_ATTRS)

#define ACE_MODIFY_PERMS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \
ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_READ_NAMED_ATTRS| \
ACE_WRITE_NAMED_ATTRS|ACE_EXECUTE|ACE_DELETE_CHILD|ACE_READ_ATTRIBUTES| \
ACE_WRITE_ATTRIBUTES|ACE_DELETE|ACE_READ_ACL|ACE_SYNCHRONIZE)

/*
* The following flags are supported by both NFSv4 ACLs and ace_t.
*/
#define ACE_NFSV4_SUP_FLAGS (ACE_FILE_INHERIT_ACE | \
ACE_DIRECTORY_INHERIT_ACE | \
ACE_NO_PROPAGATE_INHERIT_ACE | \
ACE_INHERIT_ONLY_ACE | \
ACE_IDENTIFIER_GROUP)
/* END CSTYLED */

#define VSA_ACE 0x0010
Expand Down
3 changes: 3 additions & 0 deletions include/os/linux/zfs/sys/zpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ zpl_chmod_acl(struct inode *ip)
return (0);
}
#endif /* CONFIG_FS_POSIX_ACL */
#if defined(ZFS_NFS4_ACL)
extern int zpl_permission(struct inode *ip, int mask);
#endif /* ZFS_NFS4_ACL */

extern xattr_handler_t *zpl_xattr_handlers[];

Expand Down
28 changes: 28 additions & 0 deletions include/os/linux/zfs/sys/zpl_xattr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/

#ifndef _ZPL_XATTR_H
#define _ZPL_XATTR_H

int zpl_xattr_init(void);
void zpl_xattr_fini(void);

#endif /* _ZPL_XATTR_H */
1 change: 1 addition & 0 deletions include/sys/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ COMMON_H = \
$(top_srcdir)/include/sys/zio.h \
$(top_srcdir)/include/sys/zio_impl.h \
$(top_srcdir)/include/sys/zio_priority.h \
$(top_srcdir)/include/os/linux/zfs/sys/zpl_xattr.h \
$(top_srcdir)/include/sys/zrlock.h \
$(top_srcdir)/include/sys/zthr.h

Expand Down
1 change: 1 addition & 0 deletions include/sys/zfs_ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ extern "C" {
*/
#define ZFS_ACLTYPE_OFF 0
#define ZFS_ACLTYPE_POSIXACL 1
#define ZFS_ACLTYPE_NFS4ACL 2

/*
* Field manipulation macros for the drr_versioninfo field of the
Expand Down
Loading

0 comments on commit e24fd00

Please sign in to comment.