Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NFSv4 ACL support - WIP, review requested #7728

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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/bash

mount --bind /etc/idmapd-zfs.conf /etc/idmapd.conf
/usr/sbin/nfsidmap "$@"
198 changes: 169 additions & 29 deletions config/kernel-acl.m4
Original file line number Diff line number Diff line change
Expand Up @@ -175,35 +175,6 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION], [
])
])

dnl #
dnl # 2.6.26 API change,
dnl # Check if inode_operations contains the function permission
dnl # and expects the nameidata structure to be passed.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
AC_MSG_CHECKING([whether iops->permission() wants nameidata])
ZFS_LINUX_TRY_COMPILE([
#include <linux/fs.h>
#include <linux/sched.h>

int permission_fn(struct inode *inode, int mask,
struct nameidata *nd) { return 0; }

static const struct inode_operations
iops __attribute__ ((unused)) = {
.permission = permission_fn,
};
],[
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PERMISSION, 1, [iops->permission() exists])
AC_DEFINE(HAVE_PERMISSION_WITH_NAMEIDATA, 1,
[iops->permission() with nameidata exists])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # 2.6.32 API change,
dnl # Check if inode_operations contains the function check_acl
Expand Down Expand Up @@ -324,3 +295,172 @@ AC_DEFUN([ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE], [
AC_MSG_RESULT(no)
])
])

