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

Implement NFSv41 ACLs through xattr #10

Merged
merged 5 commits into from
May 24, 2021
Merged
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
modules.order
Makefile
Makefile.in
nfs41acl.h
nfs41acl_xdr.c

#
# Top level generated files specific to this top level dir
Expand Down
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ cstyle:
@find ${top_srcdir} -name build -prune -o -name zfsd -prune \
-o -type f -name '*.[hc]' \
! -name 'zfs_config.*' ! -name '*.mod.c' \
! -name 'nfs41acl_xdr.c' ! -name 'nfs41acl.h' \
! -name 'opt_global.h' ! -name '*_if*.h' \
! -path './module/zstd/lib/*' \
-exec ${top_srcdir}/scripts/cstyle.pl -cpP {} \+
Expand Down
1 change: 1 addition & 0 deletions include/os/linux/spl/rpc/xdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#define _SPL_RPC_XDR_H

#include <sys/types.h>
#include <sys/sysmacros.h>

typedef int bool_t;

Expand Down
2 changes: 2 additions & 0 deletions include/os/linux/zfs/sys/zpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ zpl_chmod_acl(struct inode *ip)
}
#endif /* CONFIG_FS_POSIX_ACL */

extern int zpl_permission(struct inode *ip, int mask);

extern xattr_handler_t *zpl_xattr_handlers[];

/* zpl_ctldir.c */
Expand Down
10 changes: 9 additions & 1 deletion module/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ endif
FMAKE = env -u MAKEFLAGS make $(FMAKEFLAGS)

modules-Linux:
rpcgen -h "@abs_srcdir@/os/linux/zfs/nfs41acl.x" > "@abs_srcdir@/os/linux/zfs/nfs41acl.h"
sed -i "/\<rpc\/rpc.h\>/c\\#include \<rpc\/xdr.h\>" "@abs_srcdir@/os/linux/zfs/nfs41acl.h"
sed -i "9i #include <sys/sysmacros.h>" "@abs_srcdir@/os/linux/zfs/nfs41acl.h"

rpcgen -c "@abs_srcdir@/os/linux/zfs/nfs41acl.x" > "@abs_srcdir@/os/linux/zfs/nfs41acl_xdr.c"
sed -i "5i #pragma GCC diagnostic push" "@abs_srcdir@/os/linux/zfs/nfs41acl_xdr.c"
sed -i "6i #pragma GCC diagnostic ignored \"-Wunused-variable\"" "@abs_srcdir@/os/linux/zfs/nfs41acl_xdr.c"
echo "#pragma GCC diagnostic pop" >> "@abs_srcdir@/os/linux/zfs/nfs41acl_xdr.c"
list='$(SUBDIR_TARGETS)'; for targetdir in $$list; do \
$(MAKE) -C $$targetdir; \
done
Expand Down Expand Up @@ -132,7 +140,7 @@ cppcheck-FreeBSD:
cppcheck: cppcheck-@ac_system@