dnl #
dnl # check whether keyring_alloc() takes 8 args
dnl #
AC_DEFUN([ZFS_AC_KERNEL_KEYRING_ALLOC_8_ARGS], [
AC_MSG_CHECKING([whether keyring_alloc() takes 8 args])
ZFS_LINUX_TRY_COMPILE([
#include <linux/cred.h>
#include <linux/key.h>

#ifndef GLOBAL_ROOT_UID
#define GLOBAL_ROOT_UID 0
#endif
#ifndef GLOBAL_ROOT_GID
#define GLOBAL_ROOT_GID 0
#endif
],[
struct key *k;
struct cred c;

k = keyring_alloc("", GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, &c, 0, 0, NULL, NULL);
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_KEYRING_ALLOC_WITH_8_ARGS, 1, [keyring_alloc() takes 8 args])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # check whether user_key_payload() exists
dnl #
AC_DEFUN([ZFS_AC_KERNEL_USER_KEY_PAYLOAD], [
AC_MSG_CHECKING([whether user_key_payload() exists])
ZFS_LINUX_TRY_COMPILE([
#include <keys/user-type.h>
],[
const struct user_key_payload *ukp;
const struct key *k = NULL;

ukp = user_key_payload(k);
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_USER_KEY_PAYLOAD, 1, [user_key_payload() exists])
],[
AC_MSG_RESULT(no)
])
])

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

ukp = user_key_payload_rcu(k);
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_USER_KEY_PAYLOAD_RCU, 1, [user_key_payload_rcu() exists])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # Check whether key subsystem has generic_key_instantiate
dnl #
AC_DEFUN([ZFS_AC_KERNEL_GENERIC_KEY_INSTANTIATE], [
AC_MSG_CHECKING([whether generic_key_instantiate() exists])
ZFS_LINUX_TRY_COMPILE([
#include <linux/key-type.h>
],[
struct key_type k;

k.instantiate = generic_key_instantiate;
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GENERIC_KEY_INSTANTIATE, 1, [generic_key_instantiate() exists])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # Check whether KEY_FLAG_ROOT_CAN_INVAL exists
dnl #
AC_DEFUN([ZFS_AC_KERNEL_KEY_FLAG_ROOT_CAN_INVAL_EXISTS], [
AC_MSG_CHECKING([whether KEY_FLAG_ROOT_CAN_INVAL exists])
ZFS_LINUX_TRY_COMPILE([
#include <linux/key.h>
],[
unsigned long addr;

set_bit(KEY_FLAG_ROOT_CAN_INVAL, &addr);
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_KEY_FLAG_ROOT_CAN_INVAL, 1, [KEY_FLAG_ROOT_CAN_INVAL exists])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # Check whether struct key_preparsed_payload exists
dnl #
AC_DEFUN([ZFS_AC_KERNEL_STRUCT_KEY_PREPARSED_PAYLOAD], [
AC_MSG_CHECKING([whether struct key_preparsed_payload exists])
ZFS_LINUX_TRY_COMPILE([
#include <linux/key-type.h>

int instantiate(struct key *key, struct key_preparsed_payload *prep) { return 0; }
],[
struct key_type k;

k.instantiate = instantiate;
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_STRUCT_KEY_PREPARSED_PAYLOAD, 1, [struct key_preparsed_payload exists])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # Check whether key_is_positive() exists
dnl #
AC_DEFUN([ZFS_AC_KERNEL_KEY_IS_POSITIVE], [
AC_MSG_CHECKING([whether key_is_positive() exists])
ZFS_LINUX_TRY_COMPILE([
#include <linux/key.h>
],[
struct key *k = NULL;
bool v;

v = key_is_positive(k);
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_KEY_IS_POSITIVE, 1, [key_is_positive() exists])
],[
AC_MSG_RESULT(no)
])
])

dnl #
dnl # Check whether generic_permission takes check_acl parameter
dnl #
AC_DEFUN([ZFS_AC_KERNEL_GENERIC_PERMISSION_CHECK_ACL], [
AC_MSG_CHECKING([whether generic_permission takes check_acl parameter])
ZFS_LINUX_TRY_COMPILE([
#include <linux/fs.h>

int check_acl(struct inode *, int);
],[
struct inode *in = NULL;
int i = 0;

i = generic_permission(in, i, check_acl);
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GENERIC_PERMISSION_CHECK_ACL, 1, [generic_permission takes check_acl parameter])
],[
AC_MSG_RESULT(no)
])
])
9 changes: 8 additions & 1 deletion config/kernel.m4
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,14 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
ZFS_AC_KERNEL_POSIX_ACL_CHMOD
ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T
ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS
ZFS_AC_KERNEL_USER_KEY_PAYLOAD
ZFS_AC_KERNEL_USER_KEY_PAYLOAD_RCU
ZFS_AC_KERNEL_GENERIC_KEY_INSTANTIATE
ZFS_AC_KERNEL_KEY_FLAG_ROOT_CAN_INVAL_EXISTS
ZFS_AC_KERNEL_STRUCT_KEY_PREPARSED_PAYLOAD
ZFS_AC_KERNEL_KEY_IS_POSITIVE
ZFS_AC_KERNEL_GENERIC_PERMISSION_CHECK_ACL
ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION
ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA
ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL
ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
Expand All @@ -98,6 +104,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
ZFS_AC_KERNEL_INODE_SET_FLAGS
ZFS_AC_KERNEL_INODE_SET_IVERSION
ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE
ZFS_AC_KERNEL_KEYRING_ALLOC_8_ARGS
ZFS_AC_KERNEL_SHOW_OPTIONS
ZFS_AC_KERNEL_FILE_INODE
ZFS_AC_KERNEL_FILE_DENTRY
Expand Down
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,9 @@ AC_CONFIG_FILES([
tests/zfs-tests/tests/Makefile
tests/zfs-tests/tests/functional/Makefile
tests/zfs-tests/tests/functional/acl/Makefile
tests/zfs-tests/tests/functional/acl/nontrivial/Makefile
tests/zfs-tests/tests/functional/acl/posix/Makefile
tests/zfs-tests/tests/functional/acl/trivial/Makefile
tests/zfs-tests/tests/functional/arc/Makefile
tests/zfs-tests/tests/functional/atime/Makefile
tests/zfs-tests/tests/functional/bootfs/Makefile
Expand Down
19 changes: 19 additions & 0 deletions include/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 @@ -215,6 +219,21 @@ fn(struct inode *ip, const char *name, const void *buffer, \
security_inode_init_security(ip, dip, nm, val, len)
#endif /* HAVE_6ARGS_SECURITY_INODE_INIT_SECURITY */

#ifndef GLOBAL_ROOT_UID
#define GLOBAL_ROOT_UID 0
#endif
#ifndef GLOBAL_ROOT_GID
#define GLOBAL_ROOT_GID 0
#endif

#if defined(HAVE_USER_KEY_PAYLOAD)
#define zpl_user_key_payload_rcu(k) user_key_payload(k)
#elif defined(HAVE_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 /* HAVE_USER_KEY_PAYLOAD */

/*
* 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
9 changes: 9 additions & 0 deletions include/spl/sys/acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ typedef struct ace_object {

#define ACE_ALL_TYPES 0x001F

/*
* 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)

#define ACE_TYPE_FLAGS (ACE_OWNER|ACE_GROUP|ACE_EVERYONE|ACE_IDENTIFIER_GROUP)

/* BEGIN CSTYLED */
Expand Down
1 change: 1 addition & 0 deletions include/sys/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,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/sys/zpl_xattr.h \
$(top_srcdir)/include/sys/zrlock.h \
$(top_srcdir)/include/sys/zthr.h

Expand Down
2 changes: 1 addition & 1 deletion include/sys/fs/zfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ typedef enum {
ZFS_PROP_READONLY,
ZFS_PROP_ZONED,
ZFS_PROP_SNAPDIR,
ZFS_PROP_PRIVATE, /* not exposed to user, temporary */
ZFS_PROP_ACLMODE,
ZFS_PROP_ACLINHERIT,
ZFS_PROP_CREATETXG,
ZFS_PROP_NAME, /* not exposed to the user */
Expand Down
19 changes: 18 additions & 1 deletion include/sys/zfs_acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,23 @@
#include <sys/zfs_fuid.h>
#include <sys/sa.h>

/*
* Only include native NFS4 ACL support if underlying kernel will support it.
*
* It seems if CONFIG_PREEMPT_RCU is defined you end up with this error:
*
* FATAL: modpost: GPL-incompatible module zfs.ko uses GPL-only symbol
* '__rcu_read_lock'
*
* I'm not sure how to work around that, that functionality seems a bit
* too complicated to duplicate.
*
* XXX - what other kernel config should be checked?
*/
#if defined(CONFIG_KEYS) && !defined(CONFIG_PREEMPT_RCU)
#define ZFS_NFS4_ACL
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -220,7 +237,7 @@ int zfs_fastaccesschk_execute(struct znode *, cred_t *);
extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *);
extern int zfs_zaccess_unix(struct znode *, mode_t, cred_t *);
extern int zfs_acl_access(struct znode *, int, cred_t *);
void zfs_acl_chmod_setattr(struct znode *, zfs_acl_t **, uint64_t);
int zfs_acl_chmod_setattr(struct znode *, zfs_acl_t **, uint64_t);
int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *);
int zfs_zaccess_rename(struct znode *, struct znode *,
struct znode *, struct znode *, cred_t *cr);
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
1 change: 1 addition & 0 deletions include/sys/zfs_vfsops.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ struct zfsvfs {
boolean_t z_fuid_dirty; /* need to sync fuid table ? */
struct zfs_fuid_info *z_fuid_replay; /* fuid info for replay */
zilog_t *z_log; /* intent log pointer */
uint_t z_acl_mode; /* acl chmod/mode behavior */
uint_t z_acl_inherit; /* acl inheritance behavior */
uint_t z_acl_type; /* type of ACL usable on this FS */
zfs_case_t z_case; /* case-sense */
Expand Down
10 changes: 5 additions & 5 deletions include/sys/zpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,7 @@ extern struct posix_acl *zpl_get_acl(struct inode *ip, int type);
extern int zpl_check_acl(struct inode *inode, int mask, unsigned int flags);
#elif defined(HAVE_CHECK_ACL)
extern int zpl_check_acl(struct inode *inode, int mask);
#elif defined(HAVE_PERMISSION_WITH_NAMEIDATA)
extern int zpl_permission(struct inode *ip, int mask, struct nameidata *nd);
#elif defined(HAVE_PERMISSION)
extern int zpl_permission(struct inode *ip, int mask);
#endif /* HAVE_CHECK_ACL | HAVE_PERMISSION */
#endif /* HAVE_CHECK_ACL */
#endif /* HAVE_GET_ACL */

extern int zpl_init_acl(struct inode *ip, struct inode *dir);
Expand All @@ -105,6 +101,10 @@ zpl_chmod_acl(struct inode *ip)
}
#endif /* CONFIG_FS_POSIX_ACL */

#if defined(ZFS_NFS4_ACL) && defined(HAVE_PERMISSION)
extern int zpl_permission(struct inode *ip, int mask);
#endif /* ZFS_NFS4_ACL & HAVE_PERMISSION */

extern xattr_handler_t *zpl_xattr_handlers[];

/* zpl_ctldir.c */
Expand Down
Loading