distdir:
(cd @srcdir@ && find $(ZFS_MODULES) os -name '*.[chS]') | \
(cd @srcdir@ && find $(ZFS_MODULES) os -name '*.[chxS]') | \
while read path; do \
mkdir -p $$distdir/$${path%/*}; \
cp @srcdir@/$$path $$distdir/$$path; \
Expand Down
1 change: 1 addition & 0 deletions module/os/linux/zfs/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ ccflags-$(CONFIG_SPARC64) += -Wno-unused-value
$(MODULE)-objs += ../os/linux/zfs/abd_os.o
$(MODULE)-objs += ../os/linux/zfs/arc_os.o
$(MODULE)-objs += ../os/linux/zfs/mmp_os.o
$(MODULE)-objs += ../os/linux/zfs/nfs41acl_xdr.o
$(MODULE)-objs += ../os/linux/zfs/policy.o
$(MODULE)-objs += ../os/linux/zfs/trace.o
$(MODULE)-objs += ../os/linux/zfs/qat.o
Expand Down
74 changes: 74 additions & 0 deletions module/os/linux/zfs/nfs41acl.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000;
const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001;
const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002;
const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003;

typedef u_int acetype4;

const ACE4_FILE_INHERIT_ACE = 0x00000001;
const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002;
const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004;
const ACE4_INHERIT_ONLY_ACE = 0x00000008;
const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010;
const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020;
const ACE4_IDENTIFIER_GROUP = 0x00000040;
const ACE4_INHERITED_ACE = 0x00000080;

typedef u_int aceflag4;

const ACEI4_SPECIAL_WHO = 0x00000001;

typedef u_int aceiflag4;

const ACE4_SPECIAL_OWNER = 1;
const ACE4_SPECIAL_GROUP = 2;
const ACE4_SPECIAL_EVERYONE = 3;
const ACE4_SPECIAL_INTERACTIVE = 4;
const ACE4_SPECIAL_NETWORK = 5;
const ACE4_SPECIAL_DIALUP = 6;
const ACE4_SPECIAL_BATCH = 7;
const ACE4_SPECIAL_ANONYMOUS = 8;
const ACE4_SPECIAL_AUTHENTICATED = 9;
const ACE4_SPECIAL_SERVICE = 10;

const ACE4_READ_DATA = 0x00000001;
const ACE4_LIST_DIRECTORY = 0x00000001;
const ACE4_WRITE_DATA = 0x00000002;
const ACE4_ADD_FILE = 0x00000002;
const ACE4_APPEND_DATA = 0x00000004;
const ACE4_ADD_SUBDIRECTORY = 0x00000004;
const ACE4_READ_NAMED_ATTRS = 0x00000008;
const ACE4_WRITE_NAMED_ATTRS = 0x00000010;
const ACE4_EXECUTE = 0x00000020;
const ACE4_DELETE_CHILD = 0x00000040;
const ACE4_READ_ATTRIBUTES = 0x00000080;
const ACE4_WRITE_ATTRIBUTES = 0x00000100;
const ACE4_WRITE_RETENTION = 0x00000200;
const ACE4_WRITE_RETENTION_HOLD = 0x00000400;

const ACE4_DELETE = 0x00010000;
const ACE4_READ_ACL = 0x00020000;
const ACE4_WRITE_ACL = 0x00040000;
const ACE4_WRITE_OWNER = 0x00080000;
const ACE4_SYNCHRONIZE = 0x00100000;

typedef u_int acemask4;

struct nfsace4i {
acetype4 type;
aceflag4 flag;
aceiflag4 iflag;
acemask4 access_mask;
u_int who;
};

const ACL4_AUTO_INHERIT = 0x00000001;
const ACL4_PROTECTED = 0x00000002;
const ACL4_DEFAULTED = 0x00000004;

typedef u_int aclflag4;

struct nfsacl41i {
aclflag4 na41_flag;
nfsace4i na41_aces<>;
};
44 changes: 42 additions & 2 deletions module/os/linux/zfs/policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <sys/policy.h>
#include <linux/security.h>
#include <linux/vfs_compat.h>
#include <sys/zfs_znode.h>

/*
* The passed credentials cannot be directly verified because Linux only
Expand Down Expand Up @@ -103,13 +104,52 @@ secpolicy_sys_config(const cred_t *cr, boolean_t checkonly)
* Like secpolicy_vnode_access() but we get the actual wanted mode and the
* current mode of the file, not the missing bits.
*
* Enforced in the Linux VFS.
* If filesystem is using NFSv4 ACLs, validate the current mode
* and the wanted mode are the same, otherwise access fails.
*
* If using POSIX ACLs or no ACLs, enforced in the Linux VFS.
*/
int
secpolicy_vnode_access2(const cred_t *cr, struct inode *ip, uid_t owner,
mode_t curmode, mode_t wantmode)
{
return (0);
mode_t remainder = ~curmode & wantmode;
if ((ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_NFSV4) ||
(remainder == 0)) {
return (0);
}

/*
* short-circuit if root
*/
if (capable(CAP_SYS_ADMIN)) {
return (0);
}

/*
* There are some situations in which capabilities
* may allow overriding the DACL.
*/
if (S_ISDIR(ip->i_mode)) {
if (!(wantmode & S_IWUSR) &&
capable(CAP_DAC_READ_SEARCH)) {
return (0);
}
if (capable(CAP_DAC_OVERRIDE)) {
return (0);
}
return (EACCES);
}

if ((wantmode == S_IRUSR) && capable(CAP_DAC_READ_SEARCH)) {
return (0);
}

if (!(remainder & S_IXUSR) && capable(CAP_DAC_OVERRIDE)) {
return (0);
}

return (EACCES);
}

/*
Expand Down
14 changes: 13 additions & 1 deletion module/os/linux/zfs/zfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,17 @@ acltype_changed_cb(void *arg, uint64_t newval)
zfsvfs_t *zfsvfs = arg;

switch (newval) {
case ZFS_ACLTYPE_NFSV4:
case ZFS_ACLTYPE_OFF:
zfsvfs->z_acl_type = ZFS_ACLTYPE_OFF;
zfsvfs->z_sb->s_flags &= ~SB_POSIXACL;
#ifdef SB_NFSV4ACL
zfsvfs->z_sb->s_flags &= ~SB_NFSV4ACL;
#endif
break;
case ZFS_ACLTYPE_POSIX:
#ifdef SB_NFSV4ACL
zfsvfs->z_sb->s_flags &= ~SB_NFSV4ACL;
#endif
#ifdef CONFIG_FS_POSIX_ACL
zfsvfs->z_acl_type = ZFS_ACLTYPE_POSIX;
zfsvfs->z_sb->s_flags |= SB_POSIXACL;
Expand All @@ -372,6 +377,13 @@ acltype_changed_cb(void *arg, uint64_t newval)
zfsvfs->z_sb->s_flags &= ~SB_POSIXACL;
#endif /* CONFIG_FS_POSIX_ACL */
break;
case ZFS_ACLTYPE_NFSV4:
zfsvfs->z_acl_type = ZFS_ACLTYPE_NFSV4;
zfsvfs->z_sb->s_flags &= ~SB_POSIXACL;
#ifdef SB_NFSV4ACL
zfsvfs->z_sb->s_flags |= SB_NFSV4ACL;
#endif
break;
default:
break;
}
Expand Down
3 changes: 3 additions & 0 deletions module/os/linux/zfs/zpl_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,7 @@ const struct inode_operations zpl_inode_operations = {
#endif /* HAVE_SET_ACL */
.get_acl = zpl_get_acl,
#endif /* CONFIG_FS_POSIX_ACL */
.permission = zpl_permission,
};

const struct inode_operations zpl_dir_inode_operations = {
Expand Down Expand Up @@ -753,6 +754,7 @@ const struct inode_operations zpl_dir_inode_operations = {
#endif /* HAVE_SET_ACL */
.get_acl = zpl_get_acl,
#endif /* CONFIG_FS_POSIX_ACL */
.permission = zpl_permission,
};

const struct inode_operations zpl_symlink_inode_operations = {
Expand Down Expand Up @@ -792,6 +794,7 @@ const struct inode_operations zpl_special_inode_operations = {
#endif /* HAVE_SET_ACL */
.get_acl = zpl_get_acl,
#endif /* CONFIG_FS_POSIX_ACL */
.permission = zpl_permission,
};

dentry_operations_t zpl_dentry_operations = {
Expand Down
3 changes: 3 additions & 0 deletions module/os/linux/zfs/zpl_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ __zpl_show_options(struct seq_file *seq, zfsvfs_t *zfsvfs)
case ZFS_ACLTYPE_POSIX:
seq_puts(seq, ",posixacl");
break;
case ZFS_ACLTYPE_NFSV4:
seq_puts(seq, ",nfs4acl");
break;
default:
seq_puts(seq, ",noacl");
break;
Expand Down
Loading