summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2020-05-16 18:31:45 +0000
committerchristos <christos@NetBSD.org>2020-05-16 18:31:45 +0000
commitb9c1fd7f6063b39068aa1bbfd4959302f09c6a3e (patch)
treee2c01613d269741cd222c327acb0c000e7b7d4f0
parent3dcf34bf0155178c8bca57d98f98729ebf027421 (diff)
Add ACL support for FFS. From FreeBSD.
-rw-r--r--bin/Makefile8
-rw-r--r--bin/cp/cp.c24
-rw-r--r--bin/cp/extern.h4
-rw-r--r--bin/cp/utils.c148
-rw-r--r--bin/getfacl/Makefile6
-rw-r--r--bin/getfacl/getfacl.1138
-rw-r--r--bin/getfacl/getfacl.c348
-rw-r--r--bin/ls/ls.116
-rw-r--r--bin/ls/print.c78
-rw-r--r--bin/setfacl/Makefile7
-rw-r--r--bin/setfacl/file.c82
-rw-r--r--bin/setfacl/mask.c120
-rw-r--r--bin/setfacl/merge.c299
-rw-r--r--bin/setfacl/remove.c179
-rw-r--r--bin/setfacl/setfacl.1517
-rw-r--r--bin/setfacl/setfacl.c511
-rw-r--r--bin/setfacl/setfacl.h64
-rw-r--r--bin/setfacl/util.c85
-rw-r--r--distrib/sets/lists/base/mi4
-rw-r--r--distrib/sets/lists/comp/mi170
-rw-r--r--distrib/sets/lists/debug/mi4
-rw-r--r--distrib/sets/lists/man/mi8
-rw-r--r--external/bsd/libarchive/include/config_netbsd.h82
-rw-r--r--external/bsd/libarchive/lib/libarchive/Makefile3
-rw-r--r--external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c2
-rw-r--r--external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c20
-rw-r--r--external/cddl/osnet/sys/kern/policy.c4
-rw-r--r--external/cddl/osnet/sys/sys/policy.h4
-rw-r--r--include/mntopts.h4
-rw-r--r--include/unistd.h3
-rw-r--r--lib/libc/Makefile3
-rw-r--r--lib/libc/posix1e/Makefile.inc89
-rw-r--r--lib/libc/posix1e/acl.3307
-rw-r--r--lib/libc/posix1e/acl_add_flag_np.398
-rw-r--r--lib/libc/posix1e/acl_add_perm.3129
-rw-r--r--lib/libc/posix1e/acl_branding.c175
-rw-r--r--lib/libc/posix1e/acl_calc_mask.398
-rw-r--r--lib/libc/posix1e/acl_calc_mask.c136
-rw-r--r--lib/libc/posix1e/acl_clear_flags_np.379
-rw-r--r--lib/libc/posix1e/acl_clear_perms.379
-rw-r--r--lib/libc/posix1e/acl_compat.c69
-rw-r--r--lib/libc/posix1e/acl_copy.c91
-rw-r--r--lib/libc/posix1e/acl_copy_entry.385
-rw-r--r--lib/libc/posix1e/acl_create_entry.398
-rw-r--r--lib/libc/posix1e/acl_delete.3140
-rw-r--r--lib/libc/posix1e/acl_delete.c84
-rw-r--r--lib/libc/posix1e/acl_delete_entry.3101
-rw-r--r--lib/libc/posix1e/acl_delete_entry.c165
-rw-r--r--lib/libc/posix1e/acl_delete_flag_np.384
-rw-r--r--lib/libc/posix1e/acl_delete_perm.384
-rw-r--r--lib/libc/posix1e/acl_dup.3110
-rw-r--r--lib/libc/posix1e/acl_entry.c151
-rw-r--r--lib/libc/posix1e/acl_flag.c161
-rw-r--r--lib/libc/posix1e/acl_free.389
-rw-r--r--lib/libc/posix1e/acl_free.c59
-rw-r--r--lib/libc/posix1e/acl_from_text.3130
-rw-r--r--lib/libc/posix1e/acl_from_text.c318
-rw-r--r--lib/libc/posix1e/acl_from_text_nfs4.c289
-rw-r--r--lib/libc/posix1e/acl_get.3168
-rw-r--r--lib/libc/posix1e/acl_get.c221
-rw-r--r--lib/libc/posix1e/acl_get_brand_np.386
-rw-r--r--lib/libc/posix1e/acl_get_entry.3145
-rw-r--r--lib/libc/posix1e/acl_get_entry_type_np.380
-rw-r--r--lib/libc/posix1e/acl_get_flag_np.394
-rw-r--r--lib/libc/posix1e/acl_get_flagset_np.383
-rw-r--r--lib/libc/posix1e/acl_get_perm_np.394
-rw-r--r--lib/libc/posix1e/acl_get_permset.383
-rw-r--r--lib/libc/posix1e/acl_get_qualifier.3140
-rw-r--r--lib/libc/posix1e/acl_get_tag_type.385
-rw-r--r--lib/libc/posix1e/acl_id_to_name.c105
-rw-r--r--lib/libc/posix1e/acl_init.3111
-rw-r--r--lib/libc/posix1e/acl_init.c94
-rw-r--r--lib/libc/posix1e/acl_is_trivial_np.385
-rw-r--r--lib/libc/posix1e/acl_perm.c133
-rw-r--r--lib/libc/posix1e/acl_set.3157
-rw-r--r--lib/libc/posix1e/acl_set.c258
-rw-r--r--lib/libc/posix1e/acl_set_entry_type_np.394
-rw-r--r--lib/libc/posix1e/acl_set_flagset_np.385
-rw-r--r--lib/libc/posix1e/acl_set_permset.381
-rw-r--r--lib/libc/posix1e/acl_set_qualifier.391
-rw-r--r--lib/libc/posix1e/acl_set_tag_type.3102
-rw-r--r--lib/libc/posix1e/acl_strip.c222
-rw-r--r--lib/libc/posix1e/acl_strip_np.3109
-rw-r--r--lib/libc/posix1e/acl_support.c423
-rw-r--r--lib/libc/posix1e/acl_support.h70
-rw-r--r--lib/libc/posix1e/acl_support_nfs4.c267
-rw-r--r--lib/libc/posix1e/acl_to_text.3159
-rw-r--r--lib/libc/posix1e/acl_to_text.c267
-rw-r--r--lib/libc/posix1e/acl_to_text_nfs4.c271
-rw-r--r--lib/libc/posix1e/acl_valid.3170
-rw-r--r--lib/libc/posix1e/acl_valid.c129
-rw-r--r--lib/libc/posix1e/extattr.3100
-rw-r--r--lib/libc/posix1e/extattr.c83
-rw-r--r--lib/libc/posix1e/posix1e.3118
-rw-r--r--lib/libc/sys/Makefile.inc12
-rwxr-xr-xlib/libc/sys/makelintstub3
-rw-r--r--sbin/mount_ffs/mount_ffs.c6
-rw-r--r--sbin/tunefs/tunefs.810
-rw-r--r--sbin/tunefs/tunefs.c95
-rw-r--r--sys/arch/amd64/amd64/genassym.cf3
-rw-r--r--sys/arch/amd64/conf/GENERIC5
-rw-r--r--sys/coda/coda_vnops.c14
-rw-r--r--sys/compat/netbsd32/files.netbsd323
-rw-r--r--sys/compat/netbsd32/netbsd32.h3
-rw-r--r--sys/compat/netbsd32/netbsd32_acl.c216
-rw-r--r--sys/compat/netbsd32/netbsd32_netbsd.c19
-rw-r--r--sys/compat/netbsd32/netbsd32_syscall.h43
-rw-r--r--sys/compat/netbsd32/netbsd32_syscallargs.h115
-rw-r--r--sys/compat/netbsd32/netbsd32_syscalls.c56
-rw-r--r--sys/compat/netbsd32/netbsd32_syscalls_autoload.c4
-rw-r--r--sys/compat/netbsd32/netbsd32_sysent.c69
-rw-r--r--sys/compat/netbsd32/netbsd32_systrace_args.c376
-rw-r--r--sys/compat/netbsd32/syscalls.master36
-rw-r--r--sys/fs/adosfs/advnops.c23
-rw-r--r--sys/fs/autofs/autofs_vnops.c5
-rw-r--r--sys/fs/cd9660/cd9660_vnops.c25
-rw-r--r--sys/fs/efs/efs_vnops.c25
-rw-r--r--sys/fs/filecorefs/filecore_vnops.c19
-rw-r--r--sys/fs/hfs/hfs_vnops.c25
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c31
-rw-r--r--sys/fs/nilfs/nilfs_vnops.c27
-rw-r--r--sys/fs/ntfs/ntfs_vnops.c23
-rw-r--r--sys/fs/ptyfs/ptyfs_vnops.c25
-rw-r--r--sys/fs/puffs/puffs_vnops.c16
-rw-r--r--sys/fs/sysvbfs/sysvbfs.c5
-rw-r--r--sys/fs/sysvbfs/sysvbfs_vnops.c26
-rw-r--r--sys/fs/tmpfs/tmpfs_fifoops.c5
-rw-r--r--sys/fs/tmpfs/tmpfs_specops.c5
-rw-r--r--sys/fs/tmpfs/tmpfs_subr.c13
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c19
-rw-r--r--sys/fs/udf/udf_vnops.c29
-rw-r--r--sys/fs/union/union_vnops.c9
-rw-r--r--sys/fs/unionfs/unionfs_vnops.c1
-rw-r--r--sys/fs/v7fs/v7fs_extern.c7
-rw-r--r--sys/fs/v7fs/v7fs_vnops.c36
-rw-r--r--sys/kern/files.kern5
-rw-r--r--sys/kern/init_sysent.c82
-rw-r--r--sys/kern/kern_auth.c17
-rw-r--r--sys/kern/subr_acl_nfs4.c614
-rw-r--r--sys/kern/subr_acl_posix1e.c338
-rw-r--r--sys/kern/sys_mqueue.c14
-rw-r--r--sys/kern/syscalls.c57
-rw-r--r--sys/kern/syscalls.conf4
-rw-r--r--sys/kern/syscalls.master28
-rw-r--r--sys/kern/syscalls_autoload.c5
-rw-r--r--sys/kern/systrace_args.c376
-rw-r--r--sys/kern/vfs_acl.c542
-rw-r--r--sys/kern/vfs_cache.c16
-rw-r--r--sys/kern/vfs_getcwd.c14
-rw-r--r--sys/kern/vfs_init.c8
-rw-r--r--sys/kern/vfs_subr.c66
-rw-r--r--sys/kern/vfs_syscalls.c58
-rw-r--r--sys/kern/vfs_xattr.c8
-rw-r--r--sys/kern/vnode_if.c154
-rw-r--r--sys/kern/vnode_if.sh4
-rw-r--r--sys/kern/vnode_if.src43
-rw-r--r--sys/miscfs/fdesc/fdesc_vnops.c5
-rw-r--r--sys/miscfs/fifofs/fifo_vnops.c5
-rw-r--r--sys/miscfs/genfs/genfs.h26
-rw-r--r--sys/miscfs/genfs/genfs_rename.c6
-rw-r--r--sys/miscfs/genfs/genfs_vnops.c651
-rw-r--r--sys/miscfs/genfs/layer_vnops.c10
-rw-r--r--sys/miscfs/kernfs/kernfs_vnops.c14
-rw-r--r--sys/miscfs/nullfs/null_vnops.c5
-rw-r--r--sys/miscfs/overlay/overlay_vnops.c7
-rw-r--r--sys/miscfs/procfs/procfs_vnops.c13
-rw-r--r--sys/miscfs/specfs/spec_vnops.c5
-rw-r--r--sys/miscfs/umapfs/umap_vnops.c5
-rw-r--r--sys/modules/compat_netbsd32/Makefile3
-rw-r--r--sys/modules/ffs/Makefile4
-rw-r--r--sys/modules/ufs/Makefile6
-rw-r--r--sys/nfs/nfs_vnops.c44
-rw-r--r--sys/rump/fs/lib/libffs/Makefile10
-rw-r--r--sys/rump/include/rump/rump_syscalls.h7
-rw-r--r--sys/rump/include/rump/rumpvnode_if.h14
-rw-r--r--sys/rump/librump/rumpkern/rump_syscalls.c73
-rw-r--r--sys/rump/librump/rumpvfs/Makefile.rumpvfs13
-rw-r--r--sys/rump/librump/rumpvfs/rumpfs.c28
-rw-r--r--sys/rump/librump/rumpvfs/rumpvnode_if.c67
-rw-r--r--sys/rump/rump.sysmap1
-rw-r--r--sys/sys/Makefile4
-rw-r--r--sys/sys/acl.h440
-rw-r--r--sys/sys/ansi.h3
-rw-r--r--sys/sys/extattr.h4
-rw-r--r--sys/sys/fstypes.h16
-rw-r--r--sys/sys/kauth.h6
-rw-r--r--sys/sys/namei.h9
-rw-r--r--sys/sys/namei.src4
-rw-r--r--sys/sys/statvfs.h3
-rw-r--r--sys/sys/syscall.h43
-rw-r--r--sys/sys/syscallargs.h140
-rw-r--r--sys/sys/types.h7
-rw-r--r--sys/sys/unistd.h7
-rw-r--r--sys/sys/vnode.h73
-rw-r--r--sys/sys/vnode_if.h135
-rw-r--r--sys/ufs/chfs/chfs_subr.c4
-rw-r--r--sys/ufs/chfs/chfs_vnode.c8
-rw-r--r--sys/ufs/chfs/chfs_vnops.c24
-rw-r--r--sys/ufs/ext2fs/ext2fs_lookup.c6
-rw-r--r--sys/ufs/ext2fs/ext2fs_vfsops.c8
-rw-r--r--sys/ufs/ext2fs/ext2fs_vnops.c32
-rw-r--r--sys/ufs/ext2fs/ext2fs_xattr.c26
-rw-r--r--sys/ufs/ffs/ffs_extattr.c40
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c56
-rw-r--r--sys/ufs/ffs/ffs_vnops.c23
-rw-r--r--sys/ufs/ffs/fs.h16
-rw-r--r--sys/ufs/files.ufs5
-rw-r--r--sys/ufs/lfs/lfs_vnops.c12
-rw-r--r--sys/ufs/lfs/ulfs_extattr.c68
-rw-r--r--sys/ufs/lfs/ulfs_lookup.c6
-rw-r--r--sys/ufs/lfs/ulfs_vnops.c38
-rw-r--r--sys/ufs/mfs/mfs_vnops.c5
-rw-r--r--sys/ufs/ufs/README.acls79
-rw-r--r--sys/ufs/ufs/acl.h62
-rw-r--r--sys/ufs/ufs/ufs_acl.c698
-rw-r--r--sys/ufs/ufs/ufs_extattr.c67
-rw-r--r--sys/ufs/ufs/ufs_extern.h4
-rw-r--r--sys/ufs/ufs/ufs_lookup.c49
-rw-r--r--sys/ufs/ufs/ufs_vnops.c456
219 files changed, 18084 insertions, 1070 deletions
diff --git a/bin/Makefile b/bin/Makefile
index b7d1b2cc689..d73ad1ede7d 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -1,8 +1,8 @@
-# $NetBSD: Makefile,v 1.22 2007/12/31 15:31:24 ad Exp $
+# $NetBSD: Makefile,v 1.23 2020/05/16 18:31:45 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
-SUBDIR= cat chio chmod cp csh date dd df domainname echo ed expr hostname \
- kill ksh ln ls mkdir mt mv pax ps pwd rcp rcmd rm rmdir sh \
- sleep stty sync test
+SUBDIR= cat chio chmod cp csh date dd df domainname echo ed expr getfacl \
+ hostname kill ksh ln ls mkdir mt mv pax ps pwd rcp rcmd rm rmdir \
+ setfacl sh sleep stty sync test
.include <bsd.subdir.mk>
diff --git a/bin/cp/cp.c b/bin/cp/cp.c
index 2f4fab18103..5170e39a6dd 100644
--- a/bin/cp/cp.c
+++ b/bin/cp/cp.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cp.c,v 1.59 2016/03/05 19:48:55 uwe Exp $ */
+/* $NetBSD: cp.c,v 1.60 2020/05/16 18:31:45 christos Exp $ */
/*
* Copyright (c) 1988, 1993, 1994
@@ -43,7 +43,7 @@ __COPYRIGHT(
#if 0
static char sccsid[] = "@(#)cp.c 8.5 (Berkeley) 4/29/95";
#else
-__RCSID("$NetBSD: cp.c,v 1.59 2016/03/05 19:48:55 uwe Exp $");
+__RCSID("$NetBSD: cp.c,v 1.60 2020/05/16 18:31:45 christos Exp $");
#endif
#endif /* not lint */
@@ -499,9 +499,23 @@ copy(char *argv[], enum op type, int fts_options)
* umask; arguably wrong, but it's been that way
* forever.
*/
- if (pflag && setfile(curr->fts_statp, 0))
- this_failed = any_failed = 1;
- else if ((dne = popdne()))
+ /*
+ * If -p is in effect, set all the attributes.
+ * Otherwise, set the correct permissions, limited
+ * by the umask. Optimise by avoiding a chmod()
+ * if possible (which is usually the case if we
+ * made the directory). Note that mkdir() does not
+ * honour setuid, setgid and sticky bits, but we
+ * normally want to preserve them on directories.
+ */
+ if (pflag) {
+ if (setfile(curr->fts_statp, 0))
+ this_failed = any_failed = 1;
+ if (preserve_dir_acls(curr->fts_statp,
+ curr->fts_accpath, to.p_path) != 0)
+ this_failed = any_failed = 1;
+ }
+ if (this_failed && (dne = popdne()))
(void)chmod(to.p_path,
curr->fts_statp->st_mode);
}
diff --git a/bin/cp/extern.h b/bin/cp/extern.h
index e393844dfd5..aca3f5682f0 100644
--- a/bin/cp/extern.h
+++ b/bin/cp/extern.h
@@ -1,4 +1,4 @@
-/* $NetBSD: extern.h,v 1.17 2012/01/04 15:58:37 christos Exp $ */
+/* $NetBSD: extern.h,v 1.18 2020/05/16 18:31:45 christos Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@@ -55,6 +55,8 @@ int copy_link(FTSENT *, int);
int copy_special(struct stat *, int);
int set_utimes(const char *, struct stat *);
int setfile(struct stat *, int);
+int preserve_dir_acls(struct stat *, char *, char *);
+int preserve_fd_acls(int, int);
void usage(void) __attribute__((__noreturn__));
__END_DECLS
diff --git a/bin/cp/utils.c b/bin/cp/utils.c
index 25f599de23b..fe046c641d4 100644
--- a/bin/cp/utils.c
+++ b/bin/cp/utils.c
@@ -1,4 +1,4 @@
-/* $NetBSD: utils.c,v 1.47 2019/09/23 18:01:09 christos Exp $ */
+/* $NetBSD: utils.c,v 1.48 2020/05/16 18:31:45 christos Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@@ -34,14 +34,16 @@
#if 0
static char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94";
#else
-__RCSID("$NetBSD: utils.c,v 1.47 2019/09/23 18:01:09 christos Exp $");
+__RCSID("$NetBSD: utils.c,v 1.48 2020/05/16 18:31:45 christos Exp $");
#endif
#endif /* not lint */
+#define _ACL_PRIVATE
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/acl.h>
#include <sys/extattr.h>
#include <err.h>
@@ -254,6 +256,9 @@ copy_file(FTSENT *entp, int dne)
if (pflag && (fcpxattr(from_fd, to_fd) != 0))
warn("%s: error copying extended attributes", to.p_path);
+ if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
+ rval = 1;
+
(void)close(from_fd);
if (rval == 1) {
@@ -403,6 +408,145 @@ setfile(struct stat *fs, int fd)
return (rval);
}
+int
+preserve_fd_acls(int source_fd, int dest_fd)
+{
+ acl_t acl;
+ acl_type_t acl_type;
+ int acl_supported = 0, ret, trivial;
+
+ ret = fpathconf(source_fd, _PC_ACL_NFS4);
+ if (ret > 0 ) {
+ acl_supported = 1;
+ acl_type = ACL_TYPE_NFS4;
+ } else if (ret < 0 && errno != EINVAL) {
+ warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", to.p_path);
+ return (1);
+ }
+ if (acl_supported == 0) {
+ ret = fpathconf(source_fd, _PC_ACL_EXTENDED);
+ if (ret > 0 ) {
+ acl_supported = 1;
+ acl_type = ACL_TYPE_ACCESS;
+ } else if (ret < 0 && errno != EINVAL) {
+ warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s",
+ to.p_path);
+ return (1);
+ }
+ }
+ if (acl_supported == 0)
+ return (0);
+
+ acl = acl_get_fd_np(source_fd, acl_type);
+ if (acl == NULL) {
+ warn("failed to get acl entries while setting %s", to.p_path);
+ return (1);
+ }
+ if (acl_is_trivial_np(acl, &trivial)) {
+ warn("acl_is_trivial() failed for %s", to.p_path);
+ acl_free(acl);
+ return (1);
+ }
+ if (trivial) {
+ acl_free(acl);
+ return (0);
+ }
+ if (acl_set_fd_np(dest_fd, acl, acl_type) < 0) {
+ warn("failed to set acl entries for %s", to.p_path);
+ acl_free(acl);
+ return (1);
+ }
+ acl_free(acl);
+ return (0);
+}
+
+int
+preserve_dir_acls(struct stat *fs, char *source_dir, char *dest_dir)
+{
+ acl_t (*aclgetf)(const char *, acl_type_t);
+ int (*aclsetf)(const char *, acl_type_t, acl_t);
+ struct acl *aclp;
+ acl_t acl;
+ acl_type_t acl_type;
+ int acl_supported = 0, ret, trivial;
+
+ ret = pathconf(source_dir, _PC_ACL_NFS4);
+ if (ret > 0) {
+ acl_supported = 1;
+ acl_type = ACL_TYPE_NFS4;
+ } else if (ret < 0 && errno != EINVAL) {
+ warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", source_dir);
+ return (1);
+ }
+ if (acl_supported == 0) {
+ ret = pathconf(source_dir, _PC_ACL_EXTENDED);
+ if (ret > 0) {
+ acl_supported = 1;
+ acl_type = ACL_TYPE_ACCESS;
+ } else if (ret < 0 && errno != EINVAL) {
+ warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s",
+ source_dir);
+ return (1);
+ }
+ }
+ if (acl_supported == 0)
+ return (0);
+
+ /*
+ * If the file is a link we will not follow it.
+ */
+ if (S_ISLNK(fs->st_mode)) {
+ aclgetf = acl_get_link_np;
+ aclsetf = acl_set_link_np;
+ } else {
+ aclgetf = acl_get_file;
+ aclsetf = acl_set_file;
+ }
+ if (acl_type == ACL_TYPE_ACCESS) {
+ /*
+ * Even if there is no ACL_TYPE_DEFAULT entry here, a zero
+ * size ACL will be returned. So it is not safe to simply
+ * check the pointer to see if the default ACL is present.
+ */
+ acl = aclgetf(source_dir, ACL_TYPE_DEFAULT);
+ if (acl == NULL) {
+ warn("failed to get default acl entries on %s",
+ source_dir);
+ return (1);
+ }
+ aclp = &acl->ats_acl;
+ if (aclp->acl_cnt != 0 && aclsetf(dest_dir,
+ ACL_TYPE_DEFAULT, acl) < 0) {
+ warn("failed to set default acl entries on %s",
+ dest_dir);
+ acl_free(acl);
+ return (1);
+ }
+ acl_free(acl);
+ }
+ acl = aclgetf(source_dir, acl_type);
+ if (acl == NULL) {
+ warn("failed to get acl entries on %s", source_dir);
+ return (1);
+ }
+ if (acl_is_trivial_np(acl, &trivial)) {
+ warn("acl_is_trivial() failed on %s", source_dir);
+ acl_free(acl);
+ return (1);
+ }
+ if (trivial) {
+ acl_free(acl);
+ return (0);
+ }
+ if (aclsetf(dest_dir, acl_type, acl) < 0) {
+ warn("failed to set acl entries on %s", dest_dir);
+ acl_free(acl);
+ return (1);
+ }
+ acl_free(acl);
+ return (0);
+}
+
void
usage(void)
{
diff --git a/bin/getfacl/Makefile b/bin/getfacl/Makefile
new file mode 100644
index 00000000000..83567be0a49
--- /dev/null
+++ b/bin/getfacl/Makefile
@@ -0,0 +1,6 @@
+# $NetBSD: Makefile,v 1.1 2020/05/16 18:31:45 christos Exp $
+# $FreeBSD: head/bin/getfacl/Makefile 298107 2016-04-16 07:45:30Z gjb $
+
+PROG= getfacl
+
+.include <bsd.prog.mk>
diff --git a/bin/getfacl/getfacl.1 b/bin/getfacl/getfacl.1
new file mode 100644
index 00000000000..c704ff0ba10
--- /dev/null
+++ b/bin/getfacl/getfacl.1
@@ -0,0 +1,138 @@
+.\" $NetBSD: getfacl.1,v 1.1 2020/05/16 18:31:45 christos Exp $
+.\"-
+.\" Copyright (c) 2000, 2001, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/bin/getfacl/getfacl.1 240085 2012-09-04 12:02:23Z trasz $
+.\"
+.\" Developed by the TrustedBSD Project.
+.\" Support for POSIX.1e access control lists.
+.\"
+.Dd September 4, 2009
+.Dt GETFACL 1
+.Os
+.Sh NAME
+.Nm getfacl
+.Nd get ACL information
+.Sh SYNOPSIS
+.Nm
+.Op Fl dhinqv
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility writes discretionary access control information associated with
+the specified file(s) to standard output.
+If the
+.Xr getconf 1
+utility indicates that
+.Brq Va _POSIX_ACL_EXTENDED
+is not in effect for a
+.Ar file
+then the standard discretionary access permissions are interpreted as
+an ACL containing only the required ACL entries.
+.Pp
+The following option is available:
+.Bl -tag -width indent
+.It Fl d
+The operation applies to the default ACL of a directory instead of the
+access ACL.
+An error is generated if a default ACL cannot be associated with
+.Ar file .
+This option is not valid for NFSv4 ACLs.
+.It Fl h
+If the target of the operation is a symbolic link, return the ACL from
+the symbolic link itself rather than following the link.
+.It Fl i
+For NFSv4 ACLs, append numerical ID at the end of each entry containing
+user or group name.
+Ignored for POSIX.1e ACLs.
+.It Fl n
+Display user and group IDs numerically rather than converting to
+a user or group name.
+Ignored for POSIX.1e ACLs.
+.It Fl q
+Do not write commented information about file name and ownership.
+This is
+useful when dealing with filenames with unprintable characters.
+.It Fl v
+For NFSv4 ACLs, display access mask and flags in a verbose form.
+Ignored for POSIX.1e ACLs.
+.El
+.Pp
+The following operand is available:
+.Bl -tag -width indent
+.It Ar file
+A pathname of a file whose ACL shall be retrieved.
+If
+.Ar file
+is not specified, or a
+.Ar file
+is specified as
+.Fl ,
+then
+.Nm
+reads a list of pathnames, each terminated by one newline character,
+from the standard input.
+.El
+.Pp
+For an explanation of the ACL syntax, see the
+.Xr setfacl 1
+manual page.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+.Dl getfacl /
+.Pp
+Retrieve ACL for the directory
+.Pa / .
+.Pp
+.Dl getfacl -d /
+.Pp
+Retrieve the default ACL for the directory
+.Pa / ,
+if any.
+.Sh SEE ALSO
+.Xr setfacl 1 ,
+.Xr acl 3 ,
+.Xr getextattr 8 ,
+.Xr setextattr 8 ,
+.Xr acl 9 ,
+.Xr extattr 9
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.Tn IEEE
+Std 1003.2c compliant.
+.Sh HISTORY
+Extended Attribute and Access Control List support was developed as part
+of the
+.Tn TrustedBSD
+Project and introduced in
+.Fx 5.0 .
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/bin/getfacl/getfacl.c b/bin/getfacl/getfacl.c
new file mode 100644
index 00000000000..7a28f58672b
--- /dev/null
+++ b/bin/getfacl/getfacl.c
@@ -0,0 +1,348 @@
+/* $NetBSD: getfacl.c,v 1.1 2020/05/16 18:31:45 christos Exp $ */
+
+/*-
+ * Copyright (c) 1999, 2001, 2002 Robert N M Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * getfacl -- POSIX.1e utility to extract ACLs from files and directories
+ * and send the results to stdout
+ */
+
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/bin/getfacl/getfacl.c 340014 2018-11-01 17:45:29Z markj $");
+#else
+__RCSID("$NetBSD: getfacl.c,v 1.1 2020/05/16 18:31:45 christos Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/acl.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int more_than_one = 0;
+
+static __dead void
+usage(void)
+{
+
+ fprintf(stderr, "Usage: %s [-dhnqv] [file ...]\n", getprogname());
+}
+
+static char *
+getuname(uid_t uid)
+{
+ struct passwd *pw;
+ static char uids[10];
+
+ if ((pw = getpwuid(uid)) == NULL) {
+ (void)snprintf(uids, sizeof(uids), "%u", uid);
+ return (uids);
+ } else
+ return (pw->pw_name);
+}
+
+static char *
+getgname(gid_t gid)
+{
+ struct group *gr;
+ static char gids[10];
+
+ if ((gr = getgrgid(gid)) == NULL) {
+ (void)snprintf(gids, sizeof(gids), "%u", gid);
+ return (gids);
+ } else
+ return (gr->gr_name);
+}
+
+/*
+ * return an ACL corresponding to the permissions
+ * contained in struct stat
+ */
+static acl_t
+acl_from_stat(const struct stat *sb)
+{
+ acl_t acl;
+ acl_entry_t entry;
+ acl_permset_t perms;
+
+ /* create the ACL */
+ acl = acl_init(3);
+ if (!acl)
+ return NULL;
+
+ /* First entry: ACL_USER_OBJ */
+ if (acl_create_entry(&acl, &entry) == -1)
+ return NULL;
+ if (acl_set_tag_type(entry, ACL_USER_OBJ) == -1)
+ return NULL;
+
+ if (acl_get_permset(entry, &perms) == -1)
+ return NULL;
+ if (acl_clear_perms(perms) == -1)
+ return NULL;
+
+ /* calculate user mode */
+ if (sb->st_mode & S_IRUSR)
+ if (acl_add_perm(perms, ACL_READ) == -1)
+ return NULL;
+ if (sb->st_mode & S_IWUSR)
+ if (acl_add_perm(perms, ACL_WRITE) == -1)
+ return NULL;
+ if (sb->st_mode & S_IXUSR)
+ if (acl_add_perm(perms, ACL_EXECUTE) == -1)
+ return NULL;
+ if (acl_set_permset(entry, perms) == -1)
+ return NULL;
+
+ /* Second entry: ACL_GROUP_OBJ */
+ if (acl_create_entry(&acl, &entry) == -1)
+ return NULL;
+ if (acl_set_tag_type(entry, ACL_GROUP_OBJ) == -1)
+ return NULL;
+
+ if (acl_get_permset(entry, &perms) == -1)
+ return NULL;
+ if (acl_clear_perms(perms) == -1)
+ return NULL;
+
+ /* calculate group mode */
+ if (sb->st_mode & S_IRGRP)
+ if (acl_add_perm(perms, ACL_READ) == -1)
+ return NULL;
+ if (sb->st_mode & S_IWGRP)
+ if (acl_add_perm(perms, ACL_WRITE) == -1)
+ return NULL;
+ if (sb->st_mode & S_IXGRP)
+ if (acl_add_perm(perms, ACL_EXECUTE) == -1)
+ return NULL;
+ if (acl_set_permset(entry, perms) == -1)
+ return NULL;
+
+ /* Third entry: ACL_OTHER */
+ if (acl_create_entry(&acl, &entry) == -1)
+ return NULL;
+ if (acl_set_tag_type(entry, ACL_OTHER) == -1)
+ return NULL;
+
+ if (acl_get_permset(entry, &perms) == -1)
+ return NULL;
+ if (acl_clear_perms(perms) == -1)
+ return NULL;
+
+ /* calculate other mode */
+ if (sb->st_mode & S_IROTH)
+ if (acl_add_perm(perms, ACL_READ) == -1)
+ return NULL;
+ if (sb->st_mode & S_IWOTH)
+ if (acl_add_perm(perms, ACL_WRITE) == -1)
+ return NULL;
+ if (sb->st_mode & S_IXOTH)
+ if (acl_add_perm(perms, ACL_EXECUTE) == -1)
+ return NULL;
+ if (acl_set_permset(entry, perms) == -1)
+ return NULL;
+
+ return(acl);
+}
+
+static int
+print_acl(char *path, acl_type_t type, int hflag, int iflag, int nflag,
+ int qflag, int vflag)
+{
+ struct stat sb;
+ acl_t acl;
+ char *acl_text;
+ int error, flags = 0, ret;
+
+ if (hflag)
+ error = lstat(path, &sb);
+ else
+ error = stat(path, &sb);
+ if (error == -1) {
+ warn("%s: stat() failed", path);
+ return(-1);
+ }
+
+ if (hflag)
+ ret = lpathconf(path, _PC_ACL_NFS4);
+ else
+ ret = pathconf(path, _PC_ACL_NFS4);
+ if (ret > 0) {
+ if (type == ACL_TYPE_DEFAULT) {
+ warnx("%s: there are no default entries in NFSv4 ACLs",
+ path);
+ return (-1);
+ }
+ type = ACL_TYPE_NFS4;
+ } else if (ret < 0 && errno != EINVAL) {
+ warn("%s: pathconf(..., _PC_ACL_NFS4) failed", path);
+ return (-1);
+ }
+
+ if (more_than_one)
+ printf("\n");
+ else
+ more_than_one++;
+
+ if (!qflag)
+ printf("# file: %s\n# owner: %s\n# group: %s\n", path,
+ getuname(sb.st_uid), getgname(sb.st_gid));
+
+ if (hflag)
+ acl = acl_get_link_np(path, type);
+ else
+ acl = acl_get_file(path, type);
+ if (!acl) {
+ if (errno != EOPNOTSUPP) {
+ warn("%s", path);
+ return(-1);
+ }
+ errno = 0;
+ if (type == ACL_TYPE_DEFAULT)
+ return(0);
+ acl = acl_from_stat(&sb);
+ if (!acl) {
+ warn("%s: acl_from_stat() failed", path);
+ return(-1);
+ }
+ }
+
+ if (iflag)
+ flags |= ACL_TEXT_APPEND_ID;
+
+ if (nflag)
+ flags |= ACL_TEXT_NUMERIC_IDS;
+
+ if (vflag)
+ flags |= ACL_TEXT_VERBOSE;
+
+ acl_text = acl_to_text_np(acl, 0, flags);
+ if (!acl_text) {
+ warn("%s: acl_to_text_np() failed", path);
+ return(-1);
+ }
+
+ printf("%s", acl_text);
+
+ (void)acl_free(acl);
+ (void)acl_free(acl_text);
+
+ return(0);
+}
+
+static int
+print_acl_from_stdin(acl_type_t type, int hflag, int iflag, int nflag,
+ int qflag, int vflag)
+{
+ char *p, pathname[PATH_MAX];
+ int carried_error = 0;
+
+ while (fgets(pathname, (int)sizeof(pathname), stdin)) {
+ if ((p = strchr(pathname, '\n')) != NULL)
+ *p = '\0';
+ if (print_acl(pathname, type, hflag, iflag, nflag,
+ qflag, vflag) == -1) {
+ carried_error = -1;
+ }
+ }
+
+ return(carried_error);
+}
+
+int
+main(int argc, char *argv[])
+{
+ acl_type_t type = ACL_TYPE_ACCESS;
+ int carried_error = 0;
+ int ch, error, i;
+ int hflag, iflag, qflag, nflag, vflag;
+
+ hflag = 0;
+ iflag = 0;
+ qflag = 0;
+ nflag = 0;
+ vflag = 0;
+ while ((ch = getopt(argc, argv, "dhinqv")) != -1)
+ switch(ch) {
+ case 'd':
+ type = ACL_TYPE_DEFAULT;
+ break;
+ case 'h':
+ hflag = 1;
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ default:
+ usage();
+ return(-1);
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ error = print_acl_from_stdin(type, hflag, iflag, nflag,
+ qflag, vflag);
+ return(error ? 1 : 0);
+ }
+
+ for (i = 0; i < argc; i++) {
+ if (!strcmp(argv[i], "-")) {
+ error = print_acl_from_stdin(type, hflag, iflag, nflag,
+ qflag, vflag);
+ if (error == -1)
+ carried_error = -1;
+ } else {
+ error = print_acl(argv[i], type, hflag, iflag, nflag,
+ qflag, vflag);
+ if (error == -1)
+ carried_error = -1;
+ }
+ }
+
+ return(carried_error ? 1 : 0);
+}
diff --git a/bin/ls/ls.1 b/bin/ls/ls.1
index 1bd9161e167..dac07b41e7d 100644
--- a/bin/ls/ls.1
+++ b/bin/ls/ls.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: ls.1,v 1.80 2017/07/03 21:33:23 wiz Exp $
+.\" $NetBSD: ls.1,v 1.81 2020/05/16 18:31:45 christos Exp $
.\"
.\" Copyright (c) 1980, 1990, 1991, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
@@ -450,6 +450,20 @@ or
.El
.El
.Pp
+The next field contains a
+plus
+.Pq Ql +
+character if the file has an ACL, or a
+space
+.Pq Ql " "
+if it does not.
+The
+.Nm
+utility does not show the actual ACL;
+use
+.Xr getfacl 1
+to do this.
+.Pp
The number of bytes displayed for a directory is a function of the
number of
.Xr dirent 3
diff --git a/bin/ls/print.c b/bin/ls/print.c
index b3aecd8c539..fff4097c72f 100644
--- a/bin/ls/print.c
+++ b/bin/ls/print.c
@@ -1,4 +1,4 @@
-/* $NetBSD: print.c,v 1.55 2014/05/10 09:39:18 martin Exp $ */
+/* $NetBSD: print.c,v 1.56 2020/05/16 18:31:45 christos Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
@@ -37,12 +37,13 @@
#if 0
static char sccsid[] = "@(#)print.c 8.5 (Berkeley) 7/28/94";
#else
-__RCSID("$NetBSD: print.c,v 1.55 2014/05/10 09:39:18 martin Exp $");
+__RCSID("$NetBSD: print.c,v 1.56 2020/05/16 18:31:45 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
+#include <sys/acl.h>
#include <err.h>
#include <errno.h>
@@ -68,6 +69,7 @@ static void printlink(FTSENT *);
static void printtime(time_t);
static void printtotal(DISPLAY *dp);
static int printtype(u_int);
+static void aclmode(char *, const FTSENT *);
static time_t now;
@@ -154,6 +156,7 @@ printlong(DISPLAY *dp)
}
}
(void)strmode(sp->st_mode, buf);
+ aclmode(buf, p);
np = p->fts_pointer;
(void)printf("%s %*lu ", buf, dp->s_nlink,
(unsigned long)sp->st_nlink);
@@ -495,3 +498,74 @@ printlink(FTSENT *p)
else
(void)printf("%s", path);
}
+
+/*
+ * Add a + after the standard rwxrwxrwx mode if the file has an
+ * ACL. strmode() reserves space at the end of the string.
+ */
+static void
+aclmode(char *buf, const FTSENT *p)
+{
+ char name[MAXPATHLEN + 1];
+ int ret, trivial;
+ static dev_t previous_dev = NODEV;
+ static int supports_acls = -1;
+ static int type = ACL_TYPE_ACCESS;
+ acl_t facl;
+
+ /*
+ * XXX: ACLs are not supported on whiteouts and device files
+ * residing on UFS.
+ */
+ if (S_ISCHR(p->fts_statp->st_mode) || S_ISBLK(p->fts_statp->st_mode) ||
+ S_ISWHT(p->fts_statp->st_mode))
+ return;
+
+ if (previous_dev == p->fts_statp->st_dev && supports_acls == 0)
+ return;
+
+ if (p->fts_level == FTS_ROOTLEVEL)
+ snprintf(name, sizeof(name), "%s", p->fts_name);
+ else
+ snprintf(name, sizeof(name), "%s/%s",
+ p->fts_parent->fts_accpath, p->fts_name);
+
+ if (supports_acls == -1 || previous_dev != p->fts_statp->st_dev) {
+ previous_dev = p->fts_statp->st_dev;
+ supports_acls = 0;
+
+ ret = lpathconf(name, _PC_ACL_NFS4);
+ if (ret > 0) {
+ type = ACL_TYPE_NFS4;
+ supports_acls = 1;
+ } else if (ret < 0 && errno != EINVAL) {
+ warn("%s", name);
+ return;
+ }
+ if (supports_acls == 0) {
+ ret = lpathconf(name, _PC_ACL_EXTENDED);
+ if (ret > 0) {
+ type = ACL_TYPE_ACCESS;
+ supports_acls = 1;
+ } else if (ret < 0 && errno != EINVAL) {
+ warn("%s", name);
+ return;
+ }
+ }
+ }
+ if (supports_acls == 0)
+ return;
+ facl = acl_get_link_np(name, type);
+ if (facl == NULL) {
+ warn("%s", name);
+ return;
+ }
+ if (acl_is_trivial_np(facl, &trivial)) {
+ acl_free(facl);
+ warn("%s", name);
+ return;
+ }
+ if (!trivial)
+ buf[10] = '+';
+ acl_free(facl);
+}
diff --git a/bin/setfacl/Makefile b/bin/setfacl/Makefile
new file mode 100644
index 00000000000..f28e30aaa68
--- /dev/null
+++ b/bin/setfacl/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD: head/bin/setfacl/Makefile 298107 2016-04-16 07:45:30Z gjb $
+
+PACKAGE=runtime
+PROG= setfacl
+SRCS= file.c mask.c merge.c remove.c setfacl.c util.c
+
+.include <bsd.prog.mk>
diff --git a/bin/setfacl/file.c b/bin/setfacl/file.c
new file mode 100644
index 00000000000..ac736a482b6
--- /dev/null
+++ b/bin/setfacl/file.c
@@ -0,0 +1,82 @@
+/* $NetBSD: file.c,v 1.1 2020/05/16 18:31:45 christos Exp $ */
+
+/*-
+ * Copyright (c) 2001 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/bin/setfacl/file.c 333065 2018-04-27 15:25:24Z emaste $");
+#else
+__RCSID("$NetBSD: file.c,v 1.1 2020/05/16 18:31:45 christos Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "setfacl.h"
+
+/*
+ * read acl text from a file and return the corresponding acl
+ */
+acl_t
+get_acl_from_file(const char *filename)
+{
+ FILE *file;
+ size_t len;
+ char buf[BUFSIZ+1];
+
+ if (filename == NULL)
+ err(1, "(null) filename in get_acl_from_file()");
+
+ if (strcmp(filename, "-") == 0) {
+ if (have_stdin)
+ err(1, "cannot specify more than one stdin");
+ file = stdin;
+ have_stdin = true;
+ } else {
+ file = fopen(filename, "r");
+ if (file == NULL)
+ err(1, "fopen() %s failed", filename);
+ }
+
+ len = fread(buf, (size_t)1, sizeof(buf) - 1, file);
+ buf[len] = '\0';
+ if (ferror(file) != 0) {
+ fclose(file);
+ err(1, "error reading from %s", filename);
+ } else if (feof(file) == 0) {
+ fclose(file);
+ errx(1, "line too long in %s", filename);
+ }
+
+ fclose(file);
+
+ return (acl_from_text(buf));
+}
diff --git a/bin/setfacl/mask.c b/bin/setfacl/mask.c
new file mode 100644
index 00000000000..fd36e7cac60
--- /dev/null
+++ b/bin/setfacl/mask.c
@@ -0,0 +1,120 @@
+/* $NetBSD: mask.c,v 1.1 2020/05/16 18:31:45 christos Exp $ */
+
+/*-
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/bin/setfacl/mask.c 333065 2018-04-27 15:25:24Z emaste $");
+#else
+__RCSID("$NetBSD: mask.c,v 1.1 2020/05/16 18:31:45 christos Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "setfacl.h"
+
+/* set the appropriate mask the given ACL's */
+int
+set_acl_mask(acl_t *prev_acl, const char *filename)
+{
+ acl_entry_t entry;
+ acl_t acl;
+ acl_tag_t tag;
+ int entry_id;
+
+ entry = NULL;
+
+ /*
+ * ... if a mask entry is specified, then the permissions of the mask
+ * entry in the resulting ACL shall be set to the permissions in the
+ * specified ACL mask entry.
+ */
+ if (have_mask)
+ return (0);
+
+ acl = acl_dup(*prev_acl);
+ if (acl == NULL)
+ err(1, "%s: acl_dup() failed", filename);
+
+ if (!n_flag) {
+ /*
+ * If no mask entry is specified and the -n option is not
+ * specified, then the permissions of the resulting ACL mask
+ * entry shall be set to the union of the permissions
+ * associated with all entries which belong to the file group
+ * class in the resulting ACL
+ */
+ if (acl_calc_mask(&acl)) {
+ warn("%s: acl_calc_mask() failed", filename);
+ acl_free(acl);
+ return (-1);
+ }
+ } else {
+ /*
+ * If no mask entry is specified and the -n option is
+ * specified, then the permissions of the resulting ACL
+ * mask entry shall remain unchanged ...
+ */
+
+ entry_id = ACL_FIRST_ENTRY;
+
+ while (acl_get_entry(acl, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+ if (acl_get_tag_type(entry, &tag) == -1)
+ err(1, "%s: acl_get_tag_type() failed",
+ filename);
+
+ if (tag == ACL_MASK) {
+ acl_free(acl);
+ return (0);
+ }
+ }
+
+ /*
+ * If no mask entry is specified, the -n option is specified,
+ * and no ACL mask entry exists in the ACL associated with the
+ * file, then write an error message to standard error and
+ * continue with the next file.
+ */
+ warnx("%s: warning: no mask entry", filename);
+ acl_free(acl);
+ return (0);
+ }
+
+ acl_free(*prev_acl);
+ *prev_acl = acl_dup(acl);
+ acl_free(acl);
+
+ return (0);
+}
diff --git a/bin/setfacl/merge.c b/bin/setfacl/merge.c
new file mode 100644
index 00000000000..4928719832c
--- /dev/null
+++ b/bin/setfacl/merge.c
@@ -0,0 +1,299 @@
+/* $NetBSD: merge.c,v 1.1 2020/05/16 18:31:45 christos Exp $ */
+
+/*-
+ * Copyright (c) 2001 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/bin/setfacl/merge.c 333065 2018-04-27 15:25:24Z emaste $");
+#else
+__RCSID("$NetBSD: merge.c,v 1.1 2020/05/16 18:31:45 christos Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <stdio.h>
+
+#include "setfacl.h"
+
+static int merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new,
+ int acl_brand);
+
+static int
+merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new, int acl_brand)
+{
+ acl_permset_t permset;
+ acl_entry_type_t entry_type;
+ acl_flagset_t flagset;
+ int have_entry;
+ uid_t *id, *id_new;
+
+ have_entry = 0;
+
+ id = acl_get_qualifier(*entry);
+ if (id == NULL)
+ err(1, "acl_get_qualifier() failed");
+ id_new = acl_get_qualifier(*entry_new);
+ if (id_new == NULL)
+ err(1, "acl_get_qualifier() failed");
+ if (*id == *id_new) {
+ /* any other matches */
+ if (acl_get_permset(*entry, &permset) == -1)
+ err(1, "acl_get_permset() failed");
+ if (acl_set_permset(*entry_new, permset) == -1)
+ err(1, "acl_set_permset() failed");
+
+ if (acl_brand == ACL_BRAND_NFS4) {
+ if (acl_get_entry_type_np(*entry, &entry_type))
+ err(1, "acl_get_entry_type_np() failed");
+ if (acl_set_entry_type_np(*entry_new, entry_type))
+ err(1, "acl_set_entry_type_np() failed");
+ if (acl_get_flagset_np(*entry, &flagset))
+ err(1, "acl_get_flagset_np() failed");
+ if (acl_set_flagset_np(*entry_new, flagset))
+ err(1, "acl_set_flagset_np() failed");
+ }
+
+ have_entry = 1;
+ }
+ acl_free(id);
+ acl_free(id_new);
+
+ return (have_entry);
+}
+
+/*
+ * merge an ACL into existing file's ACL
+ */
+int
+merge_acl(acl_t acl, acl_t *prev_acl, const char *filename)
+{
+ acl_entry_t entry, entry_new;
+ acl_permset_t permset;
+ acl_t acl_new;
+ acl_tag_t tag, tag_new;
+ acl_entry_type_t entry_type, entry_type_new;
+ acl_flagset_t flagset;
+ int entry_id, entry_id_new, have_entry, had_entry, entry_number = 0;
+ int acl_brand, prev_acl_brand;
+
+ acl_get_brand_np(acl, &acl_brand);
+ acl_get_brand_np(*prev_acl, &prev_acl_brand);
+
+ if (branding_mismatch(acl_brand, prev_acl_brand)) {
+ warnx("%s: branding mismatch; existing ACL is %s, "
+ "entry to be merged is %s", filename,
+ brand_name(prev_acl_brand), brand_name(acl_brand));
+ return (-1);
+ }
+
+ acl_new = acl_dup(*prev_acl);
+ if (acl_new == NULL)
+ err(1, "%s: acl_dup() failed", filename);
+
+ entry_id = ACL_FIRST_ENTRY;
+
+ while (acl_get_entry(acl, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+ have_entry = 0;
+ had_entry = 0;
+
+ /* keep track of existing ACL_MASK entries */
+ if (acl_get_tag_type(entry, &tag) == -1)
+ err(1, "%s: acl_get_tag_type() failed - "
+ "invalid ACL entry", filename);
+ if (tag == ACL_MASK)
+ have_mask = true;
+
+ /* check against the existing ACL entries */
+ entry_id_new = ACL_FIRST_ENTRY;
+ while (acl_get_entry(acl_new, entry_id_new, &entry_new) == 1) {
+ entry_id_new = ACL_NEXT_ENTRY;
+
+ if (acl_get_tag_type(entry, &tag) == -1)
+ err(1, "%s: acl_get_tag_type() failed",
+ filename);
+ if (acl_get_tag_type(entry_new, &tag_new) == -1)
+ err(1, "%s: acl_get_tag_type() failed",
+ filename);
+ if (tag != tag_new)
+ continue;
+
+ /*
+ * For NFSv4, in addition to "tag" and "id" we also
+ * compare "entry_type".
+ */
+ if (acl_brand == ACL_BRAND_NFS4) {
+ if (acl_get_entry_type_np(entry, &entry_type))
+ err(1, "%s: acl_get_entry_type_np() "
+ "failed", filename);
+ if (acl_get_entry_type_np(entry_new, &entry_type_new))
+ err(1, "%s: acl_get_entry_type_np() "
+ "failed", filename);
+ if (entry_type != entry_type_new)
+ continue;
+ }
+
+ switch(tag) {
+ case ACL_USER:
+ case ACL_GROUP:
+ have_entry = merge_user_group(&entry,
+ &entry_new, acl_brand);
+ if (have_entry == 0)
+ break;
+ /* FALLTHROUGH */
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_OTHER:
+ case ACL_MASK:
+ case ACL_EVERYONE:
+ if (acl_get_permset(entry, &permset) == -1)
+ err(1, "%s: acl_get_permset() failed",
+ filename);
+ if (acl_set_permset(entry_new, permset) == -1)
+ err(1, "%s: acl_set_permset() failed",
+ filename);
+
+ if (acl_brand == ACL_BRAND_NFS4) {
+ if (acl_get_entry_type_np(entry, &entry_type))
+ err(1, "%s: acl_get_entry_type_np() failed",
+ filename);
+ if (acl_set_entry_type_np(entry_new, entry_type))
+ err(1, "%s: acl_set_entry_type_np() failed",
+ filename);
+ if (acl_get_flagset_np(entry, &flagset))
+ err(1, "%s: acl_get_flagset_np() failed",
+ filename);
+ if (acl_set_flagset_np(entry_new, flagset))
+ err(1, "%s: acl_set_flagset_np() failed",
+ filename);
+ }
+ had_entry = have_entry = 1;
+ break;
+ default:
+ /* should never be here */
+ errx(1, "%s: invalid tag type: %i", filename, tag);
+ break;
+ }
+ }
+
+ /* if this entry has not been found, it must be new */
+ if (had_entry == 0) {
+
+ /*
+ * NFSv4 ACL entries must be prepended to the ACL.
+ * Appending them at the end makes no sense, since
+ * in most cases they wouldn't even get evaluated.
+ */
+ if (acl_brand == ACL_BRAND_NFS4) {
+ if (acl_create_entry_np(&acl_new, &entry_new, entry_number) == -1) {
+ warn("%s: acl_create_entry_np() failed", filename);
+ acl_free(acl_new);
+ return (-1);
+ }
+ /*
+ * Without this increment, adding several
+ * entries at once, for example
+ * "setfacl -m user:1:r:allow,user:2:r:allow",
+ * would make them appear in reverse order.
+ */
+ entry_number++;
+ } else {
+ if (acl_create_entry(&acl_new, &entry_new) == -1) {
+ warn("%s: acl_create_entry() failed", filename);
+ acl_free(acl_new);
+ return (-1);
+ }
+ }
+ if (acl_copy_entry(entry_new, entry) == -1)
+ err(1, "%s: acl_copy_entry() failed", filename);
+ }
+ }
+
+ acl_free(*prev_acl);
+ *prev_acl = acl_new;
+
+ return (0);
+}
+
+int
+add_acl(acl_t acl, uint entry_number, acl_t *prev_acl, const char *filename)
+{
+ acl_entry_t entry, entry_new;
+ acl_t acl_new;
+ int entry_id, acl_brand, prev_acl_brand;
+
+ acl_get_brand_np(acl, &acl_brand);
+ acl_get_brand_np(*prev_acl, &prev_acl_brand);
+
+ if (prev_acl_brand != ACL_BRAND_NFS4) {
+ warnx("%s: the '-a' option is only applicable to NFSv4 ACLs",
+ filename);
+ return (-1);
+ }
+
+ if (branding_mismatch(acl_brand, ACL_BRAND_NFS4)) {
+ warnx("%s: branding mismatch; existing ACL is NFSv4, "
+ "entry to be added is %s", filename,
+ brand_name(acl_brand));
+ return (-1);
+ }
+
+ acl_new = acl_dup(*prev_acl);
+ if (acl_new == NULL)
+ err(1, "%s: acl_dup() failed", filename);
+
+ entry_id = ACL_FIRST_ENTRY;
+
+ while (acl_get_entry(acl, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+
+ if (acl_create_entry_np(&acl_new, &entry_new, entry_number) == -1) {
+ warn("%s: acl_create_entry_np() failed", filename);
+ acl_free(acl_new);
+ return (-1);
+ }
+
+ /*
+ * Without this increment, adding several
+ * entries at once, for example
+ * "setfacl -m user:1:r:allow,user:2:r:allow",
+ * would make them appear in reverse order.
+ */
+ entry_number++;
+
+ if (acl_copy_entry(entry_new, entry) == -1)
+ err(1, "%s: acl_copy_entry() failed", filename);
+ }
+
+ acl_free(*prev_acl);
+ *prev_acl = acl_new;
+
+ return (0);
+}
diff --git a/bin/setfacl/remove.c b/bin/setfacl/remove.c
new file mode 100644
index 00000000000..adcd6c3ea1d
--- /dev/null
+++ b/bin/setfacl/remove.c
@@ -0,0 +1,179 @@
+/* $NetBSD: remove.c,v 1.1 2020/05/16 18:31:45 christos Exp $ */
+
+/*-
+ * Copyright (c) 2001 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/bin/setfacl/remove.c 333065 2018-04-27 15:25:24Z emaste $");
+#else
+__RCSID("$NetBSD: remove.c,v 1.1 2020/05/16 18:31:45 christos Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "setfacl.h"
+
+/*
+ * remove ACL entries from an ACL
+ */
+int
+remove_acl(acl_t acl, acl_t *prev_acl, const char *filename)
+{
+ acl_entry_t entry;
+ acl_t acl_new;
+ acl_tag_t tag;
+ int carried_error, entry_id, acl_brand, prev_acl_brand;
+
+ carried_error = 0;
+
+ acl_get_brand_np(acl, &acl_brand);
+ acl_get_brand_np(*prev_acl, &prev_acl_brand);
+
+ if (branding_mismatch(acl_brand, prev_acl_brand)) {
+ warnx("%s: branding mismatch; existing ACL is %s, "
+ "entry to be removed is %s", filename,
+ brand_name(prev_acl_brand), brand_name(acl_brand));
+ return (-1);
+ }
+
+ carried_error = 0;
+
+ acl_new = acl_dup(*prev_acl);
+ if (acl_new == NULL)
+ err(1, "%s: acl_dup() failed", filename);
+
+ tag = ACL_UNDEFINED_TAG;
+
+ /* find and delete the entry */
+ entry_id = ACL_FIRST_ENTRY;
+ while (acl_get_entry(acl, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+ if (acl_get_tag_type(entry, &tag) == -1)
+ err(1, "%s: acl_get_tag_type() failed", filename);
+ if (tag == ACL_MASK)
+ have_mask = true;
+ if (acl_delete_entry(acl_new, entry) == -1) {
+ carried_error++;
+ warnx("%s: cannot remove non-existent ACL entry",
+ filename);
+ }
+ }
+
+ acl_free(*prev_acl);
+ *prev_acl = acl_new;
+
+ if (carried_error)
+ return (-1);
+
+ return (0);
+}
+
+int
+remove_by_number(uint entry_number, acl_t *prev_acl, const char *filename)
+{
+ acl_entry_t entry;
+ acl_t acl_new;
+ acl_tag_t tag;
+ int carried_error, entry_id;
+ uint i;
+
+ carried_error = 0;
+
+ acl_new = acl_dup(*prev_acl);
+ if (acl_new == NULL)
+ err(1, "%s: acl_dup() failed", filename);
+
+ tag = ACL_UNDEFINED_TAG;
+
+ /*
+ * Find out whether we're removing the mask entry,
+ * to behave the same as the routine above.
+ *
+ * XXX: Is this loop actually needed?
+ */
+ entry_id = ACL_FIRST_ENTRY;
+ i = 0;
+ while (acl_get_entry(acl_new, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+ if (i != entry_number)
+ continue;
+ if (acl_get_tag_type(entry, &tag) == -1)
+ err(1, "%s: acl_get_tag_type() failed", filename);
+ if (tag == ACL_MASK)
+ have_mask = true;
+ }
+
+ if (acl_delete_entry_np(acl_new, entry_number) == -1) {
+ carried_error++;
+ warn("%s: acl_delete_entry_np() failed", filename);
+ }
+
+ acl_free(*prev_acl);
+ *prev_acl = acl_new;
+
+ if (carried_error)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * remove default entries
+ */
+int
+remove_default(acl_t *prev_acl, const char *filename)
+{
+
+ acl_free(*prev_acl);
+ *prev_acl = acl_init(ACL_MAX_ENTRIES);
+ if (*prev_acl == NULL)
+ err(1, "%s: acl_init() failed", filename);
+
+ return (0);
+}
+
+/*
+ * remove extended entries
+ */
+void
+remove_ext(acl_t *prev_acl, const char *filename)
+{
+ acl_t acl_new;
+
+ acl_new = acl_strip_np(*prev_acl, !n_flag);
+ if (acl_new == NULL)
+ err(1, "%s: acl_strip_np() failed", filename);
+
+ acl_free(*prev_acl);
+ *prev_acl = acl_new;
+}
diff --git a/bin/setfacl/setfacl.1 b/bin/setfacl/setfacl.1
new file mode 100644
index 00000000000..307c8000a6b
--- /dev/null
+++ b/bin/setfacl/setfacl.1
@@ -0,0 +1,517 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" Copyright (c) 2011 Edward Tomasz Napierała
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/bin/setfacl/setfacl.1 339793 2018-10-26 21:17:06Z markj $
+.\"
+.Dd October 26, 2018
+.Dt SETFACL 1
+.Os
+.Sh NAME
+.Nm setfacl
+.Nd set ACL information
+.Sh SYNOPSIS
+.Nm
+.Op Fl R Op Fl H | L | P
+.Op Fl bdhkn
+.Op Fl a Ar position entries
+.Op Fl m Ar entries
+.Op Fl M Ar file
+.Op Fl x Ar entries | position
+.Op Fl X Ar file
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility sets discretionary access control information on
+the specified file(s).
+If no files are specified, or the list consists of the only
+.Sq Fl ,
+the file names are taken from the standard input.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a Ar position entries
+Modify the ACL on the specified files by inserting new
+ACL entries
+specified in
+.Ar entries ,
+starting at position
+.Ar position ,
+counting from zero.
+This option is only applicable to NFSv4 ACLs.
+.It Fl b
+Remove all ACL entries except for the ones synthesized
+from the file mode - the three mandatory entries in case
+of POSIX.1e ACL.
+If the POSIX.1e ACL contains a
+.Dq Li mask
+entry, the permissions of the
+.Dq Li group
+entry in the resulting ACL will be set to the permission
+associated with both the
+.Dq Li group
+and
+.Dq Li mask
+entries of the current ACL.
+.It Fl d
+The operations apply to the default ACL entries instead of
+access ACL entries.
+Currently only directories may have
+default ACL's.
+This option is not applicable to NFSv4 ACLs.
+.It Fl h
+If the target of the operation is a symbolic link, perform the operation
+on the symbolic link itself, rather than following the link.
+.It Fl H
+If the
+.Fl R
+option is specified, symbolic links on the command line are followed
+and hence unaffected by the command.
+(Symbolic links encountered during tree traversal are not followed.)
+.It Fl k
+Delete any default ACL entries on the specified files.
+It
+is not considered an error if the specified files do not have
+any default ACL entries.
+An error will be reported if any of
+the specified files cannot have a default entry (i.e.,
+non-directories).
+This option is not applicable to NFSv4 ACLs.
+.It Fl L
+If the
+.Fl R
+option is specified, all symbolic links are followed.
+.It Fl m Ar entries
+Modify the ACL on the specified file.
+New entries will be added, and existing entries will be modified
+according to the
+.Ar entries
+argument.
+For NFSv4 ACLs, it is recommended to use the
+.Fl a
+and
+.Fl x
+options instead.
+.It Fl M Ar file
+Modify the ACL entries on the specified files by adding new
+ACL entries and modifying existing ACL entries with the ACL
+entries specified in the file
+.Ar file .
+If
+.Ar file
+is
+.Fl ,
+the input is taken from stdin.
+.It Fl n
+Do not recalculate the permissions associated with the ACL
+mask entry.
+This option is not applicable to NFSv4 ACLs.
+.It Fl P
+If the
+.Fl R
+option is specified, no symbolic links are followed.
+This is the default.
+.It Fl R
+Perform the action recursively on any specified directories.
+When modifying or adding NFSv4 ACL entries, inheritance flags
+are applied only to directories.
+.It Fl x Ar entries | position
+If
+.Ar entries
+is specified, remove the ACL entries specified there
+from the access or default ACL of the specified files.
+Otherwise, remove entry at index
+.Ar position ,
+counting from zero.
+.It Fl X Ar file
+Remove the ACL entries specified in the file
+.Ar file
+from the access or default ACL of the specified files.
+.El
+.Pp
+The above options are evaluated in the order specified
+on the command-line.
+.Sh POSIX.1e ACL ENTRIES
+A POSIX.1E ACL entry contains three colon-separated fields:
+an ACL tag, an ACL qualifier, and discretionary access
+permissions:
+.Bl -tag -width indent
+.It Ar "ACL tag"
+The ACL tag specifies the ACL entry type and consists of
+one of the following:
+.Dq Li user
+or
+.Ql u
+specifying the access
+granted to the owner of the file or a specified user;
+.Dq Li group
+or
+.Ql g
+specifying the access granted to the file owning group
+or a specified group;
+.Dq Li other
+or
+.Ql o
+specifying the access
+granted to any process that does not match any user or group
+ACL entry;
+.Dq Li mask
+or
+.Ql m
+specifying the maximum access
+granted to any ACL entry except the
+.Dq Li user
+ACL entry for the file owner and the
+.Dq Li other
+ACL entry.
+.It Ar "ACL qualifier"
+The ACL qualifier field describes the user or group associated with
+the ACL entry.
+It may consist of one of the following: uid or
+user name, gid or group name, or empty.
+For
+.Dq Li user
+ACL entries, an empty field specifies access granted to the
+file owner.
+For
+.Dq Li group
+ACL entries, an empty field specifies access granted to the
+file owning group.
+.Dq Li mask
+and
+.Dq Li other
+ACL entries do not use this field.
+.It Ar "access permissions"
+The access permissions field contains up to one of each of
+the following:
+.Ql r ,
+.Ql w ,
+and
+.Ql x
+to set read, write, and
+execute permissions, respectively.
+Each of these may be excluded
+or replaced with a
+.Ql -
+character to indicate no access.
+.El
+.Pp
+A
+.Dq Li mask
+ACL entry is required on a file with any ACL entries other than
+the default
+.Dq Li user ,
+.Dq Li group ,
+and
+.Dq Li other
+ACL entries.
+If the
+.Fl n
+option is not specified and no
+.Dq Li mask
+ACL entry was specified, the
+.Nm
+utility
+will apply a
+.Dq Li mask
+ACL entry consisting of the union of the permissions associated
+with all
+.Dq Li group
+ACL entries in the resulting ACL.
+.Pp
+Traditional POSIX interfaces acting on file system object modes have
+modified semantics in the presence of POSIX.1e extended ACLs.
+When a mask entry is present on the access ACL of an object, the mask
+entry is substituted for the group bits; this occurs in programs such
+as
+.Xr stat 1
+or
+.Xr ls 1 .
+When the mode is modified on an object that has a mask entry, the
+changes applied to the group bits will actually be applied to the
+mask entry.
+These semantics provide for greater application compatibility:
+applications modifying the mode instead of the ACL will see
+conservative behavior, limiting the effective rights granted by all
+of the additional user and group entries; this occurs in programs
+such as
+.Xr chmod 1 .
+.Pp
+ACL entries applied from a file using the
+.Fl M
+or
+.Fl X
+options shall be of the following form: one ACL entry per line, as
+previously specified; whitespace is ignored; any text after a
+.Ql #
+is ignored (comments).
+.Pp
+When POSIX.1e ACL entries are evaluated, the access check algorithm checks
+the ACL entries in the following order: file owner,
+.Dq Li user
+ACL entries, file owning group,
+.Dq Li group
+ACL entries, and
+.Dq Li other
+ACL entry.
+.Pp
+Multiple ACL entries specified on the command line are
+separated by commas.
+.Pp
+It is possible for files and directories to inherit ACL entries from their
+parent directory.
+This is accomplished through the use of the default ACL.
+It should be noted that before you can specify a default ACL, the mandatory
+ACL entries for user, group, other and mask must be set.
+For more details see the examples below.
+Default ACLs can be created by using
+.Fl d .
+.Sh NFSv4 ACL ENTRIES
+An NFSv4 ACL entry contains four or five colon-separated fields: an ACL tag,
+an ACL qualifier (only for
+.Dq Li user
+and
+.Dq Li group
+tags), discretionary access permissions, ACL inheritance flags, and ACL type:
+.Bl -tag -width indent
+.It Ar "ACL tag"
+The ACL tag specifies the ACL entry type and consists of
+one of the following:
+.Dq Li user
+or
+.Ql u
+specifying the access
+granted to the specified user;
+.Dq Li group
+or
+.Ql g
+specifying the access granted to the specified group;
+.Dq Li owner@
+specifying the access granted to the owner of the file;
+.Dq Li group@
+specifying the access granted to the file owning group;
+.Dq Li everyone@
+specifying everyone.
+Note that
+.Dq Li everyone@
+is not the same as traditional Unix
+.Dq Li other
+- it means,
+literally, everyone, including file owner and owning group.
+.It Ar "ACL qualifier"
+The ACL qualifier field describes the user or group associated with
+the ACL entry.
+It may consist of one of the following: uid or
+user name, or gid or group name.
+In entries whose tag type is one of
+.Dq Li owner@ ,
+.Dq Li group@ ,
+or
+.Dq Li everyone@ ,
+this field is omitted altogether, including the trailing comma.
+.It Ar "access permissions"
+Access permissions may be specified in either short or long form.
+Short and long forms may not be mixed.
+Permissions in long form are separated by the
+.Ql /
+character; in short form, they are concatenated together.
+Valid permissions are:
+.Bl -tag -width ".Dv modify_set"
+.It Short
+Long
+.It r
+read_data
+.It w
+write_data
+.It x
+execute
+.It p
+append_data
+.It D
+delete_child
+.It d
+delete
+.It a
+read_attributes
+.It A
+write_attributes
+.It R
+read_xattr
+.It W
+write_xattr
+.It c
+read_acl
+.It C
+write_acl
+.It o
+write_owner
+.It s
+synchronize
+.El
+.Pp
+In addition, the following permission sets may be used:
+.Bl -tag -width ".Dv modify_set"
+.It Set
+Permissions
+.It full_set
+all permissions, as shown above
+.It modify_set
+all permissions except write_acl and write_owner
+.It read_set
+read_data, read_attributes, read_xattr and read_acl
+.It write_set
+write_data, append_data, write_attributes and write_xattr
+.El
+.It Ar "ACL inheritance flags"
+Inheritance flags may be specified in either short or long form.
+Short and long forms may not be mixed.
+Access flags in long form are separated by the
+.Ql /
+character; in short form, they are concatenated together.
+Valid inheritance flags are:
+.Bl -tag -width ".Dv short"
+.It Short
+Long
+.It f
+file_inherit
+.It d
+dir_inherit
+.It i
+inherit_only
+.It n
+no_propagate
+.It I
+inherited
+.El
+.Pp
+Other than the "inherited" flag, inheritance flags may be only set on directories.
+.It Ar "ACL type"
+The ACL type field is either
+.Dq Li allow
+or
+.Dq Li deny .
+.El
+.Pp
+ACL entries applied from a file using the
+.Fl M
+or
+.Fl X
+options shall be of the following form: one ACL entry per line, as
+previously specified; whitespace is ignored; any text after a
+.Ql #
+is ignored (comments).
+.Pp
+NFSv4 ACL entries are evaluated in their visible order.
+.Pp
+Multiple ACL entries specified on the command line are
+separated by commas.
+.Pp
+Note that the file owner is always granted the read_acl, write_acl,
+read_attributes, and write_attributes permissions, even if the ACL
+would deny it.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+.Dl setfacl -d -m u::rwx,g::rx,o::rx,mask::rwx dir
+.Dl setfacl -d -m g:admins:rwx dir
+.Pp
+The first command sets the mandatory elements of the POSIX.1e default ACL.
+The second command specifies that users in group admins can have read, write, and execute
+permissions for directory named "dir".
+It should be noted that any files or directories created underneath "dir" will
+inherit these default ACLs upon creation.
+.Pp
+.Dl setfacl -m u::rwx,g:mail:rw file
+.Pp
+Sets read, write, and execute permissions for the
+.Pa file
+owner's POSIX.1e ACL entry and read and write permissions for group mail on
+.Pa file .
+.Pp
+.Dl setfacl -m owner@:rwxp::allow,g:mail:rwp::allow file
+.Pp
+Semantically equal to the example above, but for NFSv4 ACL.
+.Pp
+.Dl setfacl -M file1 file2
+.Pp
+Sets/updates the ACL entries contained in
+.Pa file1
+on
+.Pa file2 .
+.Pp
+.Dl setfacl -x g:mail:rw file
+.Pp
+Remove the group mail POSIX.1e ACL entry containing read/write permissions
+from
+.Pa file .
+.Pp
+.Dl setfacl -x0 file
+.Pp
+Remove the first entry from the NFSv4 ACL from
+.Pa file .
+.Pp
+.Dl setfacl -bn file
+.Pp
+Remove all
+.Dq Li access
+ACL entries except for the three required from
+.Pa file .
+.Pp
+.Dl getfacl file1 | setfacl -b -n -M - file2
+.Pp
+Copy ACL entries from
+.Pa file1
+to
+.Pa file2 .
+.Sh SEE ALSO
+.Xr getfacl 1 ,
+.Xr acl 3 ,
+.Xr getextattr 8 ,
+.Xr setextattr 8 ,
+.Xr acl 9 ,
+.Xr extattr 9
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.Tn IEEE
+Std 1003.2c compliant.
+.Sh HISTORY
+Extended Attribute and Access Control List support was developed
+as part of the
+.Tn TrustedBSD
+Project and introduced in
+.Fx 5.0 .
+NFSv4 ACL support was introduced in
+.Fx 8.1 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
+NFSv4 ACL support was implemented by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org .
diff --git a/bin/setfacl/setfacl.c b/bin/setfacl/setfacl.c
new file mode 100644
index 00000000000..9d0cf119b61
--- /dev/null
+++ b/bin/setfacl/setfacl.c
@@ -0,0 +1,511 @@
+/* $NetBSD: setfacl.c,v 1.1 2020/05/16 18:31:45 christos Exp $ */
+
+/*-
+ * Copyright (c) 2001 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/bin/setfacl/setfacl.c 339793 2018-10-26 21:17:06Z markj $");
+#else
+__RCSID("$NetBSD: setfacl.c,v 1.1 2020/05/16 18:31:45 christos Exp $");
+#endif
+
+#include <sys/param.h>
+#include <sys/acl.h>
+#include <sys/queue.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fts.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "setfacl.h"
+
+/* file operations */
+#define OP_MERGE_ACL 0x00 /* merge acl's (-mM) */
+#define OP_REMOVE_DEF 0x01 /* remove default acl's (-k) */
+#define OP_REMOVE_EXT 0x02 /* remove extended acl's (-b) */
+#define OP_REMOVE_ACL 0x03 /* remove acl's (-xX) */
+#define OP_REMOVE_BY_NUMBER 0x04 /* remove acl's (-xX) by acl entry number */
+#define OP_ADD_ACL 0x05 /* add acls entries at a given position */
+
+/* TAILQ entry for acl operations */
+struct sf_entry {
+ uint op;
+ acl_t acl;
+ uint entry_number;
+ TAILQ_ENTRY(sf_entry) next;
+};
+static TAILQ_HEAD(, sf_entry) entrylist;
+
+bool have_mask;
+bool have_stdin;
+bool n_flag;
+static bool h_flag;
+static bool H_flag;
+static bool L_flag;
+static bool R_flag;
+static bool need_mask;
+static acl_type_t acl_type = ACL_TYPE_ACCESS;
+
+static int handle_file(FTS *ftsp, FTSENT *file);
+static acl_t clear_inheritance_flags(acl_t acl);
+static char **stdin_files(void);
+static void usage(void);
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: setfacl [-R [-H | -L | -P]] [-bdhkn] "
+ "[-a position entries] [-m entries] [-M file] "
+ "[-x entries] [-X file] [file ...]\n");
+ exit(1);
+}
+
+static char **
+stdin_files(void)
+{
+ char **files_list;
+ char filename[PATH_MAX];
+ size_t fl_count, i;
+
+ if (have_stdin)
+ err(1, "cannot have more than one stdin");
+
+ i = 0;
+ have_stdin = true;
+ bzero(&filename, sizeof(filename));
+ /* Start with an array size sufficient for basic cases. */
+ fl_count = 1024;
+ files_list = zmalloc(fl_count * sizeof(char *));
+ while (fgets(filename, (int)sizeof(filename), stdin)) {
+ /* remove the \n */
+ filename[strlen(filename) - 1] = '\0';
+ files_list[i] = strdup(filename);
+ if (files_list[i] == NULL)
+ err(1, "strdup() failed");
+ /* Grow array if necessary. */
+ if (++i == fl_count) {
+ fl_count <<= 1;
+ if (fl_count > SIZE_MAX / sizeof(char *))
+ errx(1, "Too many input files");
+ files_list = zrealloc(files_list,
+ fl_count * sizeof(char *));
+ }
+ }
+
+ /* fts_open() requires the last array element to be NULL. */
+ files_list[i] = NULL;
+
+ return (files_list);
+}
+
+/*
+ * Remove any inheritance flags from NFSv4 ACLs when running in recursive
+ * mode. This is to avoid files being assigned identical ACLs to their
+ * parent directory while also being set to inherit them.
+ *
+ * The acl argument is assumed to be valid.
+ */
+static acl_t
+clear_inheritance_flags(acl_t acl)
+{
+ acl_t nacl;
+ acl_entry_t acl_entry;
+ acl_flagset_t acl_flagset;
+ int acl_brand, entry_id;
+
+ (void)acl_get_brand_np(acl, &acl_brand);
+ if (acl_brand != ACL_BRAND_NFS4)
+ return (acl);
+
+ nacl = acl_dup(acl);
+ if (nacl == NULL) {
+ warn("acl_dup() failed");
+ return (acl);
+ }
+
+ entry_id = ACL_FIRST_ENTRY;
+ while (acl_get_entry(nacl, entry_id, &acl_entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+ if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
+ warn("acl_get_flagset_np() failed");
+ continue;
+ }
+ if (acl_get_flag_np(acl_flagset, ACL_ENTRY_INHERIT_ONLY) == 1) {
+ if (acl_delete_entry(nacl, acl_entry) != 0)
+ warn("acl_delete_entry() failed");
+ continue;
+ }
+ if (acl_delete_flag_np(acl_flagset,
+ ACL_ENTRY_FILE_INHERIT |
+ ACL_ENTRY_DIRECTORY_INHERIT |
+ ACL_ENTRY_NO_PROPAGATE_INHERIT) != 0)
+ warn("acl_delete_flag_np() failed");
+ }
+
+ return (nacl);
+}
+
+static int
+handle_file(FTS *ftsp, FTSENT *file)
+{
+ acl_t acl, nacl;
+ acl_entry_t unused_entry;
+ int local_error, ret;
+ struct sf_entry *entry;
+ bool follow_symlink;
+
+ local_error = 0;
+ switch (file->fts_info) {
+ case FTS_D:
+ /* Do not recurse if -R not specified. */
+ if (!R_flag)
+ fts_set(ftsp, file, FTS_SKIP);
+ break;
+ case FTS_DP:
+ /* Skip the second visit to a directory. */
+ return (0);
+ case FTS_DNR:
+ case FTS_ERR:
+ warnx("%s: %s", file->fts_path, strerror(file->fts_errno));
+ return (0);
+ default:
+ break;
+ }
+
+ if (acl_type == ACL_TYPE_DEFAULT && file->fts_info != FTS_D) {
+ warnx("%s: default ACL may only be set on a directory",
+ file->fts_path);
+ return (1);
+ }
+
+ follow_symlink = (!R_flag && !h_flag) || (R_flag && L_flag) ||
+ (R_flag && H_flag && file->fts_level == FTS_ROOTLEVEL);
+
+ if (follow_symlink)
+ ret = pathconf(file->fts_accpath, _PC_ACL_NFS4);
+ else
+ ret = lpathconf(file->fts_accpath, _PC_ACL_NFS4);
+ if (ret > 0) {
+ if (acl_type == ACL_TYPE_DEFAULT) {
+ warnx("%s: there are no default entries in NFSv4 ACLs",
+ file->fts_path);
+ return (1);
+ }
+ acl_type = ACL_TYPE_NFS4;
+ } else if (ret == 0) {
+ if (acl_type == ACL_TYPE_NFS4)
+ acl_type = ACL_TYPE_ACCESS;
+ } else if (ret < 0 && errno != EINVAL && errno != ENOENT) {
+ warn("%s: pathconf(_PC_ACL_NFS4) failed",
+ file->fts_path);
+ }
+
+ if (follow_symlink)
+ acl = acl_get_file(file->fts_accpath, acl_type);
+ else
+ acl = acl_get_link_np(file->fts_accpath, acl_type);
+ if (acl == NULL) {
+ if (follow_symlink)
+ warn("%s: acl_get_file() failed", file->fts_path);
+ else
+ warn("%s: acl_get_link_np() failed", file->fts_path);
+ return (1);
+ }
+
+ /* Cycle through each option. */
+ TAILQ_FOREACH(entry, &entrylist, next) {
+ nacl = entry->acl;
+ switch (entry->op) {
+ case OP_ADD_ACL:
+ if (R_flag && file->fts_info != FTS_D &&
+ acl_type == ACL_TYPE_NFS4)
+ nacl = clear_inheritance_flags(nacl);
+ local_error += add_acl(nacl, entry->entry_number, &acl,
+ file->fts_path);
+ break;
+ case OP_MERGE_ACL:
+ if (R_flag && file->fts_info != FTS_D &&
+ acl_type == ACL_TYPE_NFS4)
+ nacl = clear_inheritance_flags(nacl);
+ local_error += merge_acl(nacl, &acl, file->fts_path);
+ need_mask = true;
+ break;
+ case OP_REMOVE_EXT:
+ /*
+ * Don't try to call remove_ext() for empty
+ * default ACL.
+ */
+ if (acl_type == ACL_TYPE_DEFAULT &&
+ acl_get_entry(acl, ACL_FIRST_ENTRY,
+ &unused_entry) == 0) {
+ local_error += remove_default(&acl,
+ file->fts_path);
+ break;
+ }
+ remove_ext(&acl, file->fts_path);
+ need_mask = false;
+ break;
+ case OP_REMOVE_DEF:
+ if (acl_type == ACL_TYPE_NFS4) {
+ warnx("%s: there are no default entries in "
+ "NFSv4 ACLs; cannot remove",
+ file->fts_path);
+ local_error++;
+ break;
+ }
+ if (acl_delete_def_file(file->fts_accpath) == -1) {
+ warn("%s: acl_delete_def_file() failed",
+ file->fts_path);
+ local_error++;
+ }
+ if (acl_type == ACL_TYPE_DEFAULT)
+ local_error += remove_default(&acl,
+ file->fts_path);
+ need_mask = false;
+ break;
+ case OP_REMOVE_ACL:
+ local_error += remove_acl(nacl, &acl, file->fts_path);
+ need_mask = true;
+ break;
+ case OP_REMOVE_BY_NUMBER:
+ local_error += remove_by_number(entry->entry_number,
+ &acl, file->fts_path);
+ need_mask = true;
+ break;
+ }
+
+ if (nacl != entry->acl) {
+ acl_free(nacl);
+ nacl = NULL;
+ }
+ if (local_error)
+ break;
+ }
+
+ ret = 0;
+
+ /*
+ * Don't try to set an empty default ACL; it will always fail.
+ * Use acl_delete_def_file(3) instead.
+ */
+ if (acl_type == ACL_TYPE_DEFAULT &&
+ acl_get_entry(acl, ACL_FIRST_ENTRY, &unused_entry) == 0) {
+ if (acl_delete_def_file(file->fts_accpath) == -1) {
+ warn("%s: acl_delete_def_file() failed",
+ file->fts_path);
+ ret = 1;
+ }
+ goto out;
+ }
+
+ /* Don't bother setting the ACL if something is broken. */
+ if (local_error) {
+ ret = 1;
+ } else if (acl_type != ACL_TYPE_NFS4 && need_mask &&
+ set_acl_mask(&acl, file->fts_path) == -1) {
+ warnx("%s: failed to set ACL mask", file->fts_path);
+ ret = 1;
+ } else if (follow_symlink) {
+ if (acl_set_file(file->fts_accpath, acl_type, acl) == -1) {
+ warn("%s: acl_set_file() failed", file->fts_path);
+ ret = 1;
+ }
+ } else {
+ if (acl_set_link_np(file->fts_accpath, acl_type, acl) == -1) {
+ warn("%s: acl_set_link_np() failed", file->fts_path);
+ ret = 1;
+ }
+ }
+
+out:
+ acl_free(acl);
+ return (ret);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int carried_error, ch, entry_number, fts_options;
+ FTS *ftsp;
+ FTSENT *file;
+ char **files_list;
+ struct sf_entry *entry;
+ char *end;
+
+ acl_type = ACL_TYPE_ACCESS;
+ carried_error = fts_options = 0;
+ have_mask = have_stdin = n_flag = false;
+
+ TAILQ_INIT(&entrylist);
+
+ while ((ch = getopt(argc, argv, "HLM:PRX:a:bdhkm:nx:")) != -1)
+ switch(ch) {
+ case 'H':
+ H_flag = true;
+ L_flag = false;
+ break;
+ case 'L':
+ L_flag = true;
+ H_flag = false;
+ break;
+ case 'M':
+ entry = zmalloc(sizeof(struct sf_entry));
+ entry->acl = get_acl_from_file(optarg);
+ if (entry->acl == NULL)
+ err(1, "%s: get_acl_from_file() failed",
+ optarg);
+ entry->op = OP_MERGE_ACL;
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
+ break;
+ case 'P':
+ H_flag = L_flag = false;
+ break;
+ case 'R':
+ R_flag = true;
+ break;
+ case 'X':
+ entry = zmalloc(sizeof(struct sf_entry));
+ entry->acl = get_acl_from_file(optarg);
+ entry->op = OP_REMOVE_ACL;
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
+ break;
+ case 'a':
+ entry = zmalloc(sizeof(struct sf_entry));
+
+ entry_number = strtol(optarg, &end, 10);
+ if (end - optarg != (int)strlen(optarg))
+ errx(1, "%s: invalid entry number", optarg);
+ if (entry_number < 0)
+ errx(1,
+ "%s: entry number cannot be less than zero",
+ optarg);
+ entry->entry_number = entry_number;
+
+ if (argv[optind] == NULL)
+ errx(1, "missing ACL");
+ entry->acl = acl_from_text(argv[optind]);
+ if (entry->acl == NULL)
+ err(1, "%s", argv[optind]);
+ optind++;
+ entry->op = OP_ADD_ACL;
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
+ break;
+ case 'b':
+ entry = zmalloc(sizeof(struct sf_entry));
+ entry->op = OP_REMOVE_EXT;
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
+ break;
+ case 'd':
+ acl_type = ACL_TYPE_DEFAULT;
+ break;
+ case 'h':
+ h_flag = 1;
+ break;
+ case 'k':
+ entry = zmalloc(sizeof(struct sf_entry));
+ entry->op = OP_REMOVE_DEF;
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
+ break;
+ case 'm':
+ entry = zmalloc(sizeof(struct sf_entry));
+ entry->acl = acl_from_text(optarg);
+ if (entry->acl == NULL)
+ err(1, "%s", optarg);
+ entry->op = OP_MERGE_ACL;
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
+ break;
+ case 'n':
+ n_flag = true;
+ break;
+ case 'x':
+ entry = zmalloc(sizeof(struct sf_entry));
+ entry_number = strtol(optarg, &end, 10);
+ if (end - optarg == (int)strlen(optarg)) {
+ if (entry_number < 0)
+ errx(1,
+ "%s: entry number cannot be less than zero",
+ optarg);
+ entry->entry_number = entry_number;
+ entry->op = OP_REMOVE_BY_NUMBER;
+ } else {
+ entry->acl = acl_from_text(optarg);
+ if (entry->acl == NULL)
+ err(1, "%s", optarg);
+ entry->op = OP_REMOVE_ACL;
+ }
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
+ break;
+ default:
+ usage();
+ break;
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!n_flag && TAILQ_EMPTY(&entrylist))
+ usage();
+
+ /* Take list of files from stdin. */
+ if (argc == 0 || strcmp(argv[0], "-") == 0) {
+ files_list = stdin_files();
+ } else
+ files_list = argv;
+
+ if (R_flag) {
+ if (h_flag)
+ errx(1, "the -R and -h options may not be "
+ "specified together.");
+ if (L_flag) {
+ fts_options = FTS_LOGICAL;
+ } else {
+ fts_options = FTS_PHYSICAL;
+
+ if (H_flag) {
+ fts_options |= FTS_COMFOLLOW;
+ }
+ }
+ } else if (h_flag) {
+ fts_options = FTS_PHYSICAL;
+ } else {
+ fts_options = FTS_LOGICAL;
+ }
+
+ /* Open all files. */
+ if ((ftsp = fts_open(files_list, fts_options | FTS_NOSTAT, 0)) == NULL)
+ err(1, "fts_open");
+ while ((file = fts_read(ftsp)) != NULL)
+ carried_error += handle_file(ftsp, file);
+
+ return (carried_error);
+}
diff --git a/bin/setfacl/setfacl.h b/bin/setfacl/setfacl.h
new file mode 100644
index 00000000000..5c7f4fe54d2
--- /dev/null
+++ b/bin/setfacl/setfacl.h
@@ -0,0 +1,64 @@
+/* $NetBSD: setfacl.h,v 1.1 2020/05/16 18:31:45 christos Exp $ */
+
+/*-
+ * Copyright (c) 2001 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/bin/setfacl/setfacl.h 333065 2018-04-27 15:25:24Z emaste $
+ */
+
+#ifndef _SETFACL_H
+#define _SETFACL_H
+
+#include <stdbool.h>
+
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <sys/queue.h>
+
+/* files.c */
+acl_t get_acl_from_file(const char *filename);
+/* merge.c */
+int merge_acl(acl_t acl, acl_t *prev_acl, const char *filename);
+int add_acl(acl_t acl, uint entry_number, acl_t *prev_acl,
+ const char *filename);
+/* remove.c */
+int remove_acl(acl_t acl, acl_t *prev_acl, const char *filename);
+int remove_by_number(uint entry_number, acl_t *prev_acl,
+ const char *filename);
+int remove_default(acl_t *prev_acl, const char *filename);
+void remove_ext(acl_t *prev_acl, const char *filename);
+/* mask.c */
+int set_acl_mask(acl_t *prev_acl, const char *filename);
+/* util.c */
+void *zmalloc(size_t size);
+void *zrealloc(void *ptr, size_t size);
+const char *brand_name(int brand);
+int branding_mismatch(int brand1, int brand2);
+
+extern bool have_mask;
+extern bool have_stdin;
+extern bool n_flag;
+
+#endif /* _SETFACL_H */
diff --git a/bin/setfacl/util.c b/bin/setfacl/util.c
new file mode 100644
index 00000000000..1317b1d3361
--- /dev/null
+++ b/bin/setfacl/util.c
@@ -0,0 +1,85 @@
+/* $NetBSD: util.c,v 1.1 2020/05/16 18:31:45 christos Exp $ */
+
+/*-
+ * Copyright (c) 2001 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/bin/setfacl/util.c 332396 2018-04-10 23:29:57Z emaste $");
+#else
+__RCSID("$NetBSD: util.c,v 1.1 2020/05/16 18:31:45 christos Exp $");
+#endif
+
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "setfacl.h"
+
+void *
+zmalloc(size_t size)
+{
+ void *ptr;
+
+ ptr = calloc(1, size);
+ if (ptr == NULL)
+ err(1, "calloc() failed");
+ return (ptr);
+}
+
+void *
+zrealloc(void *ptr, size_t size)
+{
+ void *newptr;
+
+ newptr = realloc(ptr, size);
+ if (newptr == NULL)
+ err(1, "realloc() failed");
+ return (newptr);
+}
+
+const char *
+brand_name(int brand)
+{
+ switch (brand) {
+ case ACL_BRAND_NFS4:
+ return "NFSv4";
+ case ACL_BRAND_POSIX:
+ return "POSIX.1e";
+ default:
+ return "unknown";
+ }
+}
+
+int
+branding_mismatch(int brand1, int brand2)
+{
+ if (brand1 == ACL_BRAND_UNKNOWN || brand2 == ACL_BRAND_UNKNOWN)
+ return (0);
+ if (brand1 != brand2)
+ return (1);
+ return (0);
+}
diff --git a/distrib/sets/lists/base/mi b/distrib/sets/lists/base/mi
index 58e568b7e08..e8d7972822e 100644
--- a/distrib/sets/lists/base/mi
+++ b/distrib/sets/lists/base/mi
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1242 2020/05/01 22:25:18 christos Exp $
+# $NetBSD: mi,v 1.1243 2020/05/16 18:31:45 christos Exp $
#
# Note: Don't delete entries from here - mark them as "obsolete" instead,
# unless otherwise stated below.
@@ -33,6 +33,7 @@
./bin/echo base-util-root
./bin/ed base-util-root
./bin/expr base-util-root
+./bin/getfacl base-util-root
./bin/hostname base-util-root
./bin/kill base-util-root
./bin/ksh base-util-root
@@ -51,6 +52,7 @@
./bin/rmail base-obsolete obsolete
./bin/rmdir base-util-root
./bin/rump.dd base-util-root rump
+./bin/setfacl base-util-root
./bin/sh base-util-root
./bin/sleep base-util-root
./bin/stty base-util-root
diff --git a/distrib/sets/lists/comp/mi b/distrib/sets/lists/comp/mi
index 397efa3316d..e2ef8cb8532 100644
--- a/distrib/sets/lists/comp/mi
+++ b/distrib/sets/lists/comp/mi
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.2326 2020/05/15 23:32:27 christos Exp $
+# $NetBSD: mi,v 1.2327 2020/05/16 18:31:45 christos Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
./etc/mtree/set.comp comp-sys-root
@@ -844,8 +844,8 @@
./usr/include/fcntl.h comp-c-include
./usr/include/fenv.h comp-c-include
./usr/include/fetch.h comp-c-include
-./usr/include/fido.h comp-c-include
./usr/include/fido comp-c-include
+./usr/include/fido.h comp-c-include
./usr/include/fido/bio.h comp-c-include
./usr/include/fido/credman.h comp-c-include
./usr/include/fido/eddsa.h comp-c-include
@@ -2974,6 +2974,7 @@
./usr/include/strings.h comp-c-include
./usr/include/struct.h comp-c-include
./usr/include/sys/acct.h comp-c-include
+./usr/include/sys/acl.h comp-c-include
./usr/include/sys/agpio.h comp-c-include
./usr/include/sys/aio.h comp-c-include
./usr/include/sys/ansi.h comp-c-include
@@ -3493,10 +3494,10 @@
./usr/lib/libexecinfo_p.a comp-c-proflib compatfile,profile
./usr/lib/libexpat.a comp-c-lib compatfile
./usr/lib/libexpat_p.a comp-c-proflib compatfile,profile
-./usr/lib/libfido2.a comp-c-lib compatfile
-./usr/lib/libfido2_p.a comp-c-proflib compatfile,profile
./usr/lib/libfetch.a comp-c-lib compatfile
./usr/lib/libfetch_p.a comp-c-proflib compatfile,profile
+./usr/lib/libfido2.a comp-c-lib compatfile
+./usr/lib/libfido2_p.a comp-c-proflib compatfile,profile
./usr/lib/libfl.a comp-c-lib compatfile
./usr/lib/libfl_p.a comp-c-proflib compatfile,profile
./usr/lib/libform.a comp-c-lib compatfile
@@ -5561,6 +5562,58 @@
./usr/share/man/cat3/a64l.0 comp-c-catman .cat
./usr/share/man/cat3/abort.0 comp-c-catman .cat
./usr/share/man/cat3/abs.0 comp-c-catman .cat
+./usr/share/man/cat3/acl.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_add_flag_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_add_perm.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_calc_mask.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_clear_flags_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_clear_perms.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_copy_entry.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_create_entry.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_create_entry_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_delete.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_delete_def_file.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_delete_entry.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_delete_entry_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_delete_fd_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_delete_file_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_delete_flag_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_delete_perm.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_dup.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_free.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_from_text.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_brand_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_entry.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_entry_type_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_fd.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_fd_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_file.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_flag_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_flagset_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_link_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_perm_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_permset.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_qualifier.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_get_tag_type.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_init.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_is_trivial_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_set.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_set_entry_type_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_set_fd.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_set_fd_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_set_file.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_set_flagset_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_set_link_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_set_permset.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_set_qualifier.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_set_tag_type.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_strip_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_to_text.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_to_text_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_valid.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_valid_fd_np.0 comp-c-catman .cat
+./usr/share/man/cat3/acl_valid_file_np.0 comp-c-catman .cat
./usr/share/man/cat3/acos.0 comp-c-catman .cat
./usr/share/man/cat3/acosf.0 comp-c-catman .cat
./usr/share/man/cat3/acosh.0 comp-c-catman .cat
@@ -8872,6 +8925,7 @@
./usr/share/man/cat3/popenve.0 comp-c-catman .cat
./usr/share/man/cat3/pos_form_cursor.0 comp-c-catman .cat
./usr/share/man/cat3/pos_menu_cursor.0 comp-c-catman .cat
+./usr/share/man/cat3/posix1e.0 comp-c-catman .cat
./usr/share/man/cat3/posix2time.0 comp-c-catman .cat
./usr/share/man/cat3/posix2time_z.0 comp-c-catman .cat
./usr/share/man/cat3/posix_memalign.0 comp-c-catman .cat
@@ -13650,6 +13704,58 @@
./usr/share/man/html3/a64l.html comp-c-htmlman html
./usr/share/man/html3/abort.html comp-c-htmlman html
./usr/share/man/html3/abs.html comp-c-htmlman html
+./usr/share/man/html3/acl.html comp-c-htmlman html
+./usr/share/man/html3/acl_add_flag_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_add_perm.html comp-c-htmlman html
+./usr/share/man/html3/acl_calc_mask.html comp-c-htmlman html
+./usr/share/man/html3/acl_clear_flags_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_clear_perms.html comp-c-htmlman html
+./usr/share/man/html3/acl_copy_entry.html comp-c-htmlman html
+./usr/share/man/html3/acl_create_entry.html comp-c-htmlman html
+./usr/share/man/html3/acl_create_entry_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_delete.html comp-c-htmlman html
+./usr/share/man/html3/acl_delete_def_file.html comp-c-htmlman html
+./usr/share/man/html3/acl_delete_entry.html comp-c-htmlman html
+./usr/share/man/html3/acl_delete_entry_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_delete_fd_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_delete_file_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_delete_flag_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_delete_perm.html comp-c-htmlman html
+./usr/share/man/html3/acl_dup.html comp-c-htmlman html
+./usr/share/man/html3/acl_free.html comp-c-htmlman html
+./usr/share/man/html3/acl_from_text.html comp-c-htmlman html
+./usr/share/man/html3/acl_get.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_brand_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_entry.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_entry_type_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_fd.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_fd_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_file.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_flag_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_flagset_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_link_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_perm_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_permset.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_qualifier.html comp-c-htmlman html
+./usr/share/man/html3/acl_get_tag_type.html comp-c-htmlman html
+./usr/share/man/html3/acl_init.html comp-c-htmlman html
+./usr/share/man/html3/acl_is_trivial_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_set.html comp-c-htmlman html
+./usr/share/man/html3/acl_set_entry_type_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_set_fd.html comp-c-htmlman html
+./usr/share/man/html3/acl_set_fd_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_set_file.html comp-c-htmlman html
+./usr/share/man/html3/acl_set_flagset_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_set_link_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_set_permset.html comp-c-htmlman html
+./usr/share/man/html3/acl_set_qualifier.html comp-c-htmlman html
+./usr/share/man/html3/acl_set_tag_type.html comp-c-htmlman html
+./usr/share/man/html3/acl_strip_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_to_text.html comp-c-htmlman html
+./usr/share/man/html3/acl_to_text_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_valid.html comp-c-htmlman html
+./usr/share/man/html3/acl_valid_fd_np.html comp-c-htmlman html
+./usr/share/man/html3/acl_valid_file_np.html comp-c-htmlman html
./usr/share/man/html3/acos.html comp-c-htmlman html
./usr/share/man/html3/acosf.html comp-c-htmlman html
./usr/share/man/html3/acosh.html comp-c-htmlman html
@@ -16902,6 +17008,7 @@
./usr/share/man/html3/popenve.html comp-c-htmlman html
./usr/share/man/html3/pos_form_cursor.html comp-c-htmlman html
./usr/share/man/html3/pos_menu_cursor.html comp-c-htmlman html
+./usr/share/man/html3/posix1e.html comp-c-htmlman html
./usr/share/man/html3/posix2time.html comp-c-htmlman html
./usr/share/man/html3/posix2time_z.html comp-c-htmlman html
./usr/share/man/html3/posix_memalign.html comp-c-htmlman html
@@ -21576,6 +21683,58 @@
./usr/share/man/man3/a64l.3 comp-c-man .man
./usr/share/man/man3/abort.3 comp-c-man .man
./usr/share/man/man3/abs.3 comp-c-man .man
+./usr/share/man/man3/acl.3 comp-c-man .man
+./usr/share/man/man3/acl_add_flag_np.3 comp-c-man .man
+./usr/share/man/man3/acl_add_perm.3 comp-c-man .man
+./usr/share/man/man3/acl_calc_mask.3 comp-c-man .man
+./usr/share/man/man3/acl_clear_flags_np.3 comp-c-man .man
+./usr/share/man/man3/acl_clear_perms.3 comp-c-man .man
+./usr/share/man/man3/acl_copy_entry.3 comp-c-man .man
+./usr/share/man/man3/acl_create_entry.3 comp-c-man .man
+./usr/share/man/man3/acl_create_entry_np.3 comp-c-man .man
+./usr/share/man/man3/acl_delete.3 comp-c-man .man
+./usr/share/man/man3/acl_delete_def_file.3 comp-c-man .man
+./usr/share/man/man3/acl_delete_entry.3 comp-c-man .man
+./usr/share/man/man3/acl_delete_entry_np.3 comp-c-man .man
+./usr/share/man/man3/acl_delete_fd_np.3 comp-c-man .man
+./usr/share/man/man3/acl_delete_file_np.3 comp-c-man .man
+./usr/share/man/man3/acl_delete_flag_np.3 comp-c-man .man
+./usr/share/man/man3/acl_delete_perm.3 comp-c-man .man
+./usr/share/man/man3/acl_dup.3 comp-c-man .man
+./usr/share/man/man3/acl_free.3 comp-c-man .man
+./usr/share/man/man3/acl_from_text.3 comp-c-man .man
+./usr/share/man/man3/acl_get.3 comp-c-man .man
+./usr/share/man/man3/acl_get_brand_np.3 comp-c-man .man
+./usr/share/man/man3/acl_get_entry.3 comp-c-man .man
+./usr/share/man/man3/acl_get_entry_type_np.3 comp-c-man .man
+./usr/share/man/man3/acl_get_fd.3 comp-c-man .man
+./usr/share/man/man3/acl_get_fd_np.3 comp-c-man .man
+./usr/share/man/man3/acl_get_file.3 comp-c-man .man
+./usr/share/man/man3/acl_get_flag_np.3 comp-c-man .man
+./usr/share/man/man3/acl_get_flagset_np.3 comp-c-man .man
+./usr/share/man/man3/acl_get_link_np.3 comp-c-man .man
+./usr/share/man/man3/acl_get_perm_np.3 comp-c-man .man
+./usr/share/man/man3/acl_get_permset.3 comp-c-man .man
+./usr/share/man/man3/acl_get_qualifier.3 comp-c-man .man
+./usr/share/man/man3/acl_get_tag_type.3 comp-c-man .man
+./usr/share/man/man3/acl_init.3 comp-c-man .man
+./usr/share/man/man3/acl_is_trivial_np.3 comp-c-man .man
+./usr/share/man/man3/acl_set.3 comp-c-man .man
+./usr/share/man/man3/acl_set_entry_type_np.3 comp-c-man .man
+./usr/share/man/man3/acl_set_fd.3 comp-c-man .man
+./usr/share/man/man3/acl_set_fd_np.3 comp-c-man .man
+./usr/share/man/man3/acl_set_file.3 comp-c-man .man
+./usr/share/man/man3/acl_set_flagset_np.3 comp-c-man .man
+./usr/share/man/man3/acl_set_link_np.3 comp-c-man .man
+./usr/share/man/man3/acl_set_permset.3 comp-c-man .man
+./usr/share/man/man3/acl_set_qualifier.3 comp-c-man .man
+./usr/share/man/man3/acl_set_tag_type.3 comp-c-man .man
+./usr/share/man/man3/acl_strip_np.3 comp-c-man .man
+./usr/share/man/man3/acl_to_text.3 comp-c-man .man
+./usr/share/man/man3/acl_to_text_np.3 comp-c-man .man
+./usr/share/man/man3/acl_valid.3 comp-c-man .man
+./usr/share/man/man3/acl_valid_fd_np.3 comp-c-man .man
+./usr/share/man/man3/acl_valid_file_np.3 comp-c-man .man
./usr/share/man/man3/acos.3 comp-c-man .man
./usr/share/man/man3/acosf.3 comp-c-man .man
./usr/share/man/man3/acosh.3 comp-c-man .man
@@ -24922,6 +25081,7 @@
./usr/share/man/man3/popenve.3 comp-c-man .man
./usr/share/man/man3/pos_form_cursor.3 comp-c-man .man
./usr/share/man/man3/pos_menu_cursor.3 comp-c-man .man
+./usr/share/man/man3/posix1e.3 comp-c-man .man
./usr/share/man/man3/posix2time.3 comp-c-man .man
./usr/share/man/man3/posix2time_z.3 comp-c-man .man
./usr/share/man/man3/posix_memalign.3 comp-c-man .man
@@ -26483,8 +26643,8 @@
./usr/share/man/man3/wdelch.3 comp-c-man .man
./usr/share/man/man3/wdeleteln.3 comp-c-man .man
./usr/share/man/man3/wechochar.3 comp-c-man .man
-./usr/share/man/man3/werase.3 comp-c-man .man
./usr/share/man/man3/wenclose.3 comp-c-man .man
+./usr/share/man/man3/werase.3 comp-c-man .man
./usr/share/man/man3/wgetch.3 comp-c-man .man
./usr/share/man/man3/wgetnstr.3 comp-c-man .man
./usr/share/man/man3/wgetstr.3 comp-c-man .man
diff --git a/distrib/sets/lists/debug/mi b/distrib/sets/lists/debug/mi
index 742e16f8951..4dddfa024c0 100644
--- a/distrib/sets/lists/debug/mi
+++ b/distrib/sets/lists/debug/mi
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.310 2020/05/15 23:32:28 christos Exp $
+# $NetBSD: mi,v 1.311 2020/05/16 18:31:46 christos Exp $
./etc/mtree/set.debug comp-sys-root
./usr/lib comp-sys-usr compatdir
./usr/lib/i18n/libBIG5_g.a comp-c-debuglib debuglib,compatfile
@@ -287,6 +287,7 @@
./usr/libdata/debug/bin/echo.debug comp-util-debug debug
./usr/libdata/debug/bin/ed.debug comp-util-debug debug
./usr/libdata/debug/bin/expr.debug comp-util-debug debug
+./usr/libdata/debug/bin/getfacl.debug comp-util-debug debug
./usr/libdata/debug/bin/hostname.debug comp-util-debug debug
./usr/libdata/debug/bin/kill.debug comp-util-debug debug
./usr/libdata/debug/bin/ksh.debug comp-util-debug debug
@@ -303,6 +304,7 @@
./usr/libdata/debug/bin/rm.debug comp-util-debug debug
./usr/libdata/debug/bin/rmdir.debug comp-util-debug debug
./usr/libdata/debug/bin/rump.dd.debug comp-util-debug debug,rump
+./usr/libdata/debug/bin/setfacl.debug comp-util-debug debug
./usr/libdata/debug/bin/sh.debug comp-util-debug debug
./usr/libdata/debug/bin/sleep.debug comp-util-debug debug
./usr/libdata/debug/bin/stty.debug comp-util-debug debug
diff --git a/distrib/sets/lists/man/mi b/distrib/sets/lists/man/mi
index d90e4ac6f44..ca7e70e7aa6 100644
--- a/distrib/sets/lists/man/mi
+++ b/distrib/sets/lists/man/mi
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1688 2020/05/16 13:46:10 maya Exp $
+# $NetBSD: mi,v 1.1689 2020/05/16 18:31:46 christos Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -188,6 +188,7 @@
./usr/share/man/cat1/getconf.0 man-util-catman .cat
./usr/share/man/cat1/getent.0 man-util-catman .cat
./usr/share/man/cat1/getextattr.0 man-util-catman .cat
+./usr/share/man/cat1/getfacl.0 man-util-catman .cat
./usr/share/man/cat1/getopt.0 man-util-catman .cat
./usr/share/man/cat1/gettext.0 man-locale-catman .cat
./usr/share/man/cat1/gkermit.0 man-obsolete .cat,obsolete
@@ -520,6 +521,7 @@
./usr/share/man/cat1/sendmail.0 man-postfix-catman postfix,.cat
./usr/share/man/cat1/seq.0 man-util-catman .cat
./usr/share/man/cat1/setextattr.0 man-util-catman .cat
+./usr/share/man/cat1/setfacl.0 man-util-catman .cat
./usr/share/man/cat1/sftp.0 man-secsh-catman .cat
./usr/share/man/cat1/sh.0 man-util-catman .cat
./usr/share/man/cat1/sha1.0 man-util-catman .cat
@@ -3487,6 +3489,7 @@
./usr/share/man/html1/getconf.html man-util-htmlman html
./usr/share/man/html1/getent.html man-util-htmlman html
./usr/share/man/html1/getextattr.html man-util-htmlman html
+./usr/share/man/html1/getfacl.html man-util-htmlman html
./usr/share/man/html1/getopt.html man-util-htmlman html
./usr/share/man/html1/gettext.html man-locale-htmlman html
./usr/share/man/html1/gkermit.html man-obsolete html,obsolete
@@ -3801,6 +3804,7 @@
./usr/share/man/html1/sendmail.html man-postfix-htmlman postfix,html
./usr/share/man/html1/seq.html man-util-htmlman html
./usr/share/man/html1/setextattr.html man-util-htmlman html
+./usr/share/man/html1/setfacl.html man-util-htmlman html
./usr/share/man/html1/sftp.html man-secsh-htmlman html
./usr/share/man/html1/sh.html man-util-htmlman html
./usr/share/man/html1/sha1.html man-util-htmlman html
@@ -6402,6 +6406,7 @@
./usr/share/man/man1/getconf.1 man-util-man .man
./usr/share/man/man1/getent.1 man-util-man .man
./usr/share/man/man1/getextattr.1 man-util-man .man
+./usr/share/man/man1/getfacl.1 man-util-man .man
./usr/share/man/man1/getopt.1 man-util-man .man
./usr/share/man/man1/gettext.1 man-locale-man .man
./usr/share/man/man1/gkermit.1 man-obsolete .man,obsolete
@@ -6734,6 +6739,7 @@
./usr/share/man/man1/sendmail.1 man-postfix-man postfix,.man
./usr/share/man/man1/seq.1 man-util-man .man
./usr/share/man/man1/setextattr.1 man-util-man .man
+./usr/share/man/man1/setfacl.1 man-util-man .man
./usr/share/man/man1/sftp.1 man-secsh-man .man
./usr/share/man/man1/sh.1 man-util-man .man
./usr/share/man/man1/sha1.1 man-util-man .man
diff --git a/external/bsd/libarchive/include/config_netbsd.h b/external/bsd/libarchive/include/config_netbsd.h
index b9b46753a13..98850e62c60 100644
--- a/external/bsd/libarchive/include/config_netbsd.h
+++ b/external/bsd/libarchive/include/config_netbsd.h
@@ -5,10 +5,10 @@
/* #undef ARCHIVE_ACL_DARWIN */
/* FreeBSD ACL support */
-/* #undef ARCHIVE_ACL_FREEBSD */
+#define ARCHIVE_ACL_FREEBSD 1
/* FreeBSD NFSv4 ACL support */
-/* #undef ARCHIVE_ACL_FREEBSD_NFS4 */
+#define ARCHIVE_ACL_FREEBSD_NFS4 1
/* Linux POSIX.1e ACL support via libacl */
/* #undef ARCHIVE_ACL_LIBACL */
@@ -170,109 +170,109 @@
/* #undef HAVE_ACLENT_T */
/* Define to 1 if you have the `acl_add_flag_np' function. */
-/* #undef HAVE_ACL_ADD_FLAG_NP */
+#define HAVE_ACL_ADD_FLAG_NP 1
/* Define to 1 if you have the `acl_add_perm' function. */
-/* #undef HAVE_ACL_ADD_PERM */
+#define HAVE_ACL_ADD_PERM 1
/* Define to 1 if you have the `acl_clear_flags_np' function. */
-/* #undef HAVE_ACL_CLEAR_FLAGS_NP */
+#define HAVE_ACL_CLEAR_FLAGS_NP 1
/* Define to 1 if you have the `acl_clear_perms' function. */
-/* #undef HAVE_ACL_CLEAR_PERMS */
+#define HAVE_ACL_CLEAR_PERMS 1
/* Define to 1 if you have the `acl_create_entry' function. */
-/* #undef HAVE_ACL_CREATE_ENTRY */
+#define HAVE_ACL_CREATE_ENTRY 1
/* Define to 1 if you have the `acl_delete_def_file' function. */
-/* #undef HAVE_ACL_DELETE_DEF_FILE */
+#define HAVE_ACL_DELETE_DEF_FILE 1
/* Define to 1 if the system has the type `acl_entry_t'. */
-/* #undef HAVE_ACL_ENTRY_T */
+#define HAVE_ACL_ENTRY_T 1
/* Define to 1 if you have the `acl_free' function. */
-/* #undef HAVE_ACL_FREE */
+#define HAVE_ACL_FREE 1
/* Define to 1 if you have the `acl_get_brand_np' function. */
-/* #undef HAVE_ACL_GET_BRAND_NP */
+#define HAVE_ACL_GET_BRAND_NP 1
/* Define to 1 if you have the `acl_get_entry' function. */
-/* #undef HAVE_ACL_GET_ENTRY */
+#define HAVE_ACL_GET_ENTRY 1
/* Define to 1 if you have the `acl_get_entry_type_np' function. */
-/* #undef HAVE_ACL_GET_ENTRY_TYPE_NP */
+#define HAVE_ACL_GET_ENTRY_TYPE_NP 1
/* Define to 1 if you have the `acl_get_fd' function. */
-/* #undef HAVE_ACL_GET_FD */
+#define HAVE_ACL_GET_FD 1
/* Define to 1 if you have the `acl_get_fd_np' function. */
-/* #undef HAVE_ACL_GET_FD_NP */
+#define HAVE_ACL_GET_FD_NP 1
/* Define to 1 if you have the `acl_get_file' function. */
-/* #undef HAVE_ACL_GET_FILE */
+#define HAVE_ACL_GET_FILE 1
/* Define to 1 if you have the `acl_get_flagset_np' function. */
-/* #undef HAVE_ACL_GET_FLAGSET_NP */
+#define HAVE_ACL_GET_FLAGSET_NP 1
/* Define to 1 if you have the `acl_get_flag_np' function. */
-/* #undef HAVE_ACL_GET_FLAG_NP */
+#define HAVE_ACL_GET_FLAG_NP 1
/* Define to 1 if you have the `acl_get_link_np' function. */
-/* #undef HAVE_ACL_GET_LINK_NP */
+#define HAVE_ACL_GET_LINK_NP 1
/* Define to 1 if you have the `acl_get_perm' function. */
/* #undef HAVE_ACL_GET_PERM */
/* Define to 1 if you have the `acl_get_permset' function. */
-/* #undef HAVE_ACL_GET_PERMSET */
+#define HAVE_ACL_GET_PERMSET 1
/* Define to 1 if you have the `acl_get_perm_np' function. */
-/* #undef HAVE_ACL_GET_PERM_NP */
+#define HAVE_ACL_GET_PERM_NP 1
/* Define to 1 if you have the `acl_get_qualifier' function. */
-/* #undef HAVE_ACL_GET_QUALIFIER */
+#define HAVE_ACL_GET_QUALIFIER 1
/* Define to 1 if you have the `acl_get_tag_type' function. */
-/* #undef HAVE_ACL_GET_TAG_TYPE */
+#define HAVE_ACL_GET_TAG_TYPE 1
/* Define to 1 if you have the `acl_init' function. */
-/* #undef HAVE_ACL_INIT */
+#define HAVE_ACL_INIT 1
/* Define to 1 if you have the `acl_is_trivial_np' function. */
-/* #undef HAVE_ACL_IS_TRIVIAL_NP */
+#define HAVE_ACL_IS_TRIVIAL_NP 1
/* Define to 1 if you have the <acl/libacl.h> header file. */
/* #undef HAVE_ACL_LIBACL_H */
/* Define to 1 if the system has the type `acl_permset_t'. */
-/* #undef HAVE_ACL_PERMSET_T */
+#define HAVE_ACL_PERMSET_T 1
/* Define to 1 if you have the `acl_set_entry_type_np' function. */
-/* #undef HAVE_ACL_SET_ENTRY_TYPE_NP */
+#define HAVE_ACL_SET_ENTRY_TYPE_NP 1
/* Define to 1 if you have the `acl_set_fd' function. */
-/* #undef HAVE_ACL_SET_FD */
+#define HAVE_ACL_SET_FD 1
/* Define to 1 if you have the `acl_set_fd_np' function. */
-/* #undef HAVE_ACL_SET_FD_NP */
+#define HAVE_ACL_SET_FD_NP 1
/* Define to 1 if you have the `acl_set_file' function. */
-/* #undef HAVE_ACL_SET_FILE */
+#define HAVE_ACL_SET_FILE 1
/* Define to 1 if you have the `acl_set_link_np' function. */
-/* #undef HAVE_ACL_SET_LINK_NP */
+#define HAVE_ACL_SET_LINK_NP 1
/* Define to 1 if you have the `acl_set_qualifier' function. */
-/* #undef HAVE_ACL_SET_QUALIFIER */
+#define HAVE_ACL_SET_QUALIFIER 1
/* Define to 1 if you have the `acl_set_tag_type' function. */
-/* #undef HAVE_ACL_SET_TAG_TYPE */
+#define HAVE_ACL_SET_TAG_TYPE 1
/* Define to 1 if the system has the type `acl_t'. */
-/* #undef HAVE_ACL_T */
+#define HAVE_ACL_T 1
/* Define to 1 if the system has the type `acl_tag_t'. */
-/* #undef HAVE_ACL_TAG_T */
+#define HAVE_ACL_TAG_T 1
/* Define to 1 if you have the `arc4random_buf' function. */
#define HAVE_ARC4RANDOM_BUF 1
@@ -324,19 +324,19 @@
/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if
you don't. */
-/* #undef HAVE_DECL_ACL_SYNCHRONIZE */
+#define HAVE_DECL_ACL_SYNCHRONIZE 1
/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if
you don't. */
-/* #undef HAVE_DECL_ACL_TYPE_EXTENDED */
+#define HAVE_DECL_ACL_TYPE_EXTENDED 0
/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you
don't. */
-/* #undef HAVE_DECL_ACL_TYPE_NFS4 */
+#define HAVE_DECL_ACL_TYPE_NFS4 1
/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you
don't. */
-/* #undef HAVE_DECL_ACL_USER */
+#define HAVE_DECL_ACL_USER 1
/* Define to 1 if you have the declaration of `EXTATTR_NAMESPACE_USER', and to
0 if you don't. */
@@ -920,7 +920,7 @@
/* Define to 1 if `stat' has the bug that it succeeds when given the
zero-length file name argument. */
-#define HAVE_STAT_EMPTY_STRING_BUG 1
+/* #undef HAVE_STAT_EMPTY_STRING_BUG */
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
@@ -1013,7 +1013,7 @@
#define HAVE_SYMLINK 1
/* Define to 1 if you have the <sys/acl.h> header file. */
-/* #undef HAVE_SYS_ACL_H */
+#define HAVE_SYS_ACL_H 1
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#define HAVE_SYS_CDEFS_H 1
diff --git a/external/bsd/libarchive/lib/libarchive/Makefile b/external/bsd/libarchive/lib/libarchive/Makefile
index 394d5169b99..95f50e8517a 100644
--- a/external/bsd/libarchive/lib/libarchive/Makefile
+++ b/external/bsd/libarchive/lib/libarchive/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.11 2019/10/13 07:28:06 mrg Exp $
+# $NetBSD: Makefile,v 1.12 2020/05/16 18:31:46 christos Exp $
.include <bsd.init.mk>
@@ -20,6 +20,7 @@ SRCS= archive_acl.c \
archive_cmdline.c \
archive_cryptor.c \
archive_digest.c \
+ archive_disk_acl_freebsd.c \
archive_entry.c \
archive_entry_copy_stat.c \
archive_entry_link_resolver.c \
diff --git a/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c b/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c
index 7ebb1bf893b..e78e0821f44 100644
--- a/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c
+++ b/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c
@@ -1590,7 +1590,7 @@ sfs_access(void *v)
SFS_NODE_ASSERT(ap->a_vp);
ZFS_ENTER(zfsvfs);
- if (ap->a_mode & FWRITE)
+ if (ap->a_accmode & FWRITE)
error = EACCES;
ZFS_EXIT(zfsvfs);
diff --git a/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c b/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c
index 6c179ccacd6..a171dcfa55b 100644
--- a/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c
+++ b/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c
@@ -5155,11 +5155,11 @@ zfs_netbsd_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
- int mode = ap->a_mode;
+ accmode_t accmode = ap->a_accmode;
mode_t zfs_mode = 0;
kauth_cred_t cred = ap->a_cred;
int error;
@@ -5169,11 +5169,11 @@ zfs_netbsd_access(void *v)
* and it exists only because of randomness in zfs_unix_to_v4
* and zfs_zaccess_rwx in zfs_acl.c.
*/
- if (mode & VREAD)
+ if (accmode & VREAD)
zfs_mode |= S_IROTH;
- if (mode & VWRITE)
+ if (accmode & VWRITE)
zfs_mode |= S_IWOTH;
- if (mode & VEXEC)
+ if (accmode & VEXEC)
zfs_mode |= S_IXOTH;
zfs_mode <<= 6;
@@ -5631,8 +5631,7 @@ zfs_netbsd_setattr(void *v)
}
error = kauth_authorize_vnode(cred, action, vp, NULL,
- genfs_can_chflags(cred, vp->v_type, zp->z_uid,
- changing_sysflags));
+ genfs_can_chflags(vp, cred, zp->z_uid, changing_sysflags));
if (error)
return error;
}
@@ -5640,8 +5639,8 @@ zfs_netbsd_setattr(void *v)
if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
vap->va_birthtime.tv_sec != VNOVAL) {
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
- NULL, genfs_can_chtimes(vp, vap->va_vaflags, zp->z_uid,
- cred));
+ NULL, genfs_can_chtimes(vp, cred, zp->z_uid,
+ vap->va_vaflags));
if (error)
return error;
}
@@ -6332,6 +6331,7 @@ const struct vnodeopv_entry_desc zfs_vnodeop_entries[] = {
{ &vop_open_desc, zfs_netbsd_open },
{ &vop_close_desc, zfs_netbsd_close },
{ &vop_access_desc, zfs_netbsd_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_getattr_desc, zfs_netbsd_getattr },
{ &vop_setattr_desc, zfs_netbsd_setattr },
{ &vop_read_desc, zfs_netbsd_read },
@@ -6377,6 +6377,7 @@ const struct vnodeopv_entry_desc zfs_specop_entries[] = {
{ &vop_open_desc, spec_open },
{ &vop_close_desc, spec_close },
{ &vop_access_desc, zfs_netbsd_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_getattr_desc, zfs_netbsd_getattr },
{ &vop_setattr_desc, zfs_netbsd_setattr },
{ &vop_read_desc, /**/zfs_netbsd_read },
@@ -6424,6 +6425,7 @@ const struct vnodeopv_entry_desc zfs_fifoop_entries[] = {
{ &vop_open_desc, vn_fifo_bypass },
{ &vop_close_desc, vn_fifo_bypass },
{ &vop_access_desc, zfs_netbsd_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_getattr_desc, zfs_netbsd_getattr },
{ &vop_setattr_desc, zfs_netbsd_setattr },
{ &vop_read_desc, /**/zfs_netbsd_read },
diff --git a/external/cddl/osnet/sys/kern/policy.c b/external/cddl/osnet/sys/kern/policy.c
index 0265d5a0050..1d69098782e 100644
--- a/external/cddl/osnet/sys/kern/policy.c
+++ b/external/cddl/osnet/sys/kern/policy.c
@@ -1,4 +1,4 @@
-/* $NetBSD: policy.c,v 1.7 2018/05/28 21:05:09 chs Exp $ */
+/* $NetBSD: policy.c,v 1.8 2020/05/16 18:31:46 christos Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -177,7 +177,7 @@ secpolicy_vnode_owner(vnode_t *vp, cred_t *cred, uid_t owner)
int
secpolicy_vnode_access(cred_t *cred, vnode_t *vp, uid_t owner,
- int mode)
+ accmode_t mode)
{
return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
diff --git a/external/cddl/osnet/sys/sys/policy.h b/external/cddl/osnet/sys/sys/policy.h
index c4d5e6c3c73..207b96b77dc 100644
--- a/external/cddl/osnet/sys/sys/policy.h
+++ b/external/cddl/osnet/sys/sys/policy.h
@@ -1,4 +1,4 @@
-/* $NetBSD: policy.h,v 1.8 2018/05/28 21:05:10 chs Exp $ */
+/* $NetBSD: policy.h,v 1.9 2020/05/16 18:31:46 christos Exp $ */
/*-
* Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
@@ -40,8 +40,6 @@
struct mount;
struct vattr;
-typedef int accmode_t;
-
int secpolicy_nfs(cred_t *cr);
int secpolicy_zfs(cred_t *crd);
int secpolicy_sys_config(cred_t *cr, int checkonly);
diff --git a/include/mntopts.h b/include/mntopts.h
index 251a5301d3d..8a4f544c6d5 100644
--- a/include/mntopts.h
+++ b/include/mntopts.h
@@ -1,4 +1,4 @@
-/* $NetBSD: mntopts.h,v 1.18 2018/01/09 03:31:12 christos Exp $ */
+/* $NetBSD: mntopts.h,v 1.19 2020/05/16 18:31:47 christos Exp $ */
/*-
* Copyright (c) 1994
@@ -43,6 +43,8 @@ struct mntopt {
};
/* User-visible MNT_ flags. */
+#define MOPT_ACLS { "acls", 0, MNT_ACLS, 0 }
+#define MOPT_POSIX1EACLS { "posix1eacls",0, MNT_POSIX1EACLS, 0 }
#define MOPT_ASYNC { "async", 0, MNT_ASYNC, 0 }
#define MOPT_NOCOREDUMP { "coredump", 1, MNT_NOCOREDUMP, 0 }
#define MOPT_NODEV { "dev", 1, MNT_NODEV, 0 }
diff --git a/include/unistd.h b/include/unistd.h
index d4987646637..227b218a95c 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -1,4 +1,4 @@
-/* $NetBSD: unistd.h,v 1.157 2020/05/06 16:17:36 nia Exp $ */
+/* $NetBSD: unistd.h,v 1.158 2020/05/16 18:31:47 christos Exp $ */
/*-
* Copyright (c) 1998, 1999, 2008 The NetBSD Foundation, Inc.
@@ -361,6 +361,7 @@ __aconst char *getusershell(void);
int initgroups(const char *, gid_t);
int iruserok(uint32_t, int, const char *, const char *);
int issetugid(void);
+long lpathconf(const char *, int);
int mkstemps(char *, int);
int nfssvc(int, void *);
int pipe2(int *, int);
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index 907f5acf10e..fa9fd393d6f 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.172 2018/08/03 14:01:21 kamil Exp $
+# $NetBSD: Makefile,v 1.173 2020/05/16 18:31:47 christos Exp $
# @(#)Makefile 8.2 (Berkeley) 2/3/94
#
# All library objects contain sccsid strings by default; they may be
@@ -80,6 +80,7 @@ CPPFLAGS+= -D__BUILD_LEGACY
.include "${.CURDIR}/net/Makefile.inc"
.include "${.CURDIR}/nameser/Makefile.inc"
.include "${.CURDIR}/nls/Makefile.inc"
+.include "${.CURDIR}/posix1e/Makefile.inc"
.include "${.CURDIR}/regex/Makefile.inc"
.include "${.CURDIR}/resolv/Makefile.inc"
.include "${.CURDIR}/rpc/Makefile.inc"
diff --git a/lib/libc/posix1e/Makefile.inc b/lib/libc/posix1e/Makefile.inc
new file mode 100644
index 00000000000..ebfd0fedd74
--- /dev/null
+++ b/lib/libc/posix1e/Makefile.inc
@@ -0,0 +1,89 @@
+# $FreeBSD: head/lib/libc/posix1e/Makefile.inc 338745 2018-09-18 01:40:37Z brd $
+
+.PATH: ${.CURDIR}/posix1e ${NETBSDSRCDIR}/sys/kern
+
+CPPFLAGS+=-D_ACL_PRIVATE
+
+SRCS+= acl_branding.c \
+ acl_calc_mask.c \
+ acl_copy.c \
+ acl_delete.c \
+ acl_delete_entry.c \
+ acl_entry.c \
+ acl_flag.c \
+ acl_free.c \
+ acl_from_text.c \
+ acl_from_text_nfs4.c \
+ acl_get.c \
+ acl_id_to_name.c \
+ acl_init.c \
+ acl_perm.c \
+ acl_set.c \
+ acl_strip.c \
+ acl_support.c \
+ acl_support_nfs4.c \
+ acl_to_text.c \
+ acl_to_text_nfs4.c \
+ acl_valid.c \
+ extattr.c \
+ subr_acl_nfs4.c
+
+MAN+= acl.3 \
+ acl_add_flag_np.3 \
+ acl_add_perm.3 \
+ acl_calc_mask.3 \
+ acl_clear_flags_np.3 \
+ acl_clear_perms.3 \
+ acl_copy_entry.3 \
+ acl_create_entry.3 \
+ acl_delete.3 \
+ acl_delete_entry.3 \
+ acl_delete_flag_np.3 \
+ acl_delete_perm.3 \
+ acl_dup.3 \
+ acl_free.3 \
+ acl_from_text.3 \
+ acl_get.3 \
+ acl_get_brand_np.3 \
+ acl_get_entry.3 \
+ acl_get_entry_type_np.3 \
+ acl_get_flagset_np.3 \
+ acl_get_flag_np.3 \
+ acl_get_permset.3 \
+ acl_get_perm_np.3 \
+ acl_get_qualifier.3 \
+ acl_get_tag_type.3 \
+ acl_init.3 \
+ acl_is_trivial_np.3 \
+ acl_set.3 \
+ acl_set_entry_type_np.3 \
+ acl_set_flagset_np.3 \
+ acl_set_permset.3 \
+ acl_set_qualifier.3 \
+ acl_set_tag_type.3 \
+ acl_strip_np.3 \
+ acl_to_text.3 \
+ acl_valid.3 \
+ extattr.3 \
+ posix1e.3
+
+MLINKS+=acl_create_entry.3 acl_create_entry_np.3 \
+ acl_delete.3 acl_delete_def_file.3 \
+ acl_delete.3 acl_delete_file_np.3 \
+ acl_delete.3 acl_delete_fd_np.3 \
+ acl_delete_entry.3 acl_delete_entry_np.3 \
+ acl_get.3 acl_get_file.3 \
+ acl_get.3 acl_get_fd.3 \
+ acl_get.3 acl_get_fd_np.3 \
+ acl_get.3 acl_get_link_np.3 \
+ acl_set.3 acl_set_file.3 \
+ acl_set.3 acl_set_fd.3 \
+ acl_set.3 acl_set_fd_np.3 \
+ acl_set.3 acl_set_link_np.3 \
+ acl_to_text.3 acl_to_text_np.3 \
+ acl_valid.3 acl_valid_file_np.3 \
+ acl_valid.3 acl_valid_fd_np.3 \
+
+
+# extattr.3 extattr_namespace_to_string.3 \
+# extattr.3 extattr_string_to_namespace.3
diff --git a/lib/libc/posix1e/acl.3 b/lib/libc/posix1e/acl.3
new file mode 100644
index 00000000000..5011cfcbb12
--- /dev/null
+++ b/lib/libc/posix1e/acl.3
@@ -0,0 +1,307 @@
+.\"-
+.\" Copyright (c) 2000, 2001, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl.3 296196 2016-02-29 16:52:06Z trasz $
+.\"
+.Dd October 30, 2014
+.Dt ACL 3
+.Os
+.Sh NAME
+.Nm acl
+.Nd introduction to the POSIX.1e/NFSv4 ACL security API
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Sh DESCRIPTION
+.Fx
+permits file systems to export Access Control Lists via the VFS, and
+provides a library for userland access to and manipulation of these ACLs.
+.Fx
+supports POSIX.1e and NFSv4 ACLs, but
+not all file systems provide support for ACLs, and some may require that
+ACL support be explicitly enabled by the administrator.
+The library calls include routines to allocate, duplicate, retrieve, set,
+and validate ACLs associated with file objects.
+As well as the POSIX.1e routines, there are a number of non-portable
+extensions defined that allow for ACL semantics alternative to
+POSIX.1e, such as NFSv4.
+Where routines are non-standard, they are suffixed with _np to indicate that
+they are not portable.
+.Pp
+POSIX.1e describes a set of ACL manipulation routines to manage the
+contents of ACLs, as well as their relationships with files; almost
+all of these support routines are implemented in
+.Fx .
+.Pp
+Available functions, sorted by behavior, include:
+.Bl -tag -width indent
+.It Fn acl_add_flag_np
+This function is described in
+.Xr acl_add_flag_np 3 ,
+and may be used to add flags to a flagset.
+.It Fn acl_add_perm
+This function is described in
+.Xr acl_add_perm 3 ,
+and may be used to add permissions to a permission set.
+.It Fn acl_calc_mask
+This function is described in
+.Xr acl_calc_mask 3 ,
+and may be used to calculate and set the permissions associated with
+the
+.Dv ACL_MASK
+entry.
+.It Fn acl_clear_flags_np
+This function is described in
+.Xr acl_clear_flags_np 3 ,
+and may be used to clear all flags from a flagset.
+.It Fn acl_clear_perms
+This function is described in
+.Xr acl_clear_perms 3 ,
+and may be used to clear all permissions from a permission set.
+.It Fn acl_copy_entry
+This function is described in
+.Xr acl_copy_entry 3 ,
+and may be used to copy the contents of an ACL entry.
+.It Xo
+.Fn acl_create_entry ,
+.Fn acl_create_entry_np
+.Xc
+These functions are described in
+.Xr acl_create_entry 3 ,
+and may be used to create an empty entry in an ACL.
+.It Xo
+.Fn acl_delete_def_file ,
+.Fn acl_delete_def_link_np ,
+.Fn acl_delete_fd_np ,
+.Fn acl_delete_file_np ,
+.Fn acl_delete_link_np
+.Xc
+These functions are described in
+.Xr acl_delete 3 ,
+and may be used to delete ACLs from file system objects.
+.It Xo
+.Fn acl_delete_entry ,
+.Fn acl_delete_entry_np ,
+.Xc
+This functions are described in
+.Xr acl_delete_entry 3 ,
+and may be used to delete an entry from an ACL.
+.It Fn acl_delete_flag_np
+This function is described in
+.Xr acl_delete_flag_np 3 ,
+and may be used to delete flags from a flagset.
+.It Fn acl_delete_perm
+This function is described in
+.Xr acl_delete_perm 3 ,
+and may be used to delete permissions from a permset.
+.It Fn acl_dup
+This function is described in
+.Xr acl_dup 3 ,
+and may be used to duplicate an ACL structure.
+.It Fn acl_free
+This function is described in
+.Xr acl_free 3 ,
+and may be used to free userland working ACL storage.
+.It Fn acl_from_text
+This function is described in
+.Xr acl_from_text 3 ,
+and may be used to convert a text-form ACL into working ACL state, if
+the ACL has POSIX.1e or NFSv4 semantics.
+.It Fn acl_get_brand_np
+This function is described in
+.Xr acl_get_brand_np 3
+and may be used to determine whether the ACL has POSIX.1e or NFSv4 semantics.
+.It Fn acl_get_entry
+This function is described in
+.Xr acl_get_entry 3 ,
+and may be used to retrieve a designated ACL entry from an ACL.
+.It Xo
+.Fn acl_get_fd ,
+.Fn acl_get_fd_np ,
+.Fn acl_get_file ,
+.Fn acl_get_link_np
+.Xc
+These functions are described in
+.Xr acl_get 3 ,
+and may be used to retrieve ACLs from file system objects.
+.It Fn acl_get_entry_type_np
+This function is described in
+.Xr acl_get_entry_type_np 3 ,
+and may be used to retrieve an ACL type from an ACL entry.
+.It Fn acl_get_flagset_np
+This function is described in
+.Xr acl_get_flagset_np 3 ,
+and may be used to retrieve a flagset from an ACL entry.
+.It Fn acl_get_permset
+This function is described in
+.Xr acl_get_permset 3 ,
+and may be used to retrieve a permset from an ACL entry.
+.It Fn acl_get_qualifier
+This function is described in
+.Xr acl_get_qualifier 3 ,
+and may be used to retrieve the qualifier from an ACL entry.
+.It Fn acl_get_tag_type
+This function is described in
+.Xr acl_get_tag_type 3 ,
+and may be used to retrieve the tag type from an ACL entry.
+.It Fn acl_init
+This function is described in
+.Xr acl_init 3 ,
+and may be used to allocate a fresh (empty) ACL structure.
+.It Fn acl_is_trivial_np
+This function is described in
+.Xr acl_is_trivial_np 3 ,
+and may be used to find out whether ACL is trivial.
+.It Xo
+.Fn acl_set_fd ,
+.Fn acl_set_fd_np ,
+.Fn acl_set_file ,
+.Fn acl_set_link_np
+.Xc
+These functions are described in
+.Xr acl_set 3 ,
+and may be used to assign an ACL to a file system object.
+.It Fn acl_set_entry_type_np
+This function is described in
+.Xr acl_set_entry_type_np 3 ,
+and may be used to set the ACL type of an ACL entry.
+.It Fn acl_set_flagset_np
+This function is described in
+.Xr acl_set_flagset_np 3 ,
+and may be used to set the flags of an ACL entry from a flagset.
+.It Fn acl_set_permset
+This function is described in
+.Xr acl_set_permset 3 ,
+and may be used to set the permissions of an ACL entry from a permset.
+.It Fn acl_set_qualifier
+This function is described in
+.Xr acl_set_qualifier 3 ,
+and may be used to set the qualifier of an ACL.
+.It Fn acl_set_tag_type
+This function is described in
+.Xr acl_set_tag_type 3 ,
+and may be used to set the tag type of an ACL.
+.It Fn acl_strip_np
+This function is described in
+.Xr acl_strip_np 3 ,
+and may be used to remove extended entries from an ACL.
+.It Xo
+.Fn acl_to_text ,
+.Fn acl_to_text_np
+.Xc
+These functions are described in
+.Xr acl_to_text 3 ,
+and may be used to generate a text-form of a POSIX.1e or NFSv4 semantics ACL.
+.It Xo
+.Fn acl_valid ,
+.Fn acl_valid_fd_np ,
+.Fn acl_valid_file_np ,
+.Fn acl_valid_link_np
+.Xc
+These functions are described in
+.Xr acl_valid 3 ,
+and may be used to validate an ACL as correct POSIX.1e-semantics, or
+as appropriate for a particular file system object regardless of semantics.
+.El
+.Pp
+Documentation of the internal kernel interfaces backing these calls may
+be found in
+.Xr acl 9 .
+The syscalls between the internal interfaces and the public library
+routines may change over time, and as such are not documented.
+They are not intended to be called directly without going through the
+library.
+.Sh SEE ALSO
+.Xr getfacl 1 ,
+.Xr setfacl 1 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_calc_mask 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_copy_entry 3 ,
+.Xr acl_create_entry 3 ,
+.Xr acl_delete_entry 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_dup 3 ,
+.Xr acl_free 3 ,
+.Xr acl_from_text 3 ,
+.Xr acl_get 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_get_entry_type_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_get_permset 3 ,
+.Xr acl_get_qualifier 3 ,
+.Xr acl_get_tag_type 3 ,
+.Xr acl_init 3 ,
+.Xr acl_is_trivial_np 3 ,
+.Xr acl_set 3 ,
+.Xr acl_set_entry_type_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr acl_set_permset 3 ,
+.Xr acl_set_qualifier 3 ,
+.Xr acl_set_tag_type 3 ,
+.Xr acl_strip_np 3 ,
+.Xr acl_to_text 3 ,
+.Xr acl_valid 3 ,
+.Xr posix1e 3 ,
+.Xr acl 9
+.Sh STANDARDS
+POSIX.1e assigns security labels to all objects, extending the security
+functionality described in POSIX.1.
+These additional labels provide fine-grained discretionary access control,
+fine-grained capabilities, and labels necessary for mandatory access
+control.
+POSIX.2c describes a set of userland utilities for manipulating these
+labels.
+.Pp
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion of the draft continues on the cross-platform POSIX.1e
+implementation mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ;
+.Fx 5.0
+was the first version to include a complete ACL implementation based
+on extended attributes for the UFS and UFS2 file systems.
+NFSv4 ACL support was introduced in
+.Fx 8.0 .
+.Pp
+The
+.Xr getfacl 1
+and
+.Xr setfacl 1
+utilities describe the user tools that permit direct manipulation of complete
+file ACLs.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_add_flag_np.3 b/lib/libc/posix1e/acl_add_flag_np.3
new file mode 100644
index 00000000000..b4301e88d81
--- /dev/null
+++ b/lib/libc/posix1e/acl_add_flag_np.3
@@ -0,0 +1,98 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_add_flag_np.3 287445 2015-09-04 00:14:20Z delphij $
+.\"
+.Dd September 4, 2015
+.Dt ACL_ADD_FLAG_NP 3
+.Os
+.Sh NAME
+.Nm acl_add_flag_np
+.Nd add flags to a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_add_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag"
+.Sh DESCRIPTION
+The
+.Fn acl_add_flag_np
+function
+is a non-portable call that adds the NFSv4 ACL flags contained in
+.Fa flags
+to the flagset
+.Fa flagset_d .
+.Pp
+Note: it is not considered an error to attempt to add flags
+that already exist in the flagset.
+.Pp
+Valid values are:
+.Bl -column -offset 3n "ACL_ENTRY_NO_PROPAGATE_INHERIT"
+.It ACL_ENTRY_FILE_INHERIT Ta "Will be inherited by files."
+.It ACL_ENTRY_DIRECTORY_INHERIT Ta "Will be inherited by directories."
+.It ACL_ENTRY_NO_PROPAGATE_INHERIT Ta "Will not propagate."
+.It ACL_ENTRY_INHERIT_ONLY Ta "Inherit-only."
+.It ACL_ENTRY_INHERITED Ta "Inherited from parent"
+.El
+.Sh RETURN VALUES
+.Rv -std acl_add_flag_np
+.Sh ERRORS
+The
+.Fn acl_add_flag_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flagset_d
+is not a valid descriptor for a flagset within an ACL entry.
+Argument
+.Fa flag
+does not contain a valid
+.Vt acl_flag_t
+value.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_add_flag_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_add_flag_np
+function was written by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_add_perm.3 b/lib/libc/posix1e/acl_add_perm.3
new file mode 100644
index 00000000000..3b0f607d3b0
--- /dev/null
+++ b/lib/libc/posix1e/acl_add_perm.3
@@ -0,0 +1,129 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_add_perm.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd June 25, 2009
+.Dt ACL_ADD_PERM 3
+.Os
+.Sh NAME
+.Nm acl_add_perm
+.Nd add permissions to a permission set
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_add_perm "acl_permset_t permset_d" "acl_perm_t perm"
+.Sh DESCRIPTION
+The
+.Fn acl_add_perm
+function
+is a POSIX.1e call that adds the permission contained in
+.Fa perm
+to the permission set
+.Fa permset_d .
+.Pp
+Note: it is not considered an error to attempt to add permissions
+that already exist in the permission set.
+.Pp
+For POSIX.1e ACLs, valid values are:
+.Bl -column -offset 3n "ACL_WRITE_NAMED_ATTRS"
+.It ACL_EXECUTE Execute permission
+.It ACL_WRITE Write permission
+.It ACL_READ Read permission
+.El
+.Pp
+For NFSv4 ACLs, valid values are:
+.Bl -column -offset 3n "ACL_WRITE_NAMED_ATTRS"
+.It ACL_READ_DATA Ta "Read permission"
+.It ACL_LIST_DIRECTORY Ta "Same as ACL_READ_DATA"
+.It ACL_WRITE_DATA Ta "Write permission, or permission to create files"
+.It ACL_ADD_FILE Ta "Same as ACL_READ_DATA"
+.It ACL_APPEND_DATA Ta "Permission to create directories. Ignored for files"
+.It ACL_ADD_SUBDIRECTORY Ta "Same as ACL_APPEND_DATA"
+.It ACL_READ_NAMED_ATTRS Ta "Ignored"
+.It ACL_WRITE_NAMED_ATTRS Ta "Ignored"
+.It ACL_EXECUTE Ta "Execute permission"
+.It ACL_DELETE_CHILD Ta "Permission to delete files and subdirectories"
+.It ACL_READ_ATTRIBUTES Ta "Permission to read basic attributes"
+.It ACL_WRITE_ATTRIBUTES Ta "Permission to change basic attributes"
+.It ACL_DELETE Ta "Permission to delete the object this ACL is placed on"
+.It ACL_READ_ACL Ta "Permission to read ACL"
+.It ACL_WRITE_ACL Ta "Permission to change the ACL and file mode"
+.It ACL_SYNCHRONIZE Ta "Ignored"
+.El
+.Pp
+Calling
+.Fn acl_add_perm
+with
+.Fa perm
+equal to ACL_WRITE or ACL_READ brands the ACL as POSIX.
+Calling it with ACL_READ_DATA, ACL_LIST_DIRECTORY, ACL_WRITE_DATA,
+ACL_ADD_FILE, ACL_APPEND_DATA, ACL_ADD_SUBDIRECTORY, ACL_READ_NAMED_ATTRS,
+ACL_WRITE_NAMED_ATTRS, ACL_DELETE_CHILD, ACL_READ_ATTRIBUTES,
+ACL_WRITE_ATTRIBUTES, ACL_DELETE, ACL_READ_ACL, ACL_WRITE_ACL
+or ACL_SYNCHRONIZE brands the ACL as NFSv4.
+.Sh RETURN VALUES
+.Rv -std acl_add_perm
+.Sh ERRORS
+The
+.Fn acl_add_perm
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa permset_d
+is not a valid descriptor for a permission set within an ACL entry.
+Argument
+.Fa perm
+does not contain a valid
+.Vt acl_perm_t
+value.
+ACL is already branded differently.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_get_permset 3 ,
+.Xr acl_set_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_add_perm
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_add_perm
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_branding.c b/lib/libc/posix1e/acl_branding.c
new file mode 100644
index 00000000000..64536ea33c5
--- /dev/null
+++ b/lib/libc/posix1e/acl_branding.c
@@ -0,0 +1,175 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_branding.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_branding.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+/*
+ * An ugly detail of the implementation - fortunately not visible
+ * to the API users - is the "branding": libc needs to keep track
+ * of what "brand" ACL is: NFSv4, POSIX.1e or unknown. It happens
+ * automatically - for example, during acl_get_file(3) ACL gets
+ * branded according to the "type" argument; during acl_set_permset
+ * ACL, if its brand is unknown it gets branded as NFSv4 if any of the
+ * NFSv4 permissions that are not valid for POSIX.1e ACL are set etc.
+ * Branding information is used for printing out the ACL (acl_to_text(3)),
+ * veryfying acl_set_whatever arguments (checking against setting
+ * bits that are valid only for NFSv4 in ACL branded as POSIX.1e) etc.
+ */
+
+static acl_t
+entry2acl(acl_entry_t entry)
+{
+ acl_t aclp;
+
+ aclp = (acl_t)(((long)entry >> _ACL_T_ALIGNMENT_BITS) << _ACL_T_ALIGNMENT_BITS);
+
+ return (aclp);
+}
+
+/*
+ * Return brand of an ACL.
+ */
+int
+_acl_brand(const acl_t acl)
+{
+
+ return (acl->ats_brand);
+}
+
+int
+_entry_brand(const acl_entry_t entry)
+{
+
+ return (_acl_brand(entry2acl(entry)));
+}
+
+/*
+ * Return 1, iff branding ACL as "brand" is ok.
+ */
+int
+_acl_brand_may_be(const acl_t acl, int brand)
+{
+
+ if (_acl_brand(acl) == ACL_BRAND_UNKNOWN)
+ return (1);
+
+ if (_acl_brand(acl) == brand)
+ return (1);
+
+ return (0);
+}
+
+int
+_entry_brand_may_be(const acl_entry_t entry, int brand)
+{
+
+ return (_acl_brand_may_be(entry2acl(entry), brand));
+}
+
+/*
+ * Brand ACL as "brand".
+ */
+void
+_acl_brand_as(acl_t acl, int brand)
+{
+
+ assert(_acl_brand_may_be(acl, brand));
+
+ acl->ats_brand = brand;
+}
+
+void
+_entry_brand_as(const acl_entry_t entry, int brand)
+{
+
+ _acl_brand_as(entry2acl(entry), brand);
+}
+
+int
+_acl_type_not_valid_for_acl(const acl_t acl, acl_type_t type)
+{
+
+ switch (_acl_brand(acl)) {
+ case ACL_BRAND_NFS4:
+ if (type == ACL_TYPE_NFS4)
+ return (0);
+ break;
+
+ case ACL_BRAND_POSIX:
+ if (type == ACL_TYPE_ACCESS || type == ACL_TYPE_DEFAULT)
+ return (0);
+ break;
+
+ case ACL_BRAND_UNKNOWN:
+ return (0);
+ }
+
+ return (-1);
+}
+
+void
+_acl_brand_from_type(acl_t acl, acl_type_t type)
+{
+
+ switch (type) {
+ case ACL_TYPE_NFS4:
+ _acl_brand_as(acl, ACL_BRAND_NFS4);
+ break;
+ case ACL_TYPE_ACCESS:
+ case ACL_TYPE_DEFAULT:
+ _acl_brand_as(acl, ACL_BRAND_POSIX);
+ break;
+ default:
+ /* XXX: What to do here? */
+ break;
+ }
+}
+
+int
+acl_get_brand_np(acl_t acl, int *brand_p)
+{
+
+ if (acl == NULL || brand_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ *brand_p = _acl_brand(acl);
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_calc_mask.3 b/lib/libc/posix1e/acl_calc_mask.3
new file mode 100644
index 00000000000..36be8723c46
--- /dev/null
+++ b/lib/libc/posix1e/acl_calc_mask.3
@@ -0,0 +1,98 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_calc_mask.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd March 10, 2001
+.Dt ACL_CALC_MASK 3
+.Os
+.Sh NAME
+.Nm acl_calc_mask
+.Nd calculate and set ACL mask permissions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_calc_mask "acl_t *acl_p"
+.Sh DESCRIPTION
+The
+.Fn acl_calc_mask
+function
+is a POSIX.1e call that calculates and set the permissions
+associated with the
+.Dv ACL_MASK
+ACL entry of the ACL referred to by
+.Fa acl_p .
+.Pp
+The value of new permissions are the union of the permissions
+granted by the
+.Dv ACL_GROUP , ACL_GROUP_OBJ , ACL_USER
+tag types which
+match processes in the file group class contained in the ACL
+referred to by
+.Fa acl_p .
+.Pp
+If the ACL referred to by
+.Fa acl_p
+already contains an
+.Dv ACL_MASK
+entry, its permissions shall be
+overwritten; if it does not contain an
+.Dv ACL_MASK
+entry, one shall
+be added.
+.Sh RETURN VALUES
+.Rv -std acl_calc_mask
+.Sh ERRORS
+The
+.Fn acl_calc_mask
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl_p
+does not point to a pointer to a valid ACL.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get_entry 3 ,
+.Xr acl_valid 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_calc_mask
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_calc_mask
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_calc_mask.c b/lib/libc/posix1e/acl_calc_mask.c
new file mode 100644
index 00000000000..e43ed873616
--- /dev/null
+++ b/lib/libc/posix1e/acl_calc_mask.c
@@ -0,0 +1,136 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_calc_mask.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_calc_mask.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "acl_support.h"
+
+/*
+ * acl_calc_mask() (23.4.2): calculate and set the permissions
+ * associated with the ACL_MASK ACL entry. If the ACL already
+ * contains an ACL_MASK entry, its permissions shall be
+ * overwritten; if not, one shall be added.
+ */
+int
+acl_calc_mask(acl_t *acl_p)
+{
+ struct acl *acl_int, *acl_int_new;
+ acl_t acl_new;
+ size_t i;
+ int mask_mode, mask_num;
+
+ /*
+ * (23.4.2.4) requires acl_p to point to a pointer to a valid ACL.
+ * Since one of the primary reasons to use this function would be
+ * to calculate the appropriate mask to obtain a valid ACL, we only
+ * perform sanity checks here and validate the ACL prior to
+ * returning.
+ */
+ if (acl_p == NULL || *acl_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (!_acl_brand_may_be(*acl_p, ACL_BRAND_POSIX)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _acl_brand_as(*acl_p, ACL_BRAND_POSIX);
+
+ acl_int = &(*acl_p)->ats_acl;
+ if ((acl_int->acl_cnt < 3) || (acl_int->acl_cnt > ACL_MAX_ENTRIES)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ acl_new = acl_dup(*acl_p);
+ if (acl_new == NULL)
+ return (-1);
+ acl_int_new = &acl_new->ats_acl;
+
+ mask_mode = 0;
+ mask_num = -1;
+
+ /* gather permissions and find a mask entry */
+ for (i = 0; i < acl_int_new->acl_cnt; i++) {
+ switch(acl_int_new->acl_entry[i].ae_tag) {
+ case ACL_USER:
+ case ACL_GROUP:
+ case ACL_GROUP_OBJ:
+ mask_mode |=
+ acl_int_new->acl_entry[i].ae_perm & ACL_PERM_BITS;
+ break;
+ case ACL_MASK:
+ mask_num = i;
+ break;
+ }
+ }
+
+ /* if a mask entry already exists, overwrite the perms */
+ if (mask_num != -1)
+ acl_int_new->acl_entry[mask_num].ae_perm = mask_mode;
+ else {
+ /* if no mask exists, check acl_cnt... */
+ if (acl_int_new->acl_cnt == ACL_MAX_ENTRIES) {
+ errno = ENOMEM;
+ acl_free(acl_new);
+ return (-1);
+ }
+ /* ...and add the mask entry */
+ acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_tag = ACL_MASK;
+ acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_id =
+ ACL_UNDEFINED_ID;
+ acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_perm =
+ mask_mode;
+ acl_int_new->acl_cnt++;
+ }
+
+ if (acl_valid(acl_new) == -1) {
+ errno = EINVAL;
+ acl_free(acl_new);
+ return (-1);
+ }
+
+ **acl_p = *acl_new;
+ acl_free(acl_new);
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_clear_flags_np.3 b/lib/libc/posix1e/acl_clear_flags_np.3
new file mode 100644
index 00000000000..e57f9945c95
--- /dev/null
+++ b/lib/libc/posix1e/acl_clear_flags_np.3
@@ -0,0 +1,79 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_clear_flags_np.3 273853 2014-10-30 10:49:50Z trasz $
+.\"
+.Dd October 30, 2014
+.Dt ACL_CLEAR_FLAGS_NP 3
+.Os
+.Sh NAME
+.Nm acl_clear_flags_np
+.Nd clear flags from a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_clear_flags_np "acl_flagset_t flagset_d"
+.Sh DESCRIPTION
+The
+.Fn acl_clear_flags_np
+function
+is a non-portable call that clears all NFSv4 ACL flags from flagset
+.Fa flagset_d .
+.Sh RETURN VALUES
+.Rv -std acl_clear_flags_np
+.Sh ERRORS
+The
+.Fn acl_clear_flags_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flagset_d
+is not a valid descriptor for a flagset.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_clear_flags_np
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_clear_flags_np
+function was written by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_clear_perms.3 b/lib/libc/posix1e/acl_clear_perms.3
new file mode 100644
index 00000000000..8407db7e4cc
--- /dev/null
+++ b/lib/libc/posix1e/acl_clear_perms.3
@@ -0,0 +1,79 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_clear_perms.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd March 10, 2001
+.Dt ACL_CLEAR_PERMS 3
+.Os
+.Sh NAME
+.Nm acl_clear_perms
+.Nd clear permissions from a permission set
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_clear_perms "acl_permset_t permset_d"
+.Sh DESCRIPTION
+The
+.Fn acl_clear_perms
+function
+is a POSIX.1e call that clears all permissions from permissions set
+.Fa permset_d .
+.Sh RETURN VALUES
+.Rv -std acl_clear_perms
+.Sh ERRORS
+The
+.Fn acl_clear_perms
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa permset_d
+is not a valid descriptor for a permission set.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_get_permset 3 ,
+.Xr acl_set_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_clear_perms
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_clear_perms
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_compat.c b/lib/libc/posix1e/acl_compat.c
new file mode 100644
index 00000000000..bcb88cb3d07
--- /dev/null
+++ b/lib/libc/posix1e/acl_compat.c
@@ -0,0 +1,69 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2008 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_compat.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_compat.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include <sys/acl.h>
+
+int __oldacl_get_perm_np(acl_permset_t, oldacl_perm_t);
+int __oldacl_add_perm(acl_permset_t, oldacl_perm_t);
+int __oldacl_delete_perm(acl_permset_t, oldacl_perm_t);
+
+/*
+ * Compatibility wrappers for applications compiled against libc from before
+ * NFSv4 ACLs were added.
+ */
+int
+__oldacl_get_perm_np(acl_permset_t permset_d, oldacl_perm_t perm)
+{
+
+ return (acl_get_perm_np(permset_d, perm));
+}
+
+int
+__oldacl_add_perm(acl_permset_t permset_d, oldacl_perm_t perm)
+{
+
+ return (acl_add_perm(permset_d, perm));
+}
+
+int
+__oldacl_delete_perm(acl_permset_t permset_d, oldacl_perm_t perm)
+{
+
+ return (acl_delete_perm(permset_d, perm));
+}
+
+__sym_compat(acl_get_perm_np, __oldacl_get_perm_np, FBSD_1.0);
+__sym_compat(acl_add_perm, __oldacl_add_perm, FBSD_1.0);
+__sym_compat(acl_delete_perm, __oldacl_delete_perm, FBSD_1.0);
diff --git a/lib/libc/posix1e/acl_copy.c b/lib/libc/posix1e/acl_copy.c
new file mode 100644
index 00000000000..79f812c3686
--- /dev/null
+++ b/lib/libc/posix1e/acl_copy.c
@@ -0,0 +1,91 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_copy.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_copy.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include "acl_support.h"
+
+/*
+ * acl_copy_entry() (23.4.4): copy the contents of ACL entry src_d to
+ * ACL entry dest_d
+ */
+int
+acl_copy_entry(acl_entry_t dest_d, acl_entry_t src_d)
+{
+
+ if (src_d == NULL || dest_d == NULL || src_d == dest_d) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /*
+ * Can we brand the new entry the same as the source entry?
+ */
+ if (!_entry_brand_may_be(dest_d, _entry_brand(src_d))) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ _entry_brand_as(dest_d, _entry_brand(src_d));
+
+ dest_d->ae_tag = src_d->ae_tag;
+ dest_d->ae_id = src_d->ae_id;
+ dest_d->ae_perm = src_d->ae_perm;
+ dest_d->ae_entry_type = src_d->ae_entry_type;
+ dest_d->ae_flags = src_d->ae_flags;
+
+ return (0);
+}
+
+ssize_t
+acl_copy_ext(void *buf_p, acl_t acl, ssize_t size)
+{
+
+ errno = ENOSYS;
+ return (-1);
+}
+
+acl_t
+acl_copy_int(const void *buf_p)
+{
+
+ errno = ENOSYS;
+ return (NULL);
+}
diff --git a/lib/libc/posix1e/acl_copy_entry.3 b/lib/libc/posix1e/acl_copy_entry.3
new file mode 100644
index 00000000000..80b098ed6a1
--- /dev/null
+++ b/lib/libc/posix1e/acl_copy_entry.3
@@ -0,0 +1,85 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_copy_entry.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd March 10, 2001
+.Dt ACL_COPY_ENTRY 3
+.Os
+.Sh NAME
+.Nm acl_copy_entry
+.Nd copy an ACL entry to another ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_copy_entry "acl_entry_t dest_d" "acl_entry_t src_d"
+.Sh DESCRIPTION
+The
+.Fn acl_copy_entry
+function
+is a POSIX.1e call that copies the contents of ACL entry
+.Fa src_d
+to ACL entry
+.Fa dest_d .
+.Sh RETURN VALUES
+.Rv -std acl_copy_entry
+.Sh ERRORS
+The
+.Fn acl_copy_entry
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa src_d
+or
+.Fa dest_d
+is not a valid descriptor for an ACL entry, or
+arguments
+.Fa src_d
+and
+.Fa dest_d
+reference the same ACL entry.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get_entry 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_copy_entry
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_copy_entry
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_create_entry.3 b/lib/libc/posix1e/acl_create_entry.3
new file mode 100644
index 00000000000..dbd284e34d9
--- /dev/null
+++ b/lib/libc/posix1e/acl_create_entry.3
@@ -0,0 +1,98 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_create_entry.3 318708 2017-05-23 07:11:15Z ngie $
+.\"
+.Dd June 25, 2009
+.Dt ACL_CREATE_ENTRY 3
+.Os
+.Sh NAME
+.Nm acl_create_entry ,
+.Nm acl_create_entry_np
+.Nd create a new ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_create_entry "acl_t *acl_p" "acl_entry_t *entry_p"
+.Ft int
+.Fn acl_create_entry_np "acl_t *acl_p" "acl_entry_t *entry_p" "int index"
+.Sh DESCRIPTION
+The
+.Fn acl_create_entry
+function
+is a POSIX.1e call that creates a new ACL entry in the ACL
+pointed to by
+.Fa acl_p .
+The
+.Fn acl_create_entry_np
+function is a non-portable version that creates the ACL entry
+at position
+.Fa index .
+Positions are numbered starting from zero, i.e. calling
+.Fn acl_create_entry_np
+with
+.Fa index
+argument equal to zero will prepend the entry to the ACL.
+.Sh RETURN VALUES
+.Rv -std acl_create_entry
+.Sh ERRORS
+The
+.Fn acl_create_entry
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl_p
+does not point to a pointer to a valid ACL.
+Argument
+.Fa index
+is out of bounds.
+.It Bq Er ENOMEM
+The ACL working storage requires more memory than is
+allowed by the hardware or system-imposed memory
+management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_delete_entry 3 ,
+.Xr acl_get_entry 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_create_entry
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_create_entry
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_delete.3 b/lib/libc/posix1e/acl_delete.3
new file mode 100644
index 00000000000..f44374b2247
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete.3
@@ -0,0 +1,140 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_delete.3 131635 2004-07-05 17:12:53Z ru $
+.\"
+.Dd December 29, 2002
+.Dt ACL_DELETE 3
+.Os
+.Sh NAME
+.Nm acl_delete_def_file ,
+.Nm acl_delete_def_link_np ,
+.Nm acl_delete_fd_np ,
+.Nm acl_delete_file_np ,
+.Nm acl_delete_link_np
+.Nd delete an ACL from a file
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_delete_def_file "const char *path_p"
+.Ft int
+.Fn acl_delete_def_link_np "const char *path_p"
+.Ft int
+.Fn acl_delete_fd_np "int filedes" "acl_type_t type"
+.Ft int
+.Fn acl_delete_file_np "const char *path_p" "acl_type_t type"
+.Ft int
+.Fn acl_delete_link_np "const char *path_p" "acl_type_t type"
+.Sh DESCRIPTION
+The
+.Fn acl_delete_def_file ,
+.Fn acl_delete_def_link_np ,
+.Fn acl_delete_fd_np ,
+.Fn acl_delete_file_np ,
+and
+.Fn acl_delete_link_np
+each allow the deletion of an ACL from a file.
+The
+.Fn acl_delete_def_file
+function
+is a POSIX.1e call that deletes the default ACL from a file (normally a
+directory) by name; the remainder of the calls are non-portable extensions
+that permit the deletion of arbitrary ACL types from a file/directory
+either by path name or file descriptor.
+The
+.Fn _file
+variations follow a symlink if it occurs in the last segment of the
+path name; the
+.Fn _link
+variations operate on the symlink itself.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+If any of the following conditions occur, these functions shall return -1
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EACCES
+Search permission is denied for a component of the path prefix, or the
+object exists and the process does not have appropriate access rights.
+.It Bq Er EBADF
+The
+.Va fd
+argument is not a valid file descriptor.
+.It Bq Er EINVAL
+The ACL type passed is invalid for this file object.
+.It Bq Er ENAMETOOLONG
+A component of a pathname exceeded 255 characters, or an
+entire path name exceeded 1023 characters.
+.It Bq Er ENOENT
+The named object does not exist, or the
+.Va path_p
+argument points to an empty string.
+.It Bq Er ENOMEM
+Insufficient memory available to fulfill request.
+.It Bq Er ENOTDIR
+A component of the path prefix is not a directory.
+.Pp
+Argument
+.Va path_p
+must be a directory, and is not.
+.It Bq Er EOPNOTSUPP
+The file system does not support ACL deletion.
+.It Bq Er EPERM
+The process does not have appropriate privilege to perform the operation
+to delete an ACL.
+.It Bq Er EROFS
+The file system is read-only.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get 3 ,
+.Xr acl_set 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_delete.c b/lib/libc/posix1e/acl_delete.c
new file mode 100644
index 00000000000..0fbb9c93856
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete.c
@@ -0,0 +1,84 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * acl_delete_def_file -- remove a default acl from a file
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_delete.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_delete.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <sys/errno.h>
+
+#include "acl_support.h"
+
+int
+acl_delete_def_file(const char *path_p)
+{
+
+ return (__acl_delete_file(path_p, ACL_TYPE_DEFAULT));
+}
+
+int
+acl_delete_def_link_np(const char *path_p)
+{
+
+ return (__acl_delete_link(path_p, ACL_TYPE_DEFAULT));
+}
+
+int
+acl_delete_file_np(const char *path_p, acl_type_t type)
+{
+
+ type = _acl_type_unold(type);
+ return (__acl_delete_file(path_p, type));
+}
+
+int
+acl_delete_link_np(const char *path_p, acl_type_t type)
+{
+
+ type = _acl_type_unold(type);
+ return (__acl_delete_link(path_p, type));
+}
+
+int
+acl_delete_fd_np(int filedes, acl_type_t type)
+{
+
+ type = _acl_type_unold(type);
+ return (__acl_delete_fd(filedes, type));
+}
diff --git a/lib/libc/posix1e/acl_delete_entry.3 b/lib/libc/posix1e/acl_delete_entry.3
new file mode 100644
index 00000000000..340b43c0741
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete_entry.3
@@ -0,0 +1,101 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_delete_entry.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd June 25, 2009
+.Dt ACL_DELETE_ENTRY 3
+.Os
+.Sh NAME
+.Nm acl_delete_entry ,
+.Nm acl_delete_entry_np
+.Nd delete an ACL entry from an ACL
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_delete_entry "acl_t acl" "acl_entry_t entry_d"
+.Ft int
+.Fn acl_delete_entry_np "acl_t acl" "int index"
+.Sh DESCRIPTION
+The
+.Fn acl_delete_entry
+function
+is a POSIX.1e call that removes the ACL entry
+.Fa entry_d
+from ACL
+.Fa acl .
+The
+.Fn acl_delete_entry_np
+function is a non-portable version that removes the ACL entry
+at position
+.Fa index
+from ACL
+.Fa acl .
+Positions are numbered starting from zero, i.e. calling
+.Fn acl_delete_entry_np
+with
+.Fa index
+argument equal to zero will remove the first ACL entry.
+.Sh RETURN VALUES
+.Rv -std acl_delete_entry
+.Sh ERRORS
+The
+.Fn acl_delete_entry
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl
+does not point to a valid ACL.
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry in
+.Fa acl .
+Argument
+.Fa index
+is out of bounds.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_copy_entry 3 ,
+.Xr acl_get_entry 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_delete_entry
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_delete_entry
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_delete_entry.c b/lib/libc/posix1e/acl_delete_entry.c
new file mode 100644
index 00000000000..73a560abdd6
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete_entry.c
@@ -0,0 +1,165 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_delete_entry.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_delete_entry.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "acl_support.h"
+
+static int
+_entry_matches(const acl_entry_t a, const acl_entry_t b)
+{
+ /*
+ * There is a semantical difference here between NFSv4 and POSIX
+ * draft ACLs. In POSIX, there may be only one entry for the particular
+ * user or group. In NFSv4 ACL, there may be any number of them. We're
+ * trying to be more specific here in that case.
+ */
+ switch (_entry_brand(a)) {
+ case ACL_BRAND_NFS4:
+ if (a->ae_tag != b->ae_tag || a->ae_entry_type != b->ae_entry_type)
+ return (0);
+
+ /* If ae_ids matter, compare them as well. */
+ if (a->ae_tag == ACL_USER || a->ae_tag == ACL_GROUP) {
+ if (a->ae_id != b->ae_id)
+ return (0);
+ }
+
+ return (1);
+
+ default:
+ if ((a->ae_tag == b->ae_tag) && (a->ae_id == b->ae_id))
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * acl_delete_entry() (23.4.9): remove the ACL entry indicated by entry_d
+ * from acl.
+ */
+int
+acl_delete_entry(acl_t acl, acl_entry_t entry_d)
+{
+ struct acl_entry entry_int;
+ size_t i, j;
+ int found = 0;
+
+ if (acl == NULL || entry_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_entry_brand(entry_d) != _acl_brand(acl)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((acl->ats_acl.acl_cnt < 1) ||
+ (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Use a local copy to prevent deletion of more than this entry */
+ entry_int = *entry_d;
+
+ for (i = 0; i < acl->ats_acl.acl_cnt;) {
+ if (_entry_matches(&(acl->ats_acl.acl_entry[i]), &entry_int)) {
+ /* ...shift the remaining entries... */
+ for (j = i; j < acl->ats_acl.acl_cnt - 1; ++j)
+ acl->ats_acl.acl_entry[j] =
+ acl->ats_acl.acl_entry[j+1];
+ /* ...drop the count and zero the unused entry... */
+ acl->ats_acl.acl_cnt--;
+ bzero(&acl->ats_acl.acl_entry[j],
+ sizeof(struct acl_entry));
+ acl->ats_cur_entry = 0;
+
+ /* Continue with the loop to remove all matching entries. */
+ found = 1;
+ } else
+ i++;
+ }
+
+ if (found)
+ return (0);
+
+ errno = EINVAL;
+ return (-1);
+}
+
+int
+acl_delete_entry_np(acl_t acl, int offset)
+{
+ struct acl *acl_int;
+ size_t i;
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ acl_int = &acl->ats_acl;
+
+ if (offset < 0 || (size_t)offset >= acl_int->acl_cnt) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((acl->ats_acl.acl_cnt < 1) ||
+ (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* ...shift the remaining entries... */
+ for (i = offset; i < acl->ats_acl.acl_cnt - 1; ++i)
+ acl->ats_acl.acl_entry[i] =
+ acl->ats_acl.acl_entry[i+1];
+ /* ...drop the count and zero the unused entry... */
+ acl->ats_acl.acl_cnt--;
+ bzero(&acl->ats_acl.acl_entry[i],
+ sizeof(struct acl_entry));
+ acl->ats_cur_entry = 0;
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_delete_flag_np.3 b/lib/libc/posix1e/acl_delete_flag_np.3
new file mode 100644
index 00000000000..d40cc81314c
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete_flag_np.3
@@ -0,0 +1,84 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_delete_flag_np.3 296196 2016-02-29 16:52:06Z trasz $
+.\"
+.Dd October 30, 2014
+.Dt ACL_DELETE_FLAG_NP 3
+.Os
+.Sh NAME
+.Nm acl_delete_flag_np
+.Nd delete flags from a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_delete_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag"
+.Sh DESCRIPTION
+The
+.Fn acl_delete_flag_np
+function
+is a non-portable call that removes specific NFSv4 ACL flags from flagset
+.Fa flags .
+.Sh RETURN VALUES
+.Rv -std acl_delete_flag_np
+.Sh ERRORS
+The
+.Fn acl_delete_flag_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flagset_d
+is not a valid descriptor for a flagset.
+Argument
+.Fa flag
+does not contain a valid
+.Vt acl_flag_t
+value.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_delete_flag_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_delete_flag_np
+function was written by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_delete_perm.3 b/lib/libc/posix1e/acl_delete_perm.3
new file mode 100644
index 00000000000..b67501c8698
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete_perm.3
@@ -0,0 +1,84 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_delete_perm.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd March 10, 2001
+.Dt ACL_DELETE_PERM 3
+.Os
+.Sh NAME
+.Nm acl_delete_perm
+.Nd delete permissions from a permission set
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_delete_perm "acl_permset_t permset_d" "acl_perm_t perm"
+.Sh DESCRIPTION
+The
+.Fn acl_delete_perm
+function
+is a POSIX.1e call that removes specific permissions from permissions set
+.Fa perm .
+.Sh RETURN VALUES
+.Rv -std acl_delete_perm
+.Sh ERRORS
+The
+.Fn acl_delete_perm
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa permset_d
+is not a valid descriptor for a permission set.
+Argument
+.Fa perm
+does not contain a valid
+.Vt acl_perm_t
+value.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_get_permset 3 ,
+.Xr acl_set_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_delete_perm
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_delete_perm
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_dup.3 b/lib/libc/posix1e/acl_dup.3
new file mode 100644
index 00000000000..f339b88e6f7
--- /dev/null
+++ b/lib/libc/posix1e/acl_dup.3
@@ -0,0 +1,110 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_dup.3 131504 2004-07-02 23:52:20Z ru $
+.\"
+.Dd January 28, 2000
+.Dt ACL_DUP 3
+.Os
+.Sh NAME
+.Nm acl_dup
+.Nd duplicate an ACL
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft acl_t
+.Fn acl_dup "acl_t acl"
+.Sh DESCRIPTION
+The
+.Fn acl_dup
+function returns a pointer to a copy of the ACL pointed to by the argument
+.Va acl .
+.Pp
+This function may cause memory to be allocated.
+The caller should free any
+releasable memory, when the new ACL is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void*)acl_t
+as an argument.
+.Pp
+Any existing ACL pointers that refer to the ACL referred to by
+.Va acl
+shall continue to refer to the ACL.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+Upon successful completion, this function shall return a pointer to the
+duplicate ACL.
+Otherwise, a value of
+.Va (acl_t)NULL
+shall be returned, and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_init
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Va acl
+does not point to a valid ACL.
+.It Bq Er ENOMEM
+The
+.Va acl_t
+to be returned requires more memory than is allowed by the hardware or
+system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_free 3 ,
+.Xr acl_get 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_entry.c b/lib/libc/posix1e/acl_entry.c
new file mode 100644
index 00000000000..a03bf31abdc
--- /dev/null
+++ b/lib/libc/posix1e/acl_entry.c
@@ -0,0 +1,151 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_entry.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_entry.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include <errno.h>
+#include <stdlib.h>
+
+/*
+ * acl_create_entry() (23.4.7): create a new ACL entry in the ACL pointed
+ * to by acl_p.
+ */
+int
+acl_create_entry(acl_t *acl_p, acl_entry_t *entry_p)
+{
+ struct acl *acl_int;
+
+ if (acl_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ acl_int = &(*acl_p)->ats_acl;
+
+ /*
+ * +1, because we are checking if there is space left for one more
+ * entry.
+ */
+ if (acl_int->acl_cnt + 1 >= ACL_MAX_ENTRIES) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *entry_p = &acl_int->acl_entry[acl_int->acl_cnt++];
+
+ (**entry_p).ae_tag = ACL_UNDEFINED_TAG;
+ (**entry_p).ae_id = ACL_UNDEFINED_ID;
+ (**entry_p).ae_perm = ACL_PERM_NONE;
+ (**entry_p).ae_entry_type = 0;
+ (**entry_p).ae_flags = 0;
+
+ (*acl_p)->ats_cur_entry = 0;
+
+ return (0);
+}
+
+int
+acl_create_entry_np(acl_t *acl_p, acl_entry_t *entry_p, int offset)
+{
+ int i;
+ struct acl *acl_int;
+
+ if (acl_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ acl_int = &(*acl_p)->ats_acl;
+
+ if (acl_int->acl_cnt + 1 >= ACL_MAX_ENTRIES) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (offset < 0 || (size_t)offset > acl_int->acl_cnt) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Make room for the new entry. */
+ for (i = acl_int->acl_cnt; i > offset; i--)
+ acl_int->acl_entry[i] = acl_int->acl_entry[i - 1];
+
+ acl_int->acl_cnt++;
+
+ *entry_p = &acl_int->acl_entry[offset];
+
+ (**entry_p).ae_tag = ACL_UNDEFINED_TAG;
+ (**entry_p).ae_id = ACL_UNDEFINED_ID;
+ (**entry_p).ae_perm = ACL_PERM_NONE;
+ (**entry_p).ae_entry_type = 0;
+ (**entry_p).ae_flags= 0;
+
+ (*acl_p)->ats_cur_entry = 0;
+
+ return (0);
+}
+
+/*
+ * acl_get_entry() (23.4.14): returns an ACL entry from an ACL
+ * indicated by entry_id.
+ */
+int
+acl_get_entry(acl_t acl, int entry_id, acl_entry_t *entry_p)
+{
+ struct acl *acl_int;
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ acl_int = &acl->ats_acl;
+
+ switch(entry_id) {
+ case ACL_FIRST_ENTRY:
+ acl->ats_cur_entry = 0;
+ /* FALLTHROUGH */
+ case ACL_NEXT_ENTRY:
+ if (acl->ats_cur_entry >= acl->ats_acl.acl_cnt)
+ return 0;
+ *entry_p = &acl_int->acl_entry[acl->ats_cur_entry++];
+ return (1);
+ }
+
+ errno = EINVAL;
+ return (-1);
+}
diff --git a/lib/libc/posix1e/acl_flag.c b/lib/libc/posix1e/acl_flag.c
new file mode 100644
index 00000000000..ec9ec9103f2
--- /dev/null
+++ b/lib/libc/posix1e/acl_flag.c
@@ -0,0 +1,161 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_flag.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_flag.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+static int
+_flag_is_invalid(acl_flag_t flag)
+{
+
+ if ((flag & ACL_FLAGS_BITS) == flag)
+ return (0);
+
+ errno = EINVAL;
+
+ return (1);
+}
+
+int
+acl_add_flag_np(acl_flagset_t flagset_d, acl_flag_t flag)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_flag_is_invalid(flag))
+ return (-1);
+
+ *flagset_d |= flag;
+
+ return (0);
+}
+
+int
+acl_clear_flags_np(acl_flagset_t flagset_d)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *flagset_d = 0;
+
+ return (0);
+}
+
+int
+acl_delete_flag_np(acl_flagset_t flagset_d, acl_flag_t flag)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_flag_is_invalid(flag))
+ return (-1);
+
+ *flagset_d &= ~flag;
+
+ return (0);
+}
+
+int
+acl_get_flag_np(acl_flagset_t flagset_d, acl_flag_t flag)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_flag_is_invalid(flag))
+ return (-1);
+
+ if (*flagset_d & flag)
+ return (1);
+
+ return (0);
+}
+
+int
+acl_get_flagset_np(acl_entry_t entry_d, acl_flagset_t *flagset_p)
+{
+
+ if (entry_d == NULL || flagset_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *flagset_p = &entry_d->ae_flags;
+
+ return (0);
+}
+
+int
+acl_set_flagset_np(acl_entry_t entry_d, acl_flagset_t flagset_d)
+{
+
+ if (entry_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+
+ if (_flag_is_invalid(*flagset_d))
+ return (-1);
+
+ entry_d->ae_flags = *flagset_d;
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_free.3 b/lib/libc/posix1e/acl_free.3
new file mode 100644
index 00000000000..e47bc6aa5dd
--- /dev/null
+++ b/lib/libc/posix1e/acl_free.3
@@ -0,0 +1,89 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_free.3 131504 2004-07-02 23:52:20Z ru $
+.\"
+.Dd January 28, 2000
+.Dt ACL_FREE 3
+.Os
+.Sh NAME
+.Nm acl_free
+.Nd free ACL working state
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_free "void *obj_p"
+.Sh DESCRIPTION
+The
+.Fn acl_free
+call allows the freeing of ACL working space, such as is allocated by
+.Xr acl_dup 3 ,
+or
+.Xr acl_from_text 3 .
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+.Rv -std acl_free
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_free
+function shall return -1 and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of the
+.Va obj_p
+argument is invalid.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_dup 3 ,
+.Xr acl_from_text 3 ,
+.Xr acl_get 3 ,
+.Xr acl_init 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_free.c b/lib/libc/posix1e/acl_free.c
new file mode 100644
index 00000000000..7e74935a18e
--- /dev/null
+++ b/lib/libc/posix1e/acl_free.c
@@ -0,0 +1,59 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999, 2000, 2001 Robert N. M. Watson
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * acl_free -- free ACL objects from user memory
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_free.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_free.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <sys/errno.h>
+#include <stdlib.h>
+
+/*
+ * acl_free() (23.4.12): free any releasable memory allocated to the
+ * ACL data object identified by obj_p.
+ */
+int
+acl_free(void *obj_p)
+{
+
+ if (obj_p) {
+ free(obj_p);
+ obj_p = NULL;
+ }
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_from_text.3 b/lib/libc/posix1e/acl_from_text.3
new file mode 100644
index 00000000000..9d9b9325ef2
--- /dev/null
+++ b/lib/libc/posix1e/acl_from_text.3
@@ -0,0 +1,130 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_from_text.3 131504 2004-07-02 23:52:20Z ru $
+.\"
+.Dd January 28, 2000
+.Dt ACL_FROM_TEXT 3
+.Os
+.Sh NAME
+.Nm acl_from_text
+.Nd create an ACL from text
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft acl_t
+.Fn acl_from_text "const char *buf_p"
+.Sh DESCRIPTION
+The
+.Fn acl_from_text
+function converts the text form of an ACL referred to by
+.Va buf_p
+into the internal working structure for ACLs, appropriate for applying to
+files or manipulating.
+.Pp
+This function may cause memory to be allocated.
+The caller should free any
+releasable memory, when the new ACL is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void *)acl_t
+as an argument.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+Upon successful completion, the function shall return a pointer to the
+internal representation of the ACL in working storage.
+Otherwise, a value
+of
+.Va (acl_t)NULL
+shall be returned, and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_from_text
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Va buf_p
+cannot be translated into an ACL.
+.It Bq Er ENOMEM
+The ACL working storage requires more memory than is allowed by the
+hardware or system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_free 3 ,
+.Xr acl_get 3 ,
+.Xr acl_to_text 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
+.Sh BUGS
+The
+.Fn acl_from_text
+and
+.Fn acl_to_text
+functions
+rely on the
+.Xr getpwent 3
+library calls to manage username and uid mapping, as well as the
+.Xr getgrent 3
+library calls to manage groupname and gid mapping.
+These calls are not
+thread safe, and so transitively, neither are
+.Fn acl_from_text
+and
+.Fn acl_to_text .
+These functions may also interfere with stateful
+calls associated with the
+.Fn getpwent
+and
+.Fn getgrent
+calls.
diff --git a/lib/libc/posix1e/acl_from_text.c b/lib/libc/posix1e/acl_from_text.c
new file mode 100644
index 00000000000..275c516d1ad
--- /dev/null
+++ b/lib/libc/posix1e/acl_from_text.c
@@ -0,0 +1,318 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999, 2000, 2001 Robert N. M. Watson
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * acl_from_text: Convert a text-form ACL from a string to an acl_t.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_from_text.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_from_text.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "acl_support.h"
+
+static acl_tag_t acl_string_to_tag(char *tag, char *qualifier);
+
+int _nfs4_acl_entry_from_text(acl_t aclp, char *entry);
+int _text_could_be_nfs4_acl(const char *entry);
+
+static acl_tag_t
+acl_string_to_tag(char *tag, char *qualifier)
+{
+
+ if (*qualifier == '\0') {
+ if ((!strcmp(tag, "user")) || (!strcmp(tag, "u"))) {
+ return (ACL_USER_OBJ);
+ } else
+ if ((!strcmp(tag, "group")) || (!strcmp(tag, "g"))) {
+ return (ACL_GROUP_OBJ);
+ } else
+ if ((!strcmp(tag, "mask")) || (!strcmp(tag, "m"))) {
+ return (ACL_MASK);
+ } else
+ if ((!strcmp(tag, "other")) || (!strcmp(tag, "o"))) {
+ return (ACL_OTHER);
+ } else
+ return(-1);
+ } else {
+ if ((!strcmp(tag, "user")) || (!strcmp(tag, "u"))) {
+ return(ACL_USER);
+ } else
+ if ((!strcmp(tag, "group")) || (!strcmp(tag, "g"))) {
+ return(ACL_GROUP);
+ } else
+ return(-1);
+ }
+}
+
+static int
+_posix1e_acl_entry_from_text(acl_t aclp, char *entry)
+{
+ acl_tag_t t;
+ acl_perm_t p;
+ char *tag, *qualifier, *permission;
+ uid_t id;
+ int error;
+
+ assert(_acl_brand(aclp) == ACL_BRAND_POSIX);
+
+ /* Split into three ':' delimited fields. */
+ tag = strsep(&entry, ":");
+ if (tag == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ tag = string_skip_whitespace(tag);
+ if ((*tag == '\0') && (!entry)) {
+ /*
+ * Is an entirely comment line, skip to next
+ * comma.
+ */
+ return (0);
+ }
+ string_trim_trailing_whitespace(tag);
+
+ qualifier = strsep(&entry, ":");
+ if (qualifier == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ qualifier = string_skip_whitespace(qualifier);
+ string_trim_trailing_whitespace(qualifier);
+
+ permission = strsep(&entry, ":");
+ if (permission == NULL || entry) {
+ errno = EINVAL;
+ return (-1);
+ }
+ permission = string_skip_whitespace(permission);
+ string_trim_trailing_whitespace(permission);
+
+ t = acl_string_to_tag(tag, qualifier);
+ if (t == (acl_tag_t)-1) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ error = _posix1e_acl_string_to_perm(permission, &p);
+ if (error == -1) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch(t) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_MASK:
+ case ACL_OTHER:
+ if (*qualifier != '\0') {
+ errno = EINVAL;
+ return (-1);
+ }
+ id = 0;
+ break;
+
+ case ACL_USER:
+ case ACL_GROUP:
+ error = _acl_name_to_id(t, qualifier, &id);
+ if (error == -1)
+ return (-1);
+ break;
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ error = _posix1e_acl_add_entry(aclp, t, id, p);
+ if (error == -1)
+ return (-1);
+
+ return (0);
+}
+
+static int
+_text_is_nfs4_entry(const char *entry)
+{
+ int count = 0;
+
+ assert(strlen(entry) > 0);
+
+ while (*entry != '\0') {
+ if (*entry == ':' || *entry == '@')
+ count++;
+ entry++;
+ }
+
+ if (count <= 2)
+ return (0);
+
+ return (1);
+}
+
+/*
+ * acl_from_text -- Convert a string into an ACL.
+ * Postpone most validity checking until the end and call acl_valid() to do
+ * that.
+ */
+acl_t
+acl_from_text(const char *buf_p)
+{
+ acl_t acl;
+ char *mybuf_p, *line, *cur, *notcomment, *comment, *entry;
+ int error;
+
+ /* Local copy we can mess up. */
+ mybuf_p = strdup(buf_p);
+ if (mybuf_p == NULL)
+ return(NULL);
+
+ acl = acl_init(3); /* XXX: WTF, 3? */
+ if (acl == NULL) {
+ free(mybuf_p);
+ return(NULL);
+ }
+
+ /* Outer loop: delimit at \n boundaries. */
+ cur = mybuf_p;
+ while ((line = strsep(&cur, "\n"))) {
+ /* Now split the line on the first # to strip out comments. */
+ comment = line;
+ notcomment = strsep(&comment, "#");
+
+ /* Inner loop: delimit at ',' boundaries. */
+ while ((entry = strsep(&notcomment, ","))) {
+
+ /* Skip empty lines. */
+ if (strlen(string_skip_whitespace(entry)) == 0)
+ continue;
+
+ if (_acl_brand(acl) == ACL_BRAND_UNKNOWN) {
+ if (_text_is_nfs4_entry(entry))
+ _acl_brand_as(acl, ACL_BRAND_NFS4);
+ else
+ _acl_brand_as(acl, ACL_BRAND_POSIX);
+ }
+
+ switch (_acl_brand(acl)) {
+ case ACL_BRAND_NFS4:
+ error = _nfs4_acl_entry_from_text(acl, entry);
+ break;
+
+ case ACL_BRAND_POSIX:
+ error = _posix1e_acl_entry_from_text(acl, entry);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ if (error)
+ goto error_label;
+ }
+ }
+
+#if 0
+ /* XXX Should we only return ACLs valid according to acl_valid? */
+ /* Verify validity of the ACL we read in. */
+ if (acl_valid(acl) == -1) {
+ errno = EINVAL;
+ goto error_label;
+ }
+#endif
+
+ free(mybuf_p);
+ return(acl);
+
+error_label:
+ acl_free(acl);
+ free(mybuf_p);
+ return(NULL);
+}
+
+/*
+ * Given a username/groupname from a text form of an ACL, return the uid/gid
+ * XXX NOT THREAD SAFE, RELIES ON GETPWNAM, GETGRNAM
+ * XXX USES *PW* AND *GR* WHICH ARE STATEFUL AND THEREFORE THIS ROUTINE
+ * MAY HAVE SIDE-EFFECTS
+ */
+int
+_acl_name_to_id(acl_tag_t tag, char *name, uid_t *id)
+{
+ struct group *g;
+ struct passwd *p;
+ unsigned long l;
+ char *endp;
+
+ switch(tag) {
+ case ACL_USER:
+ p = getpwnam(name);
+ if (p == NULL) {
+ l = strtoul(name, &endp, 0);
+ if (*endp != '\0' || l != (unsigned long)(uid_t)l) {
+ errno = EINVAL;
+ return (-1);
+ }
+ *id = (uid_t)l;
+ return (0);
+ }
+ *id = p->pw_uid;
+ return (0);
+
+ case ACL_GROUP:
+ g = getgrnam(name);
+ if (g == NULL) {
+ l = strtoul(name, &endp, 0);
+ if (*endp != '\0' || l != (unsigned long)(gid_t)l) {
+ errno = EINVAL;
+ return (-1);
+ }
+ *id = (gid_t)l;
+ return (0);
+ }
+ *id = g->gr_gid;
+ return (0);
+
+ default:
+ return (EINVAL);
+ }
+}
diff --git a/lib/libc/posix1e/acl_from_text_nfs4.c b/lib/libc/posix1e/acl_from_text_nfs4.c
new file mode 100644
index 00000000000..390dd2ee98e
--- /dev/null
+++ b/lib/libc/posix1e/acl_from_text_nfs4.c
@@ -0,0 +1,289 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_from_text_nfs4.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_from_text_nfs4.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <ctype.h>
+#include <err.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+#define MAX_ENTRY_LENGTH 512
+
+/*
+ * Parse the tag field of ACL entry passed as "str". If qualifier
+ * needs to follow, then the variable referenced by "need_qualifier"
+ * is set to 1, otherwise it's set to 0.
+ */
+static int
+parse_tag(const char *str, acl_entry_t entry, int *need_qualifier)
+{
+
+ assert(need_qualifier != NULL);
+ *need_qualifier = 0;
+
+ if (strcmp(str, "owner@") == 0)
+ return (acl_set_tag_type(entry, ACL_USER_OBJ));
+ if (strcmp(str, "group@") == 0)
+ return (acl_set_tag_type(entry, ACL_GROUP_OBJ));
+ if (strcmp(str, "everyone@") == 0)
+ return (acl_set_tag_type(entry, ACL_EVERYONE));
+
+ *need_qualifier = 1;
+
+ if (strcmp(str, "user") == 0 || strcmp(str, "u") == 0)
+ return (acl_set_tag_type(entry, ACL_USER));
+ if (strcmp(str, "group") == 0 || strcmp(str, "g") == 0)
+ return (acl_set_tag_type(entry, ACL_GROUP));
+
+ warnx("malformed ACL: invalid \"tag\" field");
+
+ return (-1);
+}
+
+/*
+ * Parse the qualifier field of ACL entry passed as "str".
+ * If user or group name cannot be resolved, then the variable
+ * referenced by "need_qualifier" is set to 1; it will be checked
+ * later to figure out whether the appended_id is required.
+ */
+static int
+parse_qualifier(char *str, acl_entry_t entry, int *need_qualifier)
+{
+ int qualifier_length, error;
+ uid_t id;
+ acl_tag_t tag;
+
+ assert(need_qualifier != NULL);
+ *need_qualifier = 0;
+
+ qualifier_length = strlen(str);
+
+ if (qualifier_length == 0) {
+ warnx("malformed ACL: empty \"qualifier\" field");
+ return (-1);
+ }
+
+ error = acl_get_tag_type(entry, &tag);
+ if (error)
+ return (error);
+
+ error = _acl_name_to_id(tag, str, &id);
+ if (error) {
+ *need_qualifier = 1;
+ return (0);
+ }
+
+ return (acl_set_qualifier(entry, &id));
+}
+
+static int
+parse_access_mask(char *str, acl_entry_t entry)
+{
+ int error;
+ acl_perm_t perm;
+
+ error = _nfs4_parse_access_mask(str, &perm);
+ if (error)
+ return (error);
+
+ error = acl_set_permset(entry, &perm);
+
+ return (error);
+}
+
+static int
+parse_flags(char *str, acl_entry_t entry)
+{
+ int error;
+ acl_flag_t flags;
+
+ error = _nfs4_parse_flags(str, &flags);
+ if (error)
+ return (error);
+
+ error = acl_set_flagset_np(entry, &flags);
+
+ return (error);
+}
+
+static int
+parse_entry_type(const char *str, acl_entry_t entry)
+{
+
+ if (strcmp(str, "allow") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALLOW));
+ if (strcmp(str, "deny") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_DENY));
+ if (strcmp(str, "audit") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_AUDIT));
+ if (strcmp(str, "alarm") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALARM));
+
+ warnx("malformed ACL: invalid \"type\" field");
+
+ return (-1);
+}
+
+static int
+parse_appended_id(char *str, acl_entry_t entry)
+{
+ int qualifier_length;
+ char *end;
+ id_t id;
+
+ qualifier_length = strlen(str);
+ if (qualifier_length == 0) {
+ warnx("malformed ACL: \"appended id\" field present, "
+ "but empty");
+ return (-1);
+ }
+
+ id = strtod(str, &end);
+ if (end - str != qualifier_length) {
+ warnx("malformed ACL: appended id is not a number");
+ return (-1);
+ }
+
+ return (acl_set_qualifier(entry, &id));
+}
+
+static int
+number_of_colons(const char *str)
+{
+ int count = 0;
+
+ while (*str != '\0') {
+ if (*str == ':')
+ count++;
+
+ str++;
+ }
+
+ return (count);
+}
+
+int
+_nfs4_acl_entry_from_text(acl_t aclp, char *str)
+{
+ int error, need_qualifier;
+ acl_entry_t entry;
+ char *field, *qualifier_field = NULL;
+
+ error = acl_create_entry(&aclp, &entry);
+ if (error)
+ return (error);
+
+ assert(_entry_brand(entry) == ACL_BRAND_NFS4);
+
+ if (str == NULL)
+ goto truncated_entry;
+ field = strsep(&str, ":");
+
+ field = string_skip_whitespace(field);
+ if ((*field == '\0') && (!str)) {
+ /*
+ * Is an entirely comment line, skip to next
+ * comma.
+ */
+ return (0);
+ }
+
+ error = parse_tag(field, entry, &need_qualifier);
+ if (error)
+ goto malformed_field;
+
+ if (need_qualifier) {
+ if (str == NULL)
+ goto truncated_entry;
+ qualifier_field = field = strsep(&str, ":");
+ error = parse_qualifier(field, entry, &need_qualifier);
+ if (error)
+ goto malformed_field;
+ }
+
+ if (str == NULL)
+ goto truncated_entry;
+ field = strsep(&str, ":");
+ error = parse_access_mask(field, entry);
+ if (error)
+ goto malformed_field;
+
+ if (str == NULL)
+ goto truncated_entry;
+ /* Do we have "flags" field? */
+ if (number_of_colons(str) > 0) {
+ field = strsep(&str, ":");
+ error = parse_flags(field, entry);
+ if (error)
+ goto malformed_field;
+ }
+
+ if (str == NULL)
+ goto truncated_entry;
+ field = strsep(&str, ":");
+ error = parse_entry_type(field, entry);
+ if (error)
+ goto malformed_field;
+
+ if (need_qualifier) {
+ if (str == NULL) {
+ warnx("malformed ACL: unknown user or group name "
+ "\"%s\"", qualifier_field);
+ goto truncated_entry;
+ }
+
+ error = parse_appended_id(str, entry);
+ if (error)
+ goto malformed_field;
+ }
+
+ return (0);
+
+truncated_entry:
+malformed_field:
+ acl_delete_entry(aclp, entry);
+ errno = EINVAL;
+ return (-1);
+}
diff --git a/lib/libc/posix1e/acl_get.3 b/lib/libc/posix1e/acl_get.3
new file mode 100644
index 00000000000..f6db44dabb0
--- /dev/null
+++ b/lib/libc/posix1e/acl_get.3
@@ -0,0 +1,168 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_get.3 213573 2010-10-08 12:40:16Z uqs $
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET 3
+.Os
+.Sh NAME
+.Nm acl_get_fd ,
+.Nm acl_get_fd_np ,
+.Nm acl_get_file ,
+.Nm acl_get_link_np
+.Nd get an ACL for a file
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft acl_t
+.Fn acl_get_fd "int fd"
+.Ft acl_t
+.Fn acl_get_fd_np "int fd" "acl_type_t type"
+.Ft acl_t
+.Fn acl_get_file "const char *path_p" "acl_type_t type"
+.Ft acl_t
+.Fn acl_get_link_np "const char *path_p" "acl_type_t type"
+.Sh DESCRIPTION
+The
+.Fn acl_get_fd ,
+.Fn acl_get_file ,
+.Fn acl_get_link_np ,
+and
+.Fn acl_get_fd_np
+each allow the retrieval of an ACL from a file.
+The
+.Fn acl_get_fd
+is a POSIX.1e call that allows the retrieval of an ACL of type
+ACL_TYPE_ACCESS
+from a file descriptor.
+The
+.Fn acl_get_fd_np
+function
+is a non-portable form of
+.Fn acl_get_fd
+that allows the retrieval of any type of ACL from a file descriptor.
+The
+.Fn acl_get_file
+function is a POSIX.1e call that allows the retrieval of a
+specified type of ACL from a file by name;
+.Fn acl_get_link_np
+is a non-portable variation on
+.Fn acl_get_file
+which does not follow a symlink if the target of the call is a
+symlink.
+.Pp
+These functions may cause memory to be allocated.
+The caller should free
+any releasable memory, when the new ACL is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void *)acl_t
+as an argument.
+.Pp
+The ACL in the working storage is an independent copy of the ACL associated
+with the object referred to by
+.Va fd .
+The ACL in the working storage shall not participate in any access control
+decisions.
+.Pp
+Valid values for the
+.Va type
+argument are:
+.Bl -column -offset 3n "ACL_TYPE_DEFAULT"
+.It ACL_TYPE_ACCESS POSIX.1e access ACL
+.It ACL_TYPE_DEFAULT POSIX.1e default ACL
+.It ACL_TYPE_NFS4 NFSv4 ACL
+.El
+.Pp
+The ACL returned will be branded accordingly.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+Upon successful completion, the function shall return a pointer to the ACL
+that was retrieved.
+Otherwise, a value of
+.Va (acl_t)NULL
+shall be returned, and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_get_fd
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EACCES
+Search permission is denied for a component of the path prefix, or the
+object exists and the process does not have appropriate access rights.
+.It Bq Er EBADF
+The
+.Va fd
+argument is not a valid file descriptor.
+.It Bq Er EINVAL
+The ACL type passed is invalid for this file object.
+.It Bq Er ENAMETOOLONG
+A component of a pathname exceeded 255 characters, or an
+entire path name exceeded 1023 characters.
+.It Bq Er ENOENT
+The named object does not exist, or the
+.Va path_p
+argument points to an empty string.
+.It Bq Er ENOMEM
+Insufficient memory available to fulfill request.
+.It Bq Er EOPNOTSUPP
+The file system does not support ACL retrieval.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_free 3 ,
+.Xr acl_get 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_set 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_get.c b/lib/libc/posix1e/acl_get.c
new file mode 100644
index 00000000000..c44799eff56
--- /dev/null
+++ b/lib/libc/posix1e/acl_get.c
@@ -0,0 +1,221 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * acl_get_fd - syscall wrapper for retrieving access ACL by fd
+ * acl_get_fd_np - syscall wrapper for retrieving ACL by fd (non-POSIX)
+ * acl_get_file - syscall wrapper for retrieving ACL by filename
+ * acl_get_link_np - syscall wrapper for retrieving ACL by filename (NOFOLLOW)
+ * (non-POSIX)
+ * acl_get_perm_np() checks if a permission is in the specified
+ * permset (non-POSIX)
+ * acl_get_permset() returns the permission set in the ACL entry
+ * acl_get_qualifier() retrieves the qualifier of the tag from the ACL entry
+ * acl_get_tag_type() returns the tag type for the ACL entry entry_d
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_get.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_get.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "acl_support.h"
+
+acl_t
+acl_get_file(const char *path_p, acl_type_t type)
+{
+ acl_t aclp;
+ int error;
+
+ aclp = acl_init(ACL_MAX_ENTRIES);
+ if (aclp == NULL)
+ return (NULL);
+
+ type = _acl_type_unold(type);
+ error = __acl_get_file(path_p, type, &aclp->ats_acl);
+ if (error) {
+ acl_free(aclp);
+ return (NULL);
+ }
+
+ aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
+ _acl_brand_from_type(aclp, type);
+
+ return (aclp);
+}
+
+acl_t
+acl_get_link_np(const char *path_p, acl_type_t type)
+{
+ acl_t aclp;
+ int error;
+
+ aclp = acl_init(ACL_MAX_ENTRIES);
+ if (aclp == NULL)
+ return (NULL);
+
+ type = _acl_type_unold(type);
+ error = __acl_get_link(path_p, type, &aclp->ats_acl);
+ if (error) {
+ acl_free(aclp);
+ return (NULL);
+ }
+
+ aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
+ _acl_brand_from_type(aclp, type);
+
+ return (aclp);
+}
+
+acl_t
+acl_get_fd(int fd)
+{
+ if (fpathconf(fd, _PC_ACL_NFS4) == 1)
+ return (acl_get_fd_np(fd, ACL_TYPE_NFS4));
+
+ return (acl_get_fd_np(fd, ACL_TYPE_ACCESS));
+}
+
+acl_t
+acl_get_fd_np(int fd, acl_type_t type)
+{
+ acl_t aclp;
+ int error;
+
+ aclp = acl_init(ACL_MAX_ENTRIES);
+ if (aclp == NULL)
+ return (NULL);
+
+ type = _acl_type_unold(type);
+ error = __acl_get_fd(fd, type, &aclp->ats_acl);
+ if (error) {
+ acl_free(aclp);
+ return (NULL);
+ }
+
+ aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
+ _acl_brand_from_type(aclp, type);
+
+ return (aclp);
+}
+
+/*
+ * acl_get_permset() (23.4.17): return via permset_p a descriptor to
+ * the permission set in the ACL entry entry_d.
+ */
+int
+acl_get_permset(acl_entry_t entry_d, acl_permset_t *permset_p)
+{
+
+ if (entry_d == NULL || permset_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *permset_p = &entry_d->ae_perm;
+
+ return (0);
+}
+
+/*
+ * acl_get_qualifier() (23.4.18): retrieve the qualifier of the tag
+ * for the ACL entry entry_d.
+ */
+void *
+acl_get_qualifier(acl_entry_t entry_d)
+{
+ uid_t *retval;
+
+ if (entry_d == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ switch(entry_d->ae_tag) {
+ case ACL_USER:
+ case ACL_GROUP:
+ retval = malloc(sizeof(uid_t));
+ if (retval == NULL)
+ return (NULL);
+ *retval = entry_d->ae_id;
+ return (retval);
+ }
+
+ errno = EINVAL;
+ return (NULL);
+}
+
+/*
+ * acl_get_tag_type() (23.4.19): return the tag type for the ACL
+ * entry entry_p.
+ */
+int
+acl_get_tag_type(acl_entry_t entry_d, acl_tag_t *tag_type_p)
+{
+
+ if (entry_d == NULL || tag_type_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *tag_type_p = entry_d->ae_tag;
+
+ return (0);
+}
+
+int
+acl_get_entry_type_np(acl_entry_t entry_d, acl_entry_type_t *entry_type_p)
+{
+
+ if (entry_d == NULL || entry_type_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *entry_type_p = entry_d->ae_entry_type;
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_get_brand_np.3 b/lib/libc/posix1e/acl_get_brand_np.3
new file mode 100644
index 00000000000..ae44d00c05f
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_brand_np.3
@@ -0,0 +1,86 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_get_brand_np.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET_BRAND_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_brand_np
+.Nd retrieve the ACL brand from an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_brand_np "acl_t acl" "int *brand_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_brand_np
+function
+is a non-portable call that returns the ACL brand for the ACL
+.Fa acl .
+Upon successful completion, the location referred to by the argument
+.Fa brand_p
+will be set to the ACL brand of the ACL
+.Fa acl .
+.Pp
+Branding is an internal mechanism intended to prevent mixing POSIX.1e
+and NFSv4 entries by mistake.
+It's also used by the libc to determine how to print out the ACL.
+The first call to function that is specific for one particular brand - POSIX.1e
+or NFSv4 - "brands" the ACL.
+After that, calling function specific to another brand will result in error.
+.Sh RETURN VALUES
+.Rv -std acl_get_brand_np
+.Sh ERRORS
+The
+.Fn acl_get_brand_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl
+does not point to a valid ACL.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_brand_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_brand_np
+function was written by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_get_entry.3 b/lib/libc/posix1e/acl_get_entry.3
new file mode 100644
index 00000000000..c89dad73917
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_entry.3
@@ -0,0 +1,145 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_get_entry.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd April 13, 2001
+.Dt ACL_GET_ENTRY 3
+.Os
+.Sh NAME
+.Nm acl_get_entry
+.Nd retrieve an ACL entry from an ACL
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_entry "acl_t acl" "int entry_id" "acl_entry_t *entry_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_entry
+function
+is a POSIX.1e call that retrieves a descriptor for an ACL entry
+specified by the argument
+.Fa entry_d
+within the ACL indicated by the argument
+.Fa acl .
+.Pp
+If the value of
+.Fa entry_id
+is
+.Dv ACL_FIRST_ENTRY ,
+then the function will return in
+.Fa entry_p
+a descriptor for the first ACL entry within
+.Fa acl .
+If a call is made to
+.Fn acl_get_entry
+with
+.Fa entry_id
+set to
+.Dv ACL_NEXT_ENTRY
+when there has not been either an initial successful call to
+.Fn acl_get_entry ,
+or a previous successful call to
+.Fn acl_create_entry ,
+.Fn acl_delete_entry ,
+.Fn acl_dup ,
+.Fn acl_from_text ,
+.Fn acl_get_fd ,
+.Fn acl_get_file ,
+.Fn acl_set_fd ,
+.Fn acl_set_file ,
+or
+.Fn acl_valid ,
+then the result is unspecified.
+.Sh RETURN VALUES
+If the
+.Fn acl_get_entry
+function successfully obtains an ACL entry, a value of 1 is returned.
+If the ACL has no ACL entries, the
+.Fn acl_get_entry
+returns a value of 0.
+If the value of
+.Fa entry_id
+is
+.Dv ACL_NEXT_ENTRY
+and the last ACL entry in the ACL has already been returned by a
+previous call to
+.Fn acl_get_entry ,
+a value of 0 will be returned until a successful call with
+.Fa entry_id
+of
+.Dv ACL_FIRST_ENTRY
+is made.
+Otherwise, a value of -1 will be returned and
+the global variable
+.Va errno
+will be set to indicate the error.
+.Sh ERRORS
+The
+.Fn acl_get_entry
+fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl
+does not point to a valid ACL.
+Argument
+.Fa entry_id
+is neither
+.Dv ACL_FIRST_ENTRY
+nor
+.Dv ACL_NEXT_ENTRY .
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_calc_mask 3 ,
+.Xr acl_create_entry 3 ,
+.Xr acl_delete_entry 3 ,
+.Xr acl_dup 3 ,
+.Xr acl_from_text 3 ,
+.Xr acl_get_fd 3 ,
+.Xr acl_get_file 3 ,
+.Xr acl_init 3 ,
+.Xr acl_set_fd 3 ,
+.Xr acl_set_file 3 ,
+.Xr acl_valid 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_entry
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_entry
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_get_entry_type_np.3 b/lib/libc/posix1e/acl_get_entry_type_np.3
new file mode 100644
index 00000000000..86a6fd1386b
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_entry_type_np.3
@@ -0,0 +1,80 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_get_entry_type_np.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET_ENTRY_TYPE_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_entry_type_np
+.Nd retrieve the ACL type from an NFSv4 ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_entry_type_np "acl_entry_t entry_d" "acl_entry_type_t *entry_type_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_entry_type_np
+function
+is a non-portable call that returns the ACL type for the NFSv4 ACL entry
+.Fa entry_d .
+Upon successful completion, the location referred to by the argument
+.Fa entry_type_p
+will be set to the ACL type of the ACL entry
+.Fa entry_d .
+.Sh RETURN VALUES
+.Rv -std acl_get_entry_type_np
+.Sh ERRORS
+The
+.Fn acl_get_entry_type_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an NFSv4 ACL entry;
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_set_entry_type_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_entry_type_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_entry_type_np
+function was written by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_get_flag_np.3 b/lib/libc/posix1e/acl_get_flag_np.3
new file mode 100644
index 00000000000..0c3e27fa380
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_flag_np.3
@@ -0,0 +1,94 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_get_flag_np.3 273853 2014-10-30 10:49:50Z trasz $
+.\"
+.Dd October 30, 2014
+.Dt ACL_GET_FLAG_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_flag_np
+.Nd check if a flag is set in a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag"
+.Sh DESCRIPTION
+The
+.Fn acl_get_flag_np
+function
+is a non-portable function that checks if a NFSv4 ACL flag is set in
+a flagset.
+.Sh RETURN VALUES
+If the flag in
+.Fa flag
+is set in the flagset
+.Fa flagset_d ,
+a value of
+1
+is returned, otherwise a value of
+0
+is returned.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_get_flag_np
+function will return a value of
+\-1
+and set global variable
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flag
+does not contain a valid ACL flag or argument
+.Fa flagset_d
+is not a valid ACL flagset.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_flag_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_flag_np
+function was written by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_get_flagset_np.3 b/lib/libc/posix1e/acl_get_flagset_np.3
new file mode 100644
index 00000000000..9efea5bd725
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_flagset_np.3
@@ -0,0 +1,83 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_get_flagset_np.3 273853 2014-10-30 10:49:50Z trasz $
+.\"
+.Dd October 30, 2014
+.Dt ACL_GET_FLAGSET_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_flagset_np
+.Nd retrieve flagset from an NFSv4 ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_flagset_np "acl_entry_t entry_d" "acl_flagset_t *flagset_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_flagset_np
+function
+is a non-portable call that returns via
+.Fa flagset_np_p
+a descriptor to the flagset in the NFSv4 ACL entry
+.Fa entry_d .
+Subsequent operations using the returned flagset operate
+on the flagset within the ACL entry.
+.Sh RETURN VALUES
+.Rv -std acl_get_flagset_np
+.Sh ERRORS
+The
+.Fn acl_get_flagset_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_flagset_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_flagset_np
+function was written by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_get_perm_np.3 b/lib/libc/posix1e/acl_get_perm_np.3
new file mode 100644
index 00000000000..72ccd7f9e28
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_perm_np.3
@@ -0,0 +1,94 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_get_perm_np.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd April 10, 2001
+.Dt ACL_GET_PERM_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_perm_np
+.Nd "check if a permission is set in a permission set"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_perm_np "acl_permset_t permset_d" "acl_perm_t perm"
+.Sh DESCRIPTION
+The
+.Fn acl_get_perm_np
+function
+is a non-portable function that checks if a permission is set in
+a permission set.
+.Sh RETURN VALUES
+If the permission in
+.Fa perm
+is set in the permission set
+.Fa permset_d ,
+a value of
+1
+is returned, otherwise a value of
+0
+is returned.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_get_perm_np
+function will return a value of
+\-1
+and set global variable
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa perm
+does not contain a valid ACL permission or argument
+.Fa permset_d
+is not a valid ACL permset.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_get_permset 3 ,
+.Xr acl_set_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_perm_np
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_perm_np
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_get_permset.3 b/lib/libc/posix1e/acl_get_permset.3
new file mode 100644
index 00000000000..561e7540dd5
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_permset.3
@@ -0,0 +1,83 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_get_permset.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd March 10, 2001
+.Dt ACL_GET_PERMSET 3
+.Os
+.Sh NAME
+.Nm acl_get_permset
+.Nd retrieve permission set from an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_permset "acl_entry_t entry_d" "acl_permset_t *permset_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_permset
+function
+is a POSIX.1e call that returns via
+.Fa permset_p
+a descriptor to the permission set in the ACL entry
+.Fa entry_d .
+Subsequent operations using the returned permission set operate
+on the permission set within the ACL entry.
+.Sh RETURN VALUES
+.Rv -std acl_get_permset
+.Sh ERRORS
+The
+.Fn acl_get_permset
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_set_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_permset
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_permset
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_get_qualifier.3 b/lib/libc/posix1e/acl_get_qualifier.3
new file mode 100644
index 00000000000..9f377c0651c
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_qualifier.3
@@ -0,0 +1,140 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_get_qualifier.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd March 13, 2001
+.Dt ACL_GET_QUALIFIER 3
+.Os
+.Sh NAME
+.Nm acl_get_qualifier
+.Nd retrieve the qualifier from an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft void *
+.Fn acl_get_qualifier "acl_entry_t entry_d"
+.Sh DESCRIPTION
+The
+.Fn acl_get_qualifier
+function
+is a POSIX.1e call that retrieves the qualifier of the tag for
+the ACL entry indicated by the argument
+.Fa entry_d
+into working storage and returns a pointer to that storage.
+.Pp
+If the value of the tag type in the ACL entry referred to by
+.Fa entry_d
+is
+.Dv ACL_USER ,
+then the value returned by
+.Fn acl_get_qualifier
+will be a pointer to type
+.Vt uid_t .
+.Pp
+If the value of the tag type in
+the ACL entry referred to by
+.Fa entry_d
+is
+.Dv ACL_GROUP ,
+then the value returned by
+.Fn acl_get_qualifier
+will be a pointer to type
+.Vt gid_t .
+.Pp
+If the value of the tag type in the ACL entry referred to by
+.Fa entry_d
+is
+.Dv ACL_UNDEFINED_TAG , ACL_USER_OBJ , ACL_GROUP_OBJ ,
+.Dv ACL_OTHER , ACL_MASK ,
+or an implementation-defined value for which a qualifier
+is not supported, then
+.Fn acl_get_qualifier
+will return a value of
+.Vt ( void * ) Ns Dv NULL
+and the function will fail.
+.Pp
+This function may cause memory to be allocated.
+The caller should
+free any releasable memory, when the new qualifier is no longer
+required, by calling
+.Fn acl_free
+with
+.Vt void *
+as the argument.
+.Sh RETURN VALUES
+The
+.Fn acl_get_qualifier
+function returns a pointer to the allocated storage if successful;
+otherwise a
+.Dv NULL
+pointer is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The
+.Fn acl_get_qualifier
+fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+does not point to a valid descriptor for an ACL entry.
+The
+value of the tag type in the ACL entry referenced by argument
+.Fa entry_d
+is not
+.Dv ACL_USER
+or
+.Dv ACL_GROUP .
+.It Bq Er ENOMEM
+The value to be returned requires more memory than is allowed
+by the hardware or system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_create_entry 3 ,
+.Xr acl_free 3 ,
+.Xr acl_get_entry 3 ,
+.Xr acl_get_tag_type 3 ,
+.Xr acl_set_qualifier 3 ,
+.Xr acl_set_tag_type 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_qualifier
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_qualifier
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_get_tag_type.3 b/lib/libc/posix1e/acl_get_tag_type.3
new file mode 100644
index 00000000000..8a65446a45d
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_tag_type.3
@@ -0,0 +1,85 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_get_tag_type.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd March 10, 2001
+.Dt ACL_GET_TAG_TYPE 3
+.Os
+.Sh NAME
+.Nm acl_get_tag_type
+.Nd retrieve the tag type from an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_tag_type "acl_entry_t entry_d" "acl_tag_t *tag_type_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_tag_type
+function
+is a POSIX.1e call that returns the tag type for the ACL entry
+.Fa entry_d .
+Upon successful completion, the location referred to by the argument
+.Fa tag_type_p
+will be set to the tag type of the ACL entry
+.Fa entry_d .
+.Sh RETURN VALUES
+.Rv -std acl_get_tag_type
+.Sh ERRORS
+The
+.Fn acl_get_tag_type
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry;
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_create_entry 3 ,
+.Xr acl_get_entry 3 ,
+.Xr acl_get_qualifier 3 ,
+.Xr acl_init 3 ,
+.Xr acl_set_qualifier 3 ,
+.Xr acl_set_tag_type 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_tag_type
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_tag_type
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_id_to_name.c b/lib/libc/posix1e/acl_id_to_name.c
new file mode 100644
index 00000000000..a663159d312
--- /dev/null
+++ b/lib/libc/posix1e/acl_id_to_name.c
@@ -0,0 +1,105 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999-2001, 2008 Robert N. M. Watson
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * Support functionality for the POSIX.1e ACL interface
+ * These calls are intended only to be called within the library.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_id_to_name.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_id_to_name.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "acl_support.h"
+
+/*
+ * Given a uid/gid, return a username/groupname for the text form of an ACL.
+ * Note that we truncate user and group names, rather than error out, as
+ * this is consistent with other tools manipulating user and group names.
+ * XXX NOT THREAD SAFE, RELIES ON GETPWUID, GETGRGID
+ * XXX USES *PW* AND *GR* WHICH ARE STATEFUL AND THEREFORE THIS ROUTINE
+ * MAY HAVE SIDE-EFFECTS
+ */
+int
+_posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len, char *buf,
+ int flags)
+{
+ struct group *g;
+ struct passwd *p;
+ int i;
+
+ switch(tag) {
+ case ACL_USER:
+ if (flags & ACL_TEXT_NUMERIC_IDS)
+ p = NULL;
+ else
+ p = getpwuid(id);
+ if (!p)
+ i = snprintf(buf, buf_len, "%d", id);
+ else
+ i = snprintf(buf, buf_len, "%s", p->pw_name);
+
+ if (i < 0) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ return (0);
+
+ case ACL_GROUP:
+ if (flags & ACL_TEXT_NUMERIC_IDS)
+ g = NULL;
+ else
+ g = getgrgid(id);
+ if (g == NULL)
+ i = snprintf(buf, buf_len, "%d", id);
+ else
+ i = snprintf(buf, buf_len, "%s", g->gr_name);
+
+ if (i < 0) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ return (0);
+
+ default:
+ return (EINVAL);
+ }
+}
diff --git a/lib/libc/posix1e/acl_init.3 b/lib/libc/posix1e/acl_init.3
new file mode 100644
index 00000000000..fabfc917126
--- /dev/null
+++ b/lib/libc/posix1e/acl_init.3
@@ -0,0 +1,111 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_init.3 131504 2004-07-02 23:52:20Z ru $
+.\"
+.Dd January 28, 2000
+.Dt ACL_INIT 3
+.Os
+.Sh NAME
+.Nm acl_init
+.Nd initialize ACL working storage
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft acl_t
+.Fn acl_init "int count"
+.Sh DESCRIPTION
+The
+.Fn acl_init
+function allocates and initializes the working storage for an ACL of at
+least
+.Va count
+ACL entries.
+A pointer to the working storage is returned.
+The working
+storage allocated to contain the ACL is freed by a call to
+.Xr acl_free 3 .
+When the area is first allocated, it shall contain an ACL that contains
+no ACL entries.
+.Pp
+This function may cause memory to be allocated.
+The caller should free any
+releasable memory, when the new ACL is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void*)acl_t
+as an argument.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+Upon successful completion, this function shall return a pointer to the
+working storage.
+Otherwise, a value of
+.Va (acl_t)NULL
+shall be returned, and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_init
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of count is less than zero.
+.It Bq Er ENOMEM
+The
+.Va acl_t
+to be returned requires more memory than is allowed by the hardware or
+system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_free 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_init.c b/lib/libc/posix1e/acl_init.c
new file mode 100644
index 00000000000..450d3e2946d
--- /dev/null
+++ b/lib/libc/posix1e/acl_init.c
@@ -0,0 +1,94 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999, 2000, 2001 Robert N. M. Watson
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * acl_init -- return a fresh acl structure
+ * acl_dup -- duplicate an acl and return the new copy
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_init.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_init.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "acl_support.h"
+
+__CTASSERT(1 << _ACL_T_ALIGNMENT_BITS > sizeof(struct acl_t_struct));
+
+acl_t
+acl_init(int count)
+{
+ int error;
+ acl_t acl;
+
+ if (count > ACL_MAX_ENTRIES) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ if (count < 0) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ error = posix_memalign((void *)&acl, 1 << _ACL_T_ALIGNMENT_BITS,
+ sizeof(struct acl_t_struct));
+ if (error) {
+ errno = error;
+ return (NULL);
+ }
+
+ bzero(acl, sizeof(struct acl_t_struct));
+ acl->ats_brand = ACL_BRAND_UNKNOWN;
+ acl->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
+
+ return (acl);
+}
+
+acl_t
+acl_dup(acl_t acl)
+{
+ acl_t acl_new;
+
+ acl_new = acl_init(ACL_MAX_ENTRIES);
+ if (acl_new != NULL) {
+ *acl_new = *acl;
+ acl->ats_cur_entry = 0;
+ acl_new->ats_cur_entry = 0;
+ }
+
+ return (acl_new);
+}
diff --git a/lib/libc/posix1e/acl_is_trivial_np.3 b/lib/libc/posix1e/acl_is_trivial_np.3
new file mode 100644
index 00000000000..219c4e78b35
--- /dev/null
+++ b/lib/libc/posix1e/acl_is_trivial_np.3
@@ -0,0 +1,85 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_is_trivial_np.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd November 12, 2013
+.Dt ACL_STRIP_NP 3
+.Os
+.Sh NAME
+.Nm acl_is_trivial_np
+.Nd determine whether ACL is trivial
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_is_trivial_np "const acl_t aclp" "int *trivialp"
+.Sh DESCRIPTION
+The
+.Fn acl_is_trivial
+function determines whether the ACL pointed to by the argument
+.Va acl
+is trivial.
+Upon successful completion, the location referred to by the argument
+.Fa trivialp
+will be set to 1, if the ACL
+.Fa aclp
+points to is trivial, or 0 if it's not.
+.Pp
+ACL is trivial if it can be fully expressed as a file mode without losing
+any access rules.
+For POSIX.1e ACLs, ACL is trivial if it has the three required entries,
+one for owner, one for owning group, and one for other.
+For NFSv4 ACLs, ACL is trivial if it is identical to the ACL generated by
+.Fn acl_strip_np 3 .
+Files that have non-trivial ACL have a plus sign appended after mode bits
+in "ls -l" output.
+.Sh RETURN VALUES
+.Rv -std acl_get_tag_type
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_is_trivial_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org
diff --git a/lib/libc/posix1e/acl_perm.c b/lib/libc/posix1e/acl_perm.c
new file mode 100644
index 00000000000..e62360341da
--- /dev/null
+++ b/lib/libc/posix1e/acl_perm.c
@@ -0,0 +1,133 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_perm.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_perm.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include <errno.h>
+#include <string.h>
+
+static int
+_perm_is_invalid(acl_perm_t perm)
+{
+
+ /* Check if more than a single bit is set. */
+ if ((perm & -perm) == perm &&
+ (perm & (ACL_POSIX1E_BITS | ACL_NFS4_PERM_BITS)) == perm)
+ return (0);
+
+ errno = EINVAL;
+
+ return (1);
+}
+
+/*
+ * acl_add_perm() (23.4.1): add the permission contained in perm to the
+ * permission set permset_d
+ */
+int
+acl_add_perm(acl_permset_t permset_d, acl_perm_t perm)
+{
+
+ if (permset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_perm_is_invalid(perm))
+ return (-1);
+
+ *permset_d |= perm;
+
+ return (0);
+}
+
+/*
+ * acl_clear_perms() (23.4.3): clear all permisions from the permission
+ * set permset_d
+ */
+int
+acl_clear_perms(acl_permset_t permset_d)
+{
+
+ if (permset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *permset_d = ACL_PERM_NONE;
+
+ return (0);
+}
+
+/*
+ * acl_delete_perm() (23.4.10): remove the permission in perm from the
+ * permission set permset_d
+ */
+int
+acl_delete_perm(acl_permset_t permset_d, acl_perm_t perm)
+{
+
+ if (permset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_perm_is_invalid(perm))
+ return (-1);
+
+ *permset_d &= ~perm;
+
+ return (0);
+}
+
+int
+acl_get_perm_np(acl_permset_t permset_d, acl_perm_t perm)
+{
+
+ if (permset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_perm_is_invalid(perm))
+ return (-1);
+
+ if (*permset_d & perm)
+ return (1);
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_set.3 b/lib/libc/posix1e/acl_set.3
new file mode 100644
index 00000000000..3d08d293f52
--- /dev/null
+++ b/lib/libc/posix1e/acl_set.3
@@ -0,0 +1,157 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_set.3 213573 2010-10-08 12:40:16Z uqs $
+.\"
+.Dd June 25, 2009
+.Dt ACL_SET 3
+.Os
+.Sh NAME
+.Nm acl_set_fd ,
+.Nm acl_set_fd_np ,
+.Nm acl_set_file ,
+.Nm acl_set_link_np
+.Nd set an ACL for a file
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_fd "int fd" "acl_t acl"
+.Ft int
+.Fn acl_set_fd_np "int fd" "acl_t acl" "acl_type_t type"
+.Ft int
+.Fn acl_set_file "const char *path_p" "acl_type_t type" "acl_t acl"
+.Ft int
+.Fn acl_set_link_np "const char *path_p" "acl_type_t type" "acl_t acl"
+.Sh DESCRIPTION
+The
+.Fn acl_set_fd ,
+.Fn acl_set_fd_np ,
+.Fn acl_set_file ,
+and
+.Fn acl_set_link_np
+each associate an ACL with an object referred to by
+.Va fd
+or
+.Va path_p .
+The
+.Fn acl_set_fd_np
+and
+.Fn acl_set_link_np
+functions are not POSIX.1e calls.
+The
+.Fn acl_set_fd
+function allows only the setting of ACLs of type ACL_TYPE_ACCESS
+where as
+.Fn acl_set_fd_np
+allows the setting of ACLs of any type.
+The
+.Fn acl_set_link_np
+function acts on a symlink rather than its target, if the target of the
+path is a symlink.
+.Pp
+Valid values for the
+.Va type
+argument are:
+.Bl -column -offset 3n "ACL_TYPE_DEFAULT"
+.It ACL_TYPE_ACCESS POSIX.1e access ACL
+.It ACL_TYPE_DEFAULT POSIX.1e default ACL
+.It ACL_TYPE_NFS4 NFSv4 ACL
+.El
+.Pp
+Trying to set ACL_TYPE_NFS4 with
+.Va acl
+branded as POSIX.1e, or ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT with ACL
+branded as NFSv4, will result in error.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+If any of the following conditions occur, these functions shall return
+-1 and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EACCES
+Search permission is denied for a component of the path prefix, or the
+object exists and the process does not have appropriate access rights.
+.It Bq Er EBADF
+The
+.Va fd
+argument is not a valid file descriptor.
+.It Bq Er EINVAL
+Argument
+.Va acl
+does not point to a valid ACL for this object, or the ACL type
+specified in
+.Va type
+is invalid for this object, or there is branding mismatch.
+.It Bq Er ENAMETOOLONG
+A component of a pathname exceeded 255 characters, or an
+entire path name exceeded 1023 characters.
+.It Bq Er ENOENT
+The named object does not exist, or the
+.Va path_p
+argument points to an empty string.
+.It Bq Er ENOMEM
+Insufficient memory available to fulfill request.
+.It Bq Er ENOSPC
+The directory or file system that would contain the new ACL cannot be
+extended, or the file system is out of file allocation resources.
+.It Bq Er EOPNOTSUPP
+The file system does not support ACL retrieval.
+.It Bq Er EROFS
+This function requires modification of a file system which is currently
+read-only.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_delete 3 ,
+.Xr acl_get 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_valid 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_set.c b/lib/libc/posix1e/acl_set.c
new file mode 100644
index 00000000000..c558d0ce76f
--- /dev/null
+++ b/lib/libc/posix1e/acl_set.c
@@ -0,0 +1,258 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * acl_set_file -- set a file/directory ACL by name
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_set.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_set.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "acl_support.h"
+
+/*
+ * For POSIX.1e-semantic ACLs, do a presort so the kernel doesn't have to
+ * (the POSIX.1e semantic code will reject unsorted ACL submission). If it's
+ * not a semantic that the library knows about, just submit it flat and
+ * assume the caller knows what they're up to.
+ */
+int
+acl_set_file(const char *path_p, acl_type_t type, acl_t acl)
+{
+
+ if (acl == NULL || path_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_acl_type_not_valid_for_acl(acl, type)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ acl->ats_cur_entry = 0;
+
+ return (__acl_set_file(path_p, type, &acl->ats_acl));
+}
+
+int
+acl_set_link_np(const char *path_p, acl_type_t type, acl_t acl)
+{
+
+ if (acl == NULL || path_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_acl_type_not_valid_for_acl(acl, type)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ acl->ats_cur_entry = 0;
+
+ return (__acl_set_link(path_p, type, &acl->ats_acl));
+}
+
+int
+acl_set_fd(int fd, acl_t acl)
+{
+
+ if (fpathconf(fd, _PC_ACL_NFS4) == 1)
+ return (acl_set_fd_np(fd, acl, ACL_TYPE_NFS4));
+
+ return (acl_set_fd_np(fd, acl, ACL_TYPE_ACCESS));
+}
+
+int
+acl_set_fd_np(int fd, acl_t acl, acl_type_t type)
+{
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_acl_type_not_valid_for_acl(acl, type)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ acl->ats_cur_entry = 0;
+
+ return (__acl_set_fd(fd, type, &acl->ats_acl));
+}
+
+/*
+ * acl_set_permset() (23.4.23): sets the permissions of ACL entry entry_d
+ * with the permissions in permset_d
+ */
+int
+acl_set_permset(acl_entry_t entry_d, acl_permset_t permset_d)
+{
+
+ if (!entry_d) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((*permset_d & ACL_POSIX1E_BITS) != *permset_d) {
+ if ((*permset_d & ACL_NFS4_PERM_BITS) != *permset_d) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+ }
+
+ entry_d->ae_perm = *permset_d;
+
+ return (0);
+}
+
+/*
+ * acl_set_qualifier() sets the qualifier (ae_id) of the tag for
+ * ACL entry entry_d to the value referred to by tag_qualifier_p
+ */
+int
+acl_set_qualifier(acl_entry_t entry_d, const void *tag_qualifier_p)
+{
+
+ if (!entry_d || !tag_qualifier_p) {
+ errno = EINVAL;
+ return (-1);
+ }
+ switch(entry_d->ae_tag) {
+ case ACL_USER:
+ case ACL_GROUP:
+ entry_d->ae_id = *(const uid_t *)tag_qualifier_p;
+ break;
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * acl_set_tag_type() sets the tag type for ACL entry entry_d to the
+ * value of tag_type
+ */
+int
+acl_set_tag_type(acl_entry_t entry_d, acl_tag_t tag_type)
+{
+
+ if (entry_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch(tag_type) {
+ case ACL_OTHER:
+ case ACL_MASK:
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_POSIX)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_POSIX);
+ break;
+ case ACL_EVERYONE:
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+ break;
+ }
+
+ switch(tag_type) {
+ case ACL_USER_OBJ:
+ case ACL_USER:
+ case ACL_GROUP_OBJ:
+ case ACL_GROUP:
+ case ACL_MASK:
+ case ACL_OTHER:
+ case ACL_EVERYONE:
+ entry_d->ae_tag = tag_type;
+ return (0);
+ }
+
+ errno = EINVAL;
+ return (-1);
+}
+
+int
+acl_set_entry_type_np(acl_entry_t entry_d, acl_entry_type_t entry_type)
+{
+
+ if (entry_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+
+ switch (entry_type) {
+ case ACL_ENTRY_TYPE_ALLOW:
+ case ACL_ENTRY_TYPE_DENY:
+ case ACL_ENTRY_TYPE_AUDIT:
+ case ACL_ENTRY_TYPE_ALARM:
+ entry_d->ae_entry_type = entry_type;
+ return (0);
+ }
+
+ errno = EINVAL;
+ return (-1);
+}
diff --git a/lib/libc/posix1e/acl_set_entry_type_np.3 b/lib/libc/posix1e/acl_set_entry_type_np.3
new file mode 100644
index 00000000000..0e5b111d920
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_entry_type_np.3
@@ -0,0 +1,94 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_set_entry_type_np.3 273853 2014-10-30 10:49:50Z trasz $
+.\"
+.Dd October 30, 2014
+.Dt ACL_SET_ENTRY_TYPE_NP 3
+.Os
+.Sh NAME
+.Nm acl_set_entry_type_np
+.Nd set NFSv4 ACL entry type
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_entry_type_np "acl_entry_t entry_d" "acl_entry_type_t entry_type"
+.Sh DESCRIPTION
+The
+.Fn acl_set_entry_type_np
+function
+is a non-portable call that sets the type of the NFSv4 ACL entry
+.Fa entry_d
+to the value referred to by
+.Fa entry_type .
+.Pp
+Valid values are:
+.Bl -column -offset 3n "ACL_ENTRY_TYPE_ALLOW"
+.It ACL_ENTRY_TYPE_ALLOW Ta "allow" type entry
+.It ACL_ENTRY_TYPE_DENY Ta "deny" type entry
+.El
+.Pp
+This call brands the ACL as NFSv4.
+.Sh RETURN VALUES
+.Rv -std acl_set_entry_type_np
+.Sh ERRORS
+The
+.Fn acl_set_entry_type_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+The value pointed to by
+.Fa entry_type
+is not valid.
+ACL is already branded as POSIX.1e.
+.It Bq Er ENOMEM
+The value to be returned requires more memory than is allowed
+by the hardware or system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_get_entry_type_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_entry_type_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_entry_type_np
+function was written by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_set_flagset_np.3 b/lib/libc/posix1e/acl_set_flagset_np.3
new file mode 100644
index 00000000000..fba1b052f56
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_flagset_np.3
@@ -0,0 +1,85 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_set_flagset_np.3 276006 2014-12-21 12:36:36Z brueffer $
+.\"
+.Dd October 30, 2014
+.Dt ACL_SET_FLAGSET_NP 3
+.Os
+.Sh NAME
+.Nm acl_set_flagset_np
+.Nd set the flags of an NFSv4 ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_flagset_np "acl_entry_t entry_d" "acl_flagset_t flagset_d"
+.Sh DESCRIPTION
+The
+.Fn acl_set_flagset_np
+function
+is a non-portable call that sets the flags of NFSv4 ACL entry
+.Fa entry_d
+with the flags contained in
+.Fa flagset_d .
+.Pp
+This call brands the ACL as NFSv4.
+.Sh RETURN VALUES
+.Rv -std acl_set_flagset_np
+.Sh ERRORS
+The
+.Fn acl_set_flagset_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+ACL is already branded as POSIX.1e.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_set_flagset_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_set_flagset_np
+function was written by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_set_permset.3 b/lib/libc/posix1e/acl_set_permset.3
new file mode 100644
index 00000000000..a70db801f7d
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_permset.3
@@ -0,0 +1,81 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_set_permset.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd March 10, 2001
+.Dt ACL_SET_PERMSET 3
+.Os
+.Sh NAME
+.Nm acl_set_permset
+.Nd set the permissions of an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_permset "acl_entry_t entry_d" "acl_permset_t permset_d"
+.Sh DESCRIPTION
+The
+.Fn acl_set_permset
+function
+is a POSIX.1e call that sets the permissions of ACL entry
+.Fa entry_d
+with the permissions contained in
+.Fa permset_d .
+.Sh RETURN VALUES
+.Rv -std acl_set_permset
+.Sh ERRORS
+The
+.Fn acl_set_permset
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_get_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_set_permset
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_set_permset
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_set_qualifier.3 b/lib/libc/posix1e/acl_set_qualifier.3
new file mode 100644
index 00000000000..91c14f53e19
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_qualifier.3
@@ -0,0 +1,91 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_set_qualifier.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd March 10, 2001
+.Dt ACL_SET_QUALIFIER 3
+.Os
+.Sh NAME
+.Nm acl_set_qualifier
+.Nd set ACL tag qualifier
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_qualifier "acl_entry_t entry_d" "const void *tag_qualifier_p"
+.Sh DESCRIPTION
+The
+.Fn acl_set_qualifier
+function
+is a POSIX.1e call that sets the qualifier of the tag for the ACL entry
+.Fa entry_d
+to the value referred to by
+.Fa tag_qualifier_p .
+.Sh RETURN VALUES
+.Rv -std acl_set_qualifier
+.Sh ERRORS
+The
+.Fn acl_set_qualifier
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+The tag type of the
+ACL entry
+.Fa entry_d
+is not
+.Dv ACL_USER
+or
+.Dv ACL_GROUP .
+The value pointed to by
+.Fa tag_qualifier_p
+is not valid.
+.It Bq Er ENOMEM
+The value to be returned requires more memory than is allowed
+by the hardware or system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get_qualifier 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_qualifier
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_qualifier
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_set_tag_type.3 b/lib/libc/posix1e/acl_set_tag_type.3
new file mode 100644
index 00000000000..25233919952
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_tag_type.3
@@ -0,0 +1,102 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_set_tag_type.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd June 25, 2009
+.Dt ACL_SET_TAG_TYPE 3
+.Os
+.Sh NAME
+.Nm acl_set_tag_type
+.Nd set the tag type of an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_tag_type "acl_entry_t entry_d" "acl_tag_t tag_type"
+.Sh DESCRIPTION
+The
+.Fn acl_set_tag_type
+function
+is a POSIX.1e call that sets the ACL tag type of ACL entry
+.Fa entry_d
+to the value of
+.Fa tag_type .
+.Pp
+Valid values are:
+.Bl -column -offset 3n "ACL_OTHER_OBJ"
+.It ACL_USER_OBJ Ta "Permissions apply to file owner"
+.It ACL_USER Ta "Permissions apply to additional user specified by qualifier"
+.It ACL_GROUP_OBJ Ta "Permissions apply to file group"
+.It ACL_GROUP Ta "Permissions apply to additional group specified by qualifier"
+.It ACL_MASK Ta "Permissions specify mask"
+.It ACL_OTHER Ta Permissions apply to "other"
+.It ACL_OTHER_OBJ Ta "Same as ACL_OTHER"
+.It ACL_EVERYONE Ta Permissions apply to "everyone@"
+.El
+.Pp
+Calling
+.Fn acl_set_tag_type
+with
+.Fa tag_type
+equal to ACL_MASK, ACL_OTHER or ACL_OTHER_OBJ brands the ACL as POSIX.1e.
+Calling it with ACL_EVERYONE brands the ACL as NFSv4.
+.Sh RETURN VALUES
+.Rv -std acl_set_tag_type
+.Sh ERRORS
+The
+.Fn acl_set_tag_type
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+Argument
+.Fa tag_type
+is not a valid ACL tag type.
+ACL is already branded differently.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_get_tag_type 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_set_tag_type
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_set_tag_type
+function was written by
+.An Chris D. Faulhaber Aq Mt jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_strip.c b/lib/libc/posix1e/acl_strip.c
new file mode 100644
index 00000000000..5008921c534
--- /dev/null
+++ b/lib/libc/posix1e/acl_strip.c
@@ -0,0 +1,222 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2001 Chris D. Faulhaber
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_strip.c 344294 2019-02-19 19:15:15Z sef $");
+#else
+__RCSID("$NetBSD: acl_strip.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+#include <sys/acl.h>
+#include <sys/stat.h>
+
+#include "acl_support.h"
+
+static acl_t
+_nfs4_acl_strip_np(const acl_t aclp, int canonical_six)
+{
+ acl_t newacl;
+ mode_t mode = 0;
+
+ newacl = acl_init(ACL_MAX_ENTRIES);
+ if (newacl == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+
+ _acl_brand_as(newacl, ACL_BRAND_NFS4);
+
+ __acl_nfs4_sync_mode_from_acl(&mode, &(aclp->ats_acl));
+ __acl_nfs4_trivial_from_mode_libc(&(newacl->ats_acl), mode, canonical_six);
+
+ return (newacl);
+}
+
+static acl_t
+_posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask)
+{
+ acl_t acl_new, acl_old;
+ acl_entry_t entry, entry_new;
+ acl_tag_t tag;
+ int entry_id, have_mask_entry;
+
+ assert(_acl_brand(aclp) == ACL_BRAND_POSIX);
+
+ acl_old = acl_dup(aclp);
+ if (acl_old == NULL)
+ return (NULL);
+
+ assert(_acl_brand(acl_old) == ACL_BRAND_POSIX);
+
+ have_mask_entry = 0;
+ acl_new = acl_init(ACL_MAX_ENTRIES);
+ if (acl_new == NULL) {
+ acl_free(acl_old);
+ return (NULL);
+ }
+ tag = ACL_UNDEFINED_TAG;
+
+ /* only save the default user/group/other entries */
+ entry_id = ACL_FIRST_ENTRY;
+ while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+
+ assert(_entry_brand(entry) == ACL_BRAND_POSIX);
+
+ if (acl_get_tag_type(entry, &tag) == -1)
+ goto fail;
+
+ switch(tag) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_OTHER:
+ if (acl_create_entry(&acl_new, &entry_new) == -1)
+ goto fail;
+ if (acl_copy_entry(entry_new, entry) == -1)
+ goto fail;
+ assert(_entry_brand(entry_new) == ACL_BRAND_POSIX);
+ break;
+ case ACL_MASK:
+ have_mask_entry = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ assert(_acl_brand(acl_new) == ACL_BRAND_POSIX);
+
+ if (have_mask_entry && recalculate_mask) {
+ if (acl_calc_mask(&acl_new) == -1)
+ goto fail;
+ }
+
+ return (acl_new);
+
+fail:
+ acl_free(acl_new);
+ acl_free(acl_old);
+
+ return (NULL);
+}
+
+acl_t
+acl_strip_np(const acl_t aclp, int recalculate_mask)
+{
+ switch (_acl_brand(aclp)) {
+ case ACL_BRAND_NFS4:
+ return (_nfs4_acl_strip_np(aclp, 0));
+
+ case ACL_BRAND_POSIX:
+ return (_posix1e_acl_strip_np(aclp, recalculate_mask));
+
+ default:
+ errno = EINVAL;
+ return (NULL);
+ }
+}
+
+/*
+ * Return 1, if ACL is trivial, 0 otherwise.
+ *
+ * ACL is trivial, iff its meaning could be fully expressed using just file
+ * mode. In other words, ACL is trivial iff it doesn't have "+" to the right
+ * of the mode bits in "ls -l" output ;-)
+ */
+int
+acl_is_trivial_np(const acl_t aclp, int *trivialp)
+{
+ acl_t tmpacl;
+ int differs;
+
+ if (aclp == NULL || trivialp == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch (_acl_brand(aclp)) {
+ case ACL_BRAND_POSIX:
+ if (aclp->ats_acl.acl_cnt == 3)
+ *trivialp = 1;
+ else
+ *trivialp = 0;
+
+ return (0);
+
+ case ACL_BRAND_NFS4:
+ /*
+ * If the ACL has more than canonical six entries,
+ * it's non trivial by definition.
+ */
+ if (aclp->ats_acl.acl_cnt > 6) {
+ *trivialp = 0;
+ return (0);
+ }
+
+ /*
+ * Calculate trivial ACL - using acl_strip_np(3) - and compare
+ * with the original.
+ */
+ tmpacl = _nfs4_acl_strip_np(aclp, 0);
+ if (tmpacl == NULL)
+ return (-1);
+
+ differs = _acl_differs(aclp, tmpacl);
+ acl_free(tmpacl);
+
+ if (differs == 0) {
+ *trivialp = 1;
+ return (0);
+ }
+
+ /*
+ * Try again with an old-style, "canonical six" trivial ACL.
+ */
+ tmpacl = _nfs4_acl_strip_np(aclp, 1);
+ if (tmpacl == NULL)
+ return (-1);
+
+ differs = _acl_differs(aclp, tmpacl);
+ acl_free(tmpacl);
+
+ if (differs)
+ *trivialp = 0;
+ else
+ *trivialp = 1;
+
+ return (0);
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+}
diff --git a/lib/libc/posix1e/acl_strip_np.3 b/lib/libc/posix1e/acl_strip_np.3
new file mode 100644
index 00000000000..f3e556705af
--- /dev/null
+++ b/lib/libc/posix1e/acl_strip_np.3
@@ -0,0 +1,109 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_strip_np.3 267774 2014-06-23 08:25:03Z bapt $
+.\"
+.Dd June 25, 2009
+.Dt ACL_STRIP_NP 3
+.Os
+.Sh NAME
+.Nm acl_strip_np
+.Nd strip extended entries from an ACL
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft acl_t
+.Fn acl_strip_np "const acl_t acl" "int recalculate_mask"
+.Sh DESCRIPTION
+The
+.Fn acl_strip_np
+function returns a pointer to a trivial ACL computed from the ACL pointed
+to by the argument
+.Va acl .
+.Pp
+This function may cause memory to be allocated.
+The caller should free any
+releasable memory, when the new ACL is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void*)acl_t
+as an argument.
+.Pp
+Any existing ACL pointers that refer to the ACL referred to by
+.Va acl
+shall continue to refer to the ACL.
+.Sh RETURN VALUES
+Upon successful completion, this function shall return a pointer to the
+newly allocated ACL.
+Otherwise, a value of
+.Va (acl_t)NULL
+shall be returned, and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_init
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Va acl
+does not point to a valid ACL.
+.It Bq Er ENOMEM
+The
+.Va acl_t
+to be returned requires more memory than is allowed by the hardware or
+system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_is_trivial_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_strip_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org
diff --git a/lib/libc/posix1e/acl_support.c b/lib/libc/posix1e/acl_support.c
new file mode 100644
index 00000000000..24856f3daef
--- /dev/null
+++ b/lib/libc/posix1e/acl_support.c
@@ -0,0 +1,423 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999-2001, 2008 Robert N. M. Watson
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * Support functionality for the POSIX.1e ACL interface
+ * These calls are intended only to be called within the library.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_support.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_support.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "acl_support.h"
+
+#define ACL_STRING_PERM_WRITE 'w'
+#define ACL_STRING_PERM_READ 'r'
+#define ACL_STRING_PERM_EXEC 'x'
+#define ACL_STRING_PERM_NONE '-'
+
+/*
+ * Return 0, if both ACLs are identical.
+ */
+int
+_acl_differs(const acl_t a, const acl_t b)
+{
+ size_t i;
+ struct acl_entry *entrya, *entryb;
+
+ assert(_acl_brand(a) == _acl_brand(b));
+ assert(_acl_brand(a) != ACL_BRAND_UNKNOWN);
+ assert(_acl_brand(b) != ACL_BRAND_UNKNOWN);
+
+ if (a->ats_acl.acl_cnt != b->ats_acl.acl_cnt)
+ return (1);
+
+ for (i = 0; i < b->ats_acl.acl_cnt; i++) {
+ entrya = &(a->ats_acl.acl_entry[i]);
+ entryb = &(b->ats_acl.acl_entry[i]);
+
+ if (entrya->ae_tag != entryb->ae_tag ||
+ entrya->ae_id != entryb->ae_id ||
+ entrya->ae_perm != entryb->ae_perm ||
+ entrya->ae_entry_type != entryb->ae_entry_type ||
+ entrya->ae_flags != entryb->ae_flags)
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * _posix1e_acl_entry_compare -- compare two acl_entry structures to
+ * determine the order they should appear in. Used by _posix1e_acl_sort to
+ * sort ACL entries into the kernel-desired order -- i.e., the order useful
+ * for evaluation and O(n) validity checking. Beter to have an O(nlogn) sort
+ * in userland and an O(n) in kernel than to have both in kernel.
+ */
+typedef int (*compare)(const void *, const void *);
+static int
+_posix1e_acl_entry_compare(struct acl_entry *a, struct acl_entry *b)
+{
+
+ assert(_entry_brand(a) == ACL_BRAND_POSIX);
+ assert(_entry_brand(b) == ACL_BRAND_POSIX);
+
+ /*
+ * First, sort between tags -- conveniently defined in the correct
+ * order for verification.
+ */
+ if (a->ae_tag < b->ae_tag)
+ return (-1);
+ if (a->ae_tag > b->ae_tag)
+ return (1);
+
+ /*
+ * Next compare uids/gids on appropriate types.
+ */
+
+ if (a->ae_tag == ACL_USER || a->ae_tag == ACL_GROUP) {
+ if (a->ae_id < b->ae_id)
+ return (-1);
+ if (a->ae_id > b->ae_id)
+ return (1);
+
+ /* shouldn't be equal, fall through to the invalid case */
+ }
+
+ /*
+ * Don't know how to sort multiple entries of the rest--either it's
+ * a bad entry, or there shouldn't be more than one. Ignore and the
+ * validity checker can get it later.
+ */
+ return (0);
+}
+
+/*
+ * _posix1e_acl_sort -- sort ACL entries in POSIX.1e-formatted ACLs.
+ */
+void
+_posix1e_acl_sort(acl_t acl)
+{
+ struct acl *acl_int;
+
+ acl_int = &acl->ats_acl;
+
+ qsort(&acl_int->acl_entry[0], acl_int->acl_cnt,
+ sizeof(struct acl_entry), (compare) _posix1e_acl_entry_compare);
+}
+
+/*
+ * acl_posix1e -- in what situations should we acl_sort before submission?
+ * We apply posix1e ACL semantics for any ACL of type ACL_TYPE_ACCESS or
+ * ACL_TYPE_DEFAULT
+ */
+int
+_posix1e_acl(acl_t acl, acl_type_t type)
+{
+
+ if (_acl_brand(acl) != ACL_BRAND_POSIX)
+ return (0);
+
+ return ((type == ACL_TYPE_ACCESS) || (type == ACL_TYPE_DEFAULT));
+}
+
+/*
+ * _posix1e_acl_check -- given an ACL, check its validity. This is mirrored
+ * from code in sys/kern/kern_acl.c, and if changes are made in one, they
+ * should be made in the other also. This copy of acl_check is made
+ * available * in userland for the benefit of processes wanting to check ACLs
+ * for validity before submitting them to the kernel, or for performing
+ * in userland file system checking. Needless to say, the kernel makes
+ * the real checks on calls to get/setacl.
+ *
+ * See the comments in kernel for explanation -- just briefly, it assumes
+ * an already sorted ACL, and checks based on that assumption. The
+ * POSIX.1e interface, acl_valid(), will perform the sort before calling
+ * this. Returns 0 on success, EINVAL on failure.
+ */
+int
+_posix1e_acl_check(acl_t acl)
+{
+ struct acl *acl_int;
+ struct acl_entry *entry; /* current entry */
+ uid_t highest_uid=0, highest_gid=0;
+ int stage = ACL_USER_OBJ;
+ size_t i = 0;
+ int count_user_obj=0, count_user=0, count_group_obj=0,
+ count_group=0, count_mask=0, count_other=0;
+
+ acl_int = &acl->ats_acl;
+
+ /* printf("_posix1e_acl_check: checking acl with %d entries\n",
+ acl->acl_cnt); */
+ while (i < acl_int->acl_cnt) {
+ entry = &acl_int->acl_entry[i];
+
+ if ((entry->ae_perm | ACL_PERM_BITS) != ACL_PERM_BITS)
+ return (EINVAL);
+
+ switch(entry->ae_tag) {
+ case ACL_USER_OBJ:
+ /* printf("_posix1e_acl_check: %d: ACL_USER_OBJ\n",
+ i); */
+ if (stage > ACL_USER_OBJ)
+ return (EINVAL);
+ stage = ACL_USER;
+ count_user_obj++;
+ break;
+
+ case ACL_USER:
+ /* printf("_posix1e_acl_check: %d: ACL_USER\n", i); */
+ if (stage > ACL_USER)
+ return (EINVAL);
+ stage = ACL_USER;
+ if (count_user && (entry->ae_id <= highest_uid))
+ return (EINVAL);
+ highest_uid = entry->ae_id;
+ count_user++;
+ break;
+
+ case ACL_GROUP_OBJ:
+ /* printf("_posix1e_acl_check: %d: ACL_GROUP_OBJ\n",
+ i); */
+ if (stage > ACL_GROUP_OBJ)
+ return (EINVAL);
+ stage = ACL_GROUP;
+ count_group_obj++;
+ break;
+
+ case ACL_GROUP:
+ /* printf("_posix1e_acl_check: %d: ACL_GROUP\n", i); */
+ if (stage > ACL_GROUP)
+ return (EINVAL);
+ stage = ACL_GROUP;
+ if (count_group && (entry->ae_id <= highest_gid))
+ return (EINVAL);
+ highest_gid = entry->ae_id;
+ count_group++;
+ break;
+
+ case ACL_MASK:
+ /* printf("_posix1e_acl_check: %d: ACL_MASK\n", i); */
+ if (stage > ACL_MASK)
+ return (EINVAL);
+ stage = ACL_MASK;
+ count_mask++;
+ break;
+
+ case ACL_OTHER:
+ /* printf("_posix1e_acl_check: %d: ACL_OTHER\n", i); */
+ if (stage > ACL_OTHER)
+ return (EINVAL);
+ stage = ACL_OTHER;
+ count_other++;
+ break;
+
+ default:
+ /* printf("_posix1e_acl_check: %d: INVALID\n", i); */
+ return (EINVAL);
+ }
+ i++;
+ }
+
+ if (count_user_obj != 1)
+ return (EINVAL);
+
+ if (count_group_obj != 1)
+ return (EINVAL);
+
+ if (count_mask != 0 && count_mask != 1)
+ return (EINVAL);
+
+ if (count_other != 1)
+ return (EINVAL);
+
+ return (0);
+}
+
+/*
+ * Given a right-shifted permission (i.e., direct ACL_PERM_* mask), fill
+ * in a string describing the permissions.
+ */
+int
+_posix1e_acl_perm_to_string(acl_perm_t perm, ssize_t buf_len, char *buf)
+{
+
+ if (buf_len < _POSIX1E_ACL_STRING_PERM_MAXSIZE + 1) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ if ((perm | ACL_PERM_BITS) != ACL_PERM_BITS) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ buf[3] = 0; /* null terminate */
+
+ if (perm & ACL_READ)
+ buf[0] = ACL_STRING_PERM_READ;
+ else
+ buf[0] = ACL_STRING_PERM_NONE;
+
+ if (perm & ACL_WRITE)
+ buf[1] = ACL_STRING_PERM_WRITE;
+ else
+ buf[1] = ACL_STRING_PERM_NONE;
+
+ if (perm & ACL_EXECUTE)
+ buf[2] = ACL_STRING_PERM_EXEC;
+ else
+ buf[2] = ACL_STRING_PERM_NONE;
+
+ return (0);
+}
+
+/*
+ * given a string, return a permission describing it
+ */
+int
+_posix1e_acl_string_to_perm(char *string, acl_perm_t *perm)
+{
+ acl_perm_t myperm = ACL_PERM_NONE;
+ char *ch;
+
+ ch = string;
+ while (*ch) {
+ switch(*ch) {
+ case ACL_STRING_PERM_READ:
+ myperm |= ACL_READ;
+ break;
+ case ACL_STRING_PERM_WRITE:
+ myperm |= ACL_WRITE;
+ break;
+ case ACL_STRING_PERM_EXEC:
+ myperm |= ACL_EXECUTE;
+ break;
+ case ACL_STRING_PERM_NONE:
+ break;
+ default:
+ return (EINVAL);
+ }
+ ch++;
+ }
+
+ *perm = myperm;
+ return (0);
+}
+
+/*
+ * Add an ACL entry without doing much checking, et al
+ */
+int
+_posix1e_acl_add_entry(acl_t acl, acl_tag_t tag, uid_t id, acl_perm_t perm)
+{
+ struct acl *acl_int;
+ struct acl_entry *e;
+
+ acl_int = &acl->ats_acl;
+
+ if (acl_int->acl_cnt >= ACL_MAX_ENTRIES) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ e = &(acl_int->acl_entry[acl_int->acl_cnt]);
+ e->ae_perm = perm;
+ e->ae_tag = tag;
+ e->ae_id = id;
+ acl_int->acl_cnt++;
+
+ return (0);
+}
+
+/*
+ * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new"
+ * counterpart. It's necessary for the old (pre-NFSv4 ACLs) binaries
+ * to work with new libc and kernel. Fixing 'type' for old binaries with
+ * old libc and new kernel is being done by kern/vfs_acl.c:type_unold().
+ */
+int
+_acl_type_unold(acl_type_t type)
+{
+
+ switch (type) {
+ case ACL_TYPE_ACCESS_OLD:
+ return (ACL_TYPE_ACCESS);
+ case ACL_TYPE_DEFAULT_OLD:
+ return (ACL_TYPE_DEFAULT);
+ default:
+ return (type);
+ }
+}
+
+char *
+string_skip_whitespace(char *string)
+{
+
+ while (*string && ((*string == ' ') || (*string == '\t')))
+ string++;
+
+ return (string);
+}
+
+void
+string_trim_trailing_whitespace(char *string)
+{
+ char *end;
+
+ if (*string == '\0')
+ return;
+
+ end = string + strlen(string) - 1;
+
+ while (end != string) {
+ if ((*end == ' ') || (*end == '\t')) {
+ *end = '\0';
+ end--;
+ } else {
+ return;
+ }
+ }
+
+ return;
+}
diff --git a/lib/libc/posix1e/acl_support.h b/lib/libc/posix1e/acl_support.h
new file mode 100644
index 00000000000..6932a7f7454
--- /dev/null
+++ b/lib/libc/posix1e/acl_support.h
@@ -0,0 +1,70 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999, 2000, 2001 Robert N. M. Watson
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_support.h 326193 2017-11-25 17:12:48Z pfg $
+ */
+/*
+ * Support functionality for the POSIX.1e ACL interface
+ * These calls are intended only to be called within the library.
+ */
+#ifndef _ACL_SUPPORT_H
+#define _ACL_SUPPORT_H
+
+#define _POSIX1E_ACL_STRING_PERM_MAXSIZE 3 /* read, write, exec */
+#define _ACL_T_ALIGNMENT_BITS 13
+
+int _acl_type_unold(acl_type_t type);
+int _acl_differs(const acl_t a, const acl_t b);
+int _acl_type_not_valid_for_acl(const acl_t acl, acl_type_t type);
+void _acl_brand_from_type(acl_t acl, acl_type_t type);
+int _acl_brand(const acl_t acl);
+int _entry_brand(const acl_entry_t entry);
+int _acl_brand_may_be(const acl_t acl, int brand);
+int _entry_brand_may_be(const acl_entry_t entry, int brand);
+void _acl_brand_as(acl_t acl, int brand);
+void _entry_brand_as(const acl_entry_t entry, int brand);
+int _nfs4_acl_entry_from_text(acl_t, char *);
+char *_nfs4_acl_to_text_np(const acl_t, ssize_t *, int);
+int _nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose);
+int _nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose);
+int _nfs4_parse_flags(const char *str, acl_flag_t *var);
+int _nfs4_parse_access_mask(const char *str, acl_perm_t *var);
+int _posix1e_acl_check(acl_t acl);
+void _posix1e_acl_sort(acl_t acl);
+int _posix1e_acl(acl_t acl, acl_type_t type);
+int _posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len,
+ char *buf, int flags);
+int _posix1e_acl_perm_to_string(acl_perm_t perm, ssize_t buf_len,
+ char *buf);
+int _posix1e_acl_string_to_perm(char *string, acl_perm_t *perm);
+int _posix1e_acl_add_entry(acl_t acl, acl_tag_t tag, uid_t id,
+ acl_perm_t perm);
+char *string_skip_whitespace(char *string);
+void string_trim_trailing_whitespace(char *string);
+int _acl_name_to_id(acl_tag_t tag, char *name, uid_t *id);
+
+#endif
diff --git a/lib/libc/posix1e/acl_support_nfs4.c b/lib/libc/posix1e/acl_support_nfs4.c
new file mode 100644
index 00000000000..0a6ac983bfb
--- /dev/null
+++ b/lib/libc/posix1e/acl_support_nfs4.c
@@ -0,0 +1,267 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_support_nfs4.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_support_nfs4.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <err.h>
+#include <sys/acl.h>
+#include "acl_support.h"
+
+struct flagnames_struct {
+ uint32_t flag;
+ const char *name;
+ char letter;
+};
+
+struct flagnames_struct a_flags[] =
+ {{ ACL_ENTRY_FILE_INHERIT, "file_inherit", 'f'},
+ { ACL_ENTRY_DIRECTORY_INHERIT, "dir_inherit", 'd'},
+ { ACL_ENTRY_INHERIT_ONLY, "inherit_only", 'i'},
+ { ACL_ENTRY_NO_PROPAGATE_INHERIT, "no_propagate", 'n'},
+ { ACL_ENTRY_SUCCESSFUL_ACCESS, "successfull_access", 'S'},
+ { ACL_ENTRY_FAILED_ACCESS, "failed_access", 'F'},
+ { ACL_ENTRY_INHERITED, "inherited", 'I' },
+ /*
+ * There is no ACE_IDENTIFIER_GROUP here - SunOS does not show it
+ * in the "flags" field. There is no ACE_OWNER, ACE_GROUP or
+ * ACE_EVERYONE either, for obvious reasons.
+ */
+ { 0, 0, 0}};
+
+struct flagnames_struct a_access_masks[] =
+ {{ ACL_READ_DATA, "read_data", 'r'},
+ { ACL_WRITE_DATA, "write_data", 'w'},
+ { ACL_EXECUTE, "execute", 'x'},
+ { ACL_APPEND_DATA, "append_data", 'p'},
+ { ACL_DELETE_CHILD, "delete_child", 'D'},
+ { ACL_DELETE, "delete", 'd'},
+ { ACL_READ_ATTRIBUTES, "read_attributes", 'a'},
+ { ACL_WRITE_ATTRIBUTES, "write_attributes", 'A'},
+ { ACL_READ_NAMED_ATTRS, "read_xattr", 'R'},
+ { ACL_WRITE_NAMED_ATTRS, "write_xattr", 'W'},
+ { ACL_READ_ACL, "read_acl", 'c'},
+ { ACL_WRITE_ACL, "write_acl", 'C'},
+ { ACL_WRITE_OWNER, "write_owner", 'o'},
+ { ACL_SYNCHRONIZE, "synchronize", 's'},
+ { ACL_FULL_SET, "full_set", '\0'},
+ { ACL_MODIFY_SET, "modify_set", '\0'},
+ { ACL_READ_SET, "read_set", '\0'},
+ { ACL_WRITE_SET, "write_set", '\0'},
+ { 0, 0, 0}};
+
+static const char *
+format_flag(uint32_t *var, const struct flagnames_struct *flags)
+{
+
+ for (; flags->name != NULL; flags++) {
+ if ((flags->flag & *var) == 0)
+ continue;
+
+ *var &= ~flags->flag;
+ return (flags->name);
+ }
+
+ return (NULL);
+}
+
+static int
+format_flags_verbose(char *str, size_t size, uint32_t var,
+ const struct flagnames_struct *flags)
+{
+ size_t off = 0;
+ const char *tmp;
+
+ while ((tmp = format_flag(&var, flags)) != NULL) {
+ off += snprintf(str + off, size - off, "%s/", tmp);
+ assert (off < size);
+ }
+
+ /* If there were any flags added... */
+ if (off > 0) {
+ off--;
+ /* ... then remove the last slash. */
+ assert(str[off] == '/');
+ }
+
+ str[off] = '\0';
+
+ return (0);
+}
+
+static int
+format_flags_compact(char *str, size_t size, uint32_t var,
+ const struct flagnames_struct *flags)
+{
+ size_t i;
+
+ for (i = 0; flags[i].letter != '\0'; i++) {
+ assert(i < size);
+ if ((flags[i].flag & var) == 0)
+ str[i] = '-';
+ else
+ str[i] = flags[i].letter;
+ }
+
+ str[i] = '\0';
+
+ return (0);
+}
+
+static int
+parse_flags_verbose(const char *strp, uint32_t *var,
+ const struct flagnames_struct *flags, const char *flags_name,
+ int *try_compact)
+{
+ int i, found, ever_found = 0;
+ char *str, *flag;
+
+ str = strdup(strp);
+ *try_compact = 0;
+ *var = 0;
+
+ while (str != NULL) {
+ flag = strsep(&str, "/:");
+
+ found = 0;
+ for (i = 0; flags[i].name != NULL; i++) {
+ if (strcmp(flags[i].name, flag) == 0) {
+ *var |= flags[i].flag;
+ found = 1;
+ ever_found = 1;
+ }
+ }
+
+ if (!found) {
+ if (ever_found)
+ warnx("malformed ACL: \"%s\" field contains "
+ "invalid flag \"%s\"", flags_name, flag);
+ else
+ *try_compact = 1;
+ free(str);
+ return (-1);
+ }
+ }
+
+ free(str);
+ return (0);
+}
+
+static int
+parse_flags_compact(const char *str, uint32_t *var,
+ const struct flagnames_struct *flags, const char *flags_name)
+{
+ int i, j, found;
+
+ *var = 0;
+
+ for (i = 0;; i++) {
+ if (str[i] == '\0')
+ return (0);
+
+ /* Ignore minus signs. */
+ if (str[i] == '-')
+ continue;
+
+ found = 0;
+
+ for (j = 0; flags[j].name != NULL; j++) {
+ if (flags[j].letter == str[i]) {
+ *var |= flags[j].flag;
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ warnx("malformed ACL: \"%s\" field contains "
+ "invalid flag \"%c\"", flags_name, str[i]);
+ return (-1);
+ }
+ }
+}
+
+int
+_nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose)
+{
+
+ if (verbose)
+ return (format_flags_verbose(str, size, var, a_flags));
+
+ return (format_flags_compact(str, size, var, a_flags));
+}
+
+int
+_nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose)
+{
+
+ if (verbose)
+ return (format_flags_verbose(str, size, var, a_access_masks));
+
+ return (format_flags_compact(str, size, var, a_access_masks));
+}
+
+int
+_nfs4_parse_flags(const char *str, acl_flag_t *flags)
+{
+ int error, try_compact;
+ unsigned int tmpflags;
+
+ error = parse_flags_verbose(str, &tmpflags, a_flags, "flags", &try_compact);
+ if (error && try_compact)
+ error = parse_flags_compact(str, &tmpflags, a_flags, "flags");
+
+ *flags = tmpflags;
+
+ return (error);
+}
+
+int
+_nfs4_parse_access_mask(const char *str, acl_perm_t *perms)
+{
+ int error, try_compact;
+ unsigned int tmpperms;
+
+ error = parse_flags_verbose(str, &tmpperms, a_access_masks,
+ "access permissions", &try_compact);
+ if (error && try_compact)
+ error = parse_flags_compact(str, &tmpperms,
+ a_access_masks, "access permissions");
+
+ *perms = tmpperms;
+
+ return (error);
+}
diff --git a/lib/libc/posix1e/acl_to_text.3 b/lib/libc/posix1e/acl_to_text.3
new file mode 100644
index 00000000000..390de3c133c
--- /dev/null
+++ b/lib/libc/posix1e/acl_to_text.3
@@ -0,0 +1,159 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_to_text.3 318709 2017-05-23 07:12:31Z ngie $
+.\"
+.Dd June 25, 2009
+.Dt ACL_TO_TEXT 3
+.Os
+.Sh NAME
+.Nm acl_to_text ,
+.Nm acl_to_text_np
+.Nd convert an ACL to text
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft char *
+.Fn acl_to_text "acl_t acl" "ssize_t *len_p"
+.Ft char *
+.Fn acl_to_text_np "acl_t acl" "ssize_t *len_p" "int flags"
+.Sh DESCRIPTION
+The
+.Fn acl_to_text
+and
+.Fn acl_to_text_np
+functions translate the ACL pointed to by argument
+.Va acl
+into a NULL terminated character string.
+If the pointer
+.Va len_p
+is not NULL, then the function shall return the length of the string (not
+including the NULL terminator) in the location pointed to by
+.Va len_p .
+If the ACL is POSIX.1e, the format of the text string returned by
+.Fn acl_to_text
+shall be the POSIX.1e long ACL form.
+If the ACL is NFSv4, the format of the text string shall be the compact form, unless
+the
+.Va ACL_TEXT_VERBOSE
+flag is given.
+.Pp
+The flags specified are formed by
+.Em or Ns 'ing
+the following values
+.Bl -column -offset 3n "ACL_TEXT_NUMERIC_IDS"
+.It ACL_TEXT_VERBOSE Ta "Format ACL using verbose form"
+.It ACL_TEXT_NUMERIC_IDS Ta "Do not resolve IDs into user or group names"
+.It ACL_TEXT_APPEND_ID Ta "In addition to user and group names, append numeric IDs"
+.El
+.Pp
+This function allocates any memory necessary to contain the string and
+returns a pointer to the string.
+The caller should free any releasable
+memory, when the new string is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void*)char
+as an argument.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+Upon successful completion, the function shall return a pointer to the
+long text form of an ACL.
+Otherwise, a value of
+.Va (char*)NULL
+shall be returned and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_to_text
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Va acl
+does not point to a valid ACL.
+.Pp
+The ACL denoted by
+.Va acl
+contains one or more improperly formed ACL entries, or for some other
+reason cannot be translated into a text form of an ACL.
+.It Bq Er ENOMEM
+The character string to be returned requires more memory than is allowed
+by the hardware or software-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_free 3 ,
+.Xr acl_from_text 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
+.Sh BUGS
+The
+.Fn acl_from_text
+and
+.Fn acl_to_text
+functions
+rely on the
+.Xr getpwent 3
+library calls to manage username and uid mapping, as well as the
+.Xr getgrent 3
+library calls to manage groupname and gid mapping.
+These calls are not
+thread safe, and so transitively, neither are
+.Fn acl_from_text
+and
+.Fn acl_to_text .
+These functions may also interfere with stateful
+calls associated with the
+.Fn getpwent
+and
+.Fn getgrent
+calls.
diff --git a/lib/libc/posix1e/acl_to_text.c b/lib/libc/posix1e/acl_to_text.c
new file mode 100644
index 00000000000..70fa7374e62
--- /dev/null
+++ b/lib/libc/posix1e/acl_to_text.c
@@ -0,0 +1,267 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999-2002 Robert N. M. Watson
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * acl_to_text - return a text string with a text representation of the acl
+ * in it.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_to_text.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_to_text.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "acl_support.h"
+
+/*
+ * acl_to_text - generate a text form of an acl
+ * spec says nothing about output ordering, so leave in acl order
+ *
+ * This function will not produce nice results if it is called with
+ * a non-POSIX.1e semantics ACL.
+ */
+
+char *_nfs4_acl_to_text_np(const acl_t acl, ssize_t *len_p, int flags);
+
+static char *
+_posix1e_acl_to_text(acl_t acl, ssize_t *len_p, int flags)
+{
+ struct acl *acl_int;
+ char *buf, *tmpbuf;
+ char name_buf[MAXLOGNAME];
+ char perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1],
+ effective_perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1];
+ size_t i;
+ int error, len;
+ uid_t ae_id;
+ acl_tag_t ae_tag;
+ acl_perm_t ae_perm, effective_perm, mask_perm;
+
+ buf = strdup("");
+ if (buf == NULL)
+ return(NULL);
+
+ acl_int = &acl->ats_acl;
+
+ mask_perm = ACL_PERM_BITS; /* effective is regular if no mask */
+ for (i = 0; i < acl_int->acl_cnt; i++)
+ if (acl_int->acl_entry[i].ae_tag == ACL_MASK)
+ mask_perm = acl_int->acl_entry[i].ae_perm;
+
+ for (i = 0; i < acl_int->acl_cnt; i++) {
+ ae_tag = acl_int->acl_entry[i].ae_tag;
+ ae_id = acl_int->acl_entry[i].ae_id;
+ ae_perm = acl_int->acl_entry[i].ae_perm;
+
+ switch(ae_tag) {
+ case ACL_USER_OBJ:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+ len = asprintf(&tmpbuf, "%suser::%s\n", buf,
+ perm_buf);
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ case ACL_USER:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+
+ error = _posix1e_acl_id_to_name(ae_tag, ae_id,
+ MAXLOGNAME, name_buf, flags);
+ if (error)
+ goto error_label;
+
+ effective_perm = ae_perm & mask_perm;
+ if (effective_perm != ae_perm) {
+ error = _posix1e_acl_perm_to_string(
+ effective_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
+ effective_perm_buf);
+ if (error)
+ goto error_label;
+ len = asprintf(&tmpbuf, "%suser:%s:%s\t\t# "
+ "effective: %s\n",
+ buf, name_buf, perm_buf,
+ effective_perm_buf);
+ } else {
+ len = asprintf(&tmpbuf, "%suser:%s:%s\n", buf,
+ name_buf, perm_buf);
+ }
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ case ACL_GROUP_OBJ:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+
+ effective_perm = ae_perm & mask_perm;
+ if (effective_perm != ae_perm) {
+ error = _posix1e_acl_perm_to_string(
+ effective_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
+ effective_perm_buf);
+ if (error)
+ goto error_label;
+ len = asprintf(&tmpbuf, "%sgroup::%s\t\t# "
+ "effective: %s\n",
+ buf, perm_buf, effective_perm_buf);
+ } else {
+ len = asprintf(&tmpbuf, "%sgroup::%s\n", buf,
+ perm_buf);
+ }
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ case ACL_GROUP:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+
+ error = _posix1e_acl_id_to_name(ae_tag, ae_id,
+ MAXLOGNAME, name_buf, flags);
+ if (error)
+ goto error_label;
+
+ effective_perm = ae_perm & mask_perm;
+ if (effective_perm != ae_perm) {
+ error = _posix1e_acl_perm_to_string(
+ effective_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
+ effective_perm_buf);
+ if (error)
+ goto error_label;
+ len = asprintf(&tmpbuf, "%sgroup:%s:%s\t\t# "
+ "effective: %s\n",
+ buf, name_buf, perm_buf,
+ effective_perm_buf);
+ } else {
+ len = asprintf(&tmpbuf, "%sgroup:%s:%s\n", buf,
+ name_buf, perm_buf);
+ }
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ case ACL_MASK:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+
+ len = asprintf(&tmpbuf, "%smask::%s\n", buf,
+ perm_buf);
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ case ACL_OTHER:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+
+ len = asprintf(&tmpbuf, "%sother::%s\n", buf,
+ perm_buf);
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ default:
+ errno = EINVAL;
+ goto error_label;
+ }
+ }
+
+ if (len_p) {
+ *len_p = strlen(buf);
+ }
+ return (buf);
+
+error_label:
+ /* jump to here sets errno already, we just clean up */
+ if (buf) free(buf);
+ return (NULL);
+}
+
+char *
+acl_to_text_np(acl_t acl, ssize_t *len_p, int flags)
+{
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return(NULL);
+ }
+
+ switch (_acl_brand(acl)) {
+ case ACL_BRAND_POSIX:
+ return (_posix1e_acl_to_text(acl, len_p, flags));
+ case ACL_BRAND_NFS4:
+ return (_nfs4_acl_to_text_np(acl, len_p, flags));
+ default:
+ errno = EINVAL;
+ return (NULL);
+ }
+}
+
+char *
+acl_to_text(acl_t acl, ssize_t *len_p)
+{
+
+ return (acl_to_text_np(acl, len_p, 0));
+}
diff --git a/lib/libc/posix1e/acl_to_text_nfs4.c b/lib/libc/posix1e/acl_to_text_nfs4.c
new file mode 100644
index 00000000000..f31cfb44a2b
--- /dev/null
+++ b/lib/libc/posix1e/acl_to_text_nfs4.c
@@ -0,0 +1,271 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_to_text_nfs4.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_to_text_nfs4.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+#define MAX_ENTRY_LENGTH 512
+
+static int
+format_who(char *str, size_t size, const acl_entry_t entry, int numeric)
+{
+ int error;
+ acl_tag_t tag;
+ struct passwd *pwd;
+ struct group *grp;
+ uid_t *id;
+
+ error = acl_get_tag_type(entry, &tag);
+ if (error)
+ return (error);
+
+ switch (tag) {
+ case ACL_USER_OBJ:
+ snprintf(str, size, "owner@");
+ break;
+
+ case ACL_USER:
+ id = (uid_t *)acl_get_qualifier(entry);
+ if (id == NULL)
+ return (-1);
+ /* XXX: Thread-unsafe. */
+ if (!numeric)
+ pwd = getpwuid(*id);
+ else
+ pwd = NULL;
+ if (pwd == NULL)
+ snprintf(str, size, "user:%d", (unsigned int)*id);
+ else
+ snprintf(str, size, "user:%s", pwd->pw_name);
+ break;
+
+ case ACL_GROUP_OBJ:
+ snprintf(str, size, "group@");
+ break;
+
+ case ACL_GROUP:
+ id = (uid_t *)acl_get_qualifier(entry);
+ if (id == NULL)
+ return (-1);
+ /* XXX: Thread-unsafe. */
+ if (!numeric)
+ grp = getgrgid(*id);
+ else
+ grp = NULL;
+ if (grp == NULL)
+ snprintf(str, size, "group:%d", (unsigned int)*id);
+ else
+ snprintf(str, size, "group:%s", grp->gr_name);
+ break;
+
+ case ACL_EVERYONE:
+ snprintf(str, size, "everyone@");
+ break;
+
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+format_entry_type(char *str, size_t size, const acl_entry_t entry)
+{
+ int error;
+ acl_entry_type_t entry_type;
+
+ error = acl_get_entry_type_np(entry, &entry_type);
+ if (error)
+ return (error);
+
+ switch (entry_type) {
+ case ACL_ENTRY_TYPE_ALLOW:
+ snprintf(str, size, "allow");
+ break;
+ case ACL_ENTRY_TYPE_DENY:
+ snprintf(str, size, "deny");
+ break;
+ case ACL_ENTRY_TYPE_AUDIT:
+ snprintf(str, size, "audit");
+ break;
+ case ACL_ENTRY_TYPE_ALARM:
+ snprintf(str, size, "alarm");
+ break;
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+format_additional_id(char *str, size_t size, const acl_entry_t entry)
+{
+ int error;
+ acl_tag_t tag;
+ uid_t *id;
+
+ error = acl_get_tag_type(entry, &tag);
+ if (error)
+ return (error);
+
+ switch (tag) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_EVERYONE:
+ str[0] = '\0';
+ break;
+
+ default:
+ id = (uid_t *)acl_get_qualifier(entry);
+ if (id == NULL)
+ return (-1);
+ snprintf(str, size, ":%d", (unsigned int)*id);
+ }
+
+ return (0);
+}
+
+static int
+format_entry(char *str, size_t size, const acl_entry_t entry, int flags)
+{
+ size_t off = 0, min_who_field_length = 18;
+ acl_permset_t permset;
+ acl_flagset_t flagset;
+ int error;
+ unsigned int len;
+ char buf[MAX_ENTRY_LENGTH + 1];
+
+ assert(_entry_brand(entry) == ACL_BRAND_NFS4);
+
+ error = acl_get_flagset_np(entry, &flagset);
+ if (error)
+ return (error);
+
+ error = acl_get_permset(entry, &permset);
+ if (error)
+ return (error);
+
+ error = format_who(buf, sizeof(buf), entry,
+ flags & ACL_TEXT_NUMERIC_IDS);
+ if (error)
+ return (error);
+ len = strlen(buf);
+ if (len < min_who_field_length)
+ len = min_who_field_length;
+ off += snprintf(str + off, size - off, "%*s:", len, buf);
+
+ error = _nfs4_format_access_mask(buf, sizeof(buf), *permset,
+ flags & ACL_TEXT_VERBOSE);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s:", buf);
+
+ error = _nfs4_format_flags(buf, sizeof(buf), *flagset,
+ flags & ACL_TEXT_VERBOSE);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s:", buf);
+
+ error = format_entry_type(buf, sizeof(buf), entry);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s", buf);
+
+ if (flags & ACL_TEXT_APPEND_ID) {
+ error = format_additional_id(buf, sizeof(buf), entry);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s", buf);
+ }
+
+ off += snprintf(str + off, size - off, "\n");
+
+ /* Make sure we didn't truncate anything. */
+ assert (off < size);
+
+ return (0);
+}
+
+char *
+_nfs4_acl_to_text_np(const acl_t aclp, ssize_t *len_p, int flags)
+{
+ int error, off = 0, size, entry_id = ACL_FIRST_ENTRY;
+ char *str;
+ acl_entry_t entry;
+
+ if (aclp->ats_acl.acl_cnt == 0)
+ return strdup("");
+
+ size = aclp->ats_acl.acl_cnt * MAX_ENTRY_LENGTH;
+ str = malloc(size);
+ if (str == NULL)
+ return (NULL);
+
+ while (acl_get_entry(aclp, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+
+ assert(off < size);
+
+ error = format_entry(str + off, size - off, entry, flags);
+ if (error) {
+ free(str);
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ off = strlen(str);
+ }
+
+ assert(off < size);
+ str[off] = '\0';
+
+ if (len_p != NULL)
+ *len_p = off;
+
+ return (str);
+}
diff --git a/lib/libc/posix1e/acl_valid.3 b/lib/libc/posix1e/acl_valid.3
new file mode 100644
index 00000000000..1716059ba1b
--- /dev/null
+++ b/lib/libc/posix1e/acl_valid.3
@@ -0,0 +1,170 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/acl_valid.3 140288 2005-01-15 12:21:03Z ru $
+.\"
+.Dd December 29, 2002
+.Dt ACL_VALID 3
+.Os
+.Sh NAME
+.Nm acl_valid ,
+.Nm acl_valid_fd_np ,
+.Nm acl_valid_file_np ,
+.Nm acl_valid_link_np
+.Nd validate an ACL
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_valid "acl_t acl"
+.Ft int
+.Fn acl_valid_fd_np "int fd" "acl_type_t type" "acl_t acl"
+.Ft int
+.Fn acl_valid_file_np "const char *path_p" "acl_type_t type" "acl_t acl"
+.Ft int
+.Fn acl_valid_link_np "const char *path_p" "acl_type_t type" "acl_t acl"
+.Sh DESCRIPTION
+These functions check that the ACL referred to by the argument
+.Va acl
+is valid.
+The POSIX.1e routine,
+.Fn acl_valid ,
+checks this validity only with POSIX.1e ACL semantics, and irrespective
+of the context in which the ACL is to be used.
+The non-portable forms,
+.Fn acl_valid_fd_np ,
+.Fn acl_valid_file_np ,
+and
+.Fn acl_valid_link_np
+allow an ACL to be checked in the context of a specific acl type,
+.Va type ,
+and file system object.
+In environments where additional ACL types are
+supported than just POSIX.1e, this makes more sense.
+Whereas
+.Fn acl_valid_file_np
+will follow the symlink if the specified path is to a symlink,
+.Fn acl_valid_link_np
+will not.
+.Pp
+For POSIX.1e semantics, the checks include:
+.Bl -bullet
+.It
+The three required entries
+.Dv ( ACL_USER_OBJ , ACL_GROUP_OBJ ,
+and
+.Dv ACL_OTHER )
+shall exist exactly once in the ACL.
+If the ACL contains any
+.Dv ACL_USER , ACL_GROUP ,
+or any other
+implementation-defined entries in the file group class
+then one
+.Dv ACL_MASK
+entry shall also be required.
+The ACL shall contain at most one
+.Dv ACL_MASK
+entry.
+.It
+The qualifier field shall be unique among all entries of
+the same POSIX.1e ACL facility defined tag type.
+The
+tag type field shall contain valid values including any
+implementation-defined values.
+Validation of the values
+of the qualifier field is implementation-defined.
+.El
+.Pp
+The POSIX.1e
+.Fn acl_valid
+function may reorder the ACL for the purposes of verification; the
+non-portable validation functions will not.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+If any of the following conditions occur, these functions shall return
+-1 and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EACCES
+Search permission is denied for a component of the path prefix, or the
+object exists and the process does not have appropriate access rights.
+.It Bq Er EBADF
+The
+.Va fd
+argument is not a valid file descriptor.
+.It Bq Er EINVAL
+Argument
+.Va acl
+does not point to a valid ACL.
+.Pp
+One or more of the required ACL entries is not present in
+.Va acl .
+.Pp
+The ACL contains entries that are not unique.
+.Pp
+The file system rejects the ACL based on fs-specific semantics issues.
+.It Bq Er ENAMETOOLONG
+A component of a pathname exceeded 255 characters, or an
+entire path name exceeded 1023 characters.
+.It Bq Er ENOENT
+The named object does not exist, or the
+.Va path_p
+argument points to an empty string.
+.It Bq Er ENOMEM
+Insufficient memory available to fulfill request.
+.It Bq Er EOPNOTSUPP
+The file system does not support ACL retrieval.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get 3 ,
+.Xr acl_init 3 ,
+.Xr acl_set 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_valid.c b/lib/libc/posix1e/acl_valid.c
new file mode 100644
index 00000000000..a085b9668db
--- /dev/null
+++ b/lib/libc/posix1e/acl_valid.c
@@ -0,0 +1,129 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * acl_valid -- POSIX.1e ACL check routine
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_valid.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: acl_valid.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "acl_support.h"
+
+/*
+ * acl_valid: accepts an ACL, returns 0 on valid ACL, -1 for invalid,
+ * and errno set to EINVAL.
+ *
+ * Implemented by calling the acl_check routine in acl_support, which
+ * requires ordering. We call acl_support's _posix1e_acl_sort to make this
+ * true. POSIX.1e allows acl_valid() to reorder the ACL as it sees fit.
+ *
+ * This call is deprecated, as it doesn't ask whether the ACL is valid
+ * for a particular target. However, this call is standardized, unlike
+ * the other two forms.
+ */
+int
+acl_valid(acl_t acl)
+{
+ int error;
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (!_acl_brand_may_be(acl, ACL_BRAND_POSIX)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _posix1e_acl_sort(acl);
+ error = _posix1e_acl_check(acl);
+ if (error) {
+ errno = error;
+ return (-1);
+ } else {
+ return (0);
+ }
+}
+
+int
+acl_valid_file_np(const char *pathp, acl_type_t type, acl_t acl)
+{
+
+ if (pathp == NULL || acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ return (__acl_aclcheck_file(pathp, type, &acl->ats_acl));
+}
+
+int
+acl_valid_link_np(const char *pathp, acl_type_t type, acl_t acl)
+{
+
+ if (pathp == NULL || acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ return (__acl_aclcheck_link(pathp, type, &acl->ats_acl));
+}
+
+int
+acl_valid_fd_np(int fd, acl_type_t type, acl_t acl)
+{
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ acl->ats_cur_entry = 0;
+
+ return (__acl_aclcheck_fd(fd, type, &acl->ats_acl));
+}
diff --git a/lib/libc/posix1e/extattr.3 b/lib/libc/posix1e/extattr.3
new file mode 100644
index 00000000000..47d8b68e455
--- /dev/null
+++ b/lib/libc/posix1e/extattr.3
@@ -0,0 +1,100 @@
+.\"
+.\" Copyright (c) 2001 Dima Dorfman <dd@FreeBSD.org>
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/extattr.3 107788 2002-12-12 17:26:04Z ru $
+.\"
+.Dd June 24, 2001
+.Dt EXTATTR 3
+.Os
+.Sh NAME
+.Nm extattr_namespace_to_string ,
+.Nm extattr_string_to_namespace
+.Nd convert an extended attribute namespace identifier to a string and
+vice versa
+.Sh LIBRARY
+.Lb libutil
+.Sh SYNOPSIS
+.In sys/extattr.h
+.In libutil.h
+.Ft int
+.Fn extattr_namespace_to_string "int attrnamespace" "char **string"
+.Ft int
+.Fn extattr_string_to_namespace "const char *string" "int *attrnamespace"
+.Sh DESCRIPTION
+The
+.Fn extattr_namespace_to_string
+function converts a VFS extended attribute identifier to a human-readable
+string;
+the
+.Fn extattr_string_to_namespace
+function undoes the aforementioned operation,
+and converts a human-readable string representing a namespace to a
+namespace identifier.
+Although a file system may implement arbitrary namespaces,
+these functions only support the
+.Dv EXTATTR_NAMESPACE_USER
+.Pq Dq user
+and
+.Dv EXTATTR_NAMESPACE_SYSTEM
+.Pq Dq system
+namespaces,
+which are defined in
+.Xr extattr 9 .
+.Pp
+These functions are meant to be used in error reporting and other
+interactive tasks.
+For example,
+instead of printing the integer identifying an extended attribute in
+an error message,
+a program might use
+.Fn extattr_namespace_to_string
+to obtain a human-readable representation.
+Likewise,
+instead of requiring a user to enter the integer representing a namespace,
+an interactive program might ask for a name and use
+.Fn extattr_string_to_namespace
+to get the desired identifier.
+.Sh RETURN VALUES
+If any of the calls are unsuccessful, the value \-1 is returned
+and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The requested namespace could not be identified.
+.El
+.Sh SEE ALSO
+.Xr extattr 2 ,
+.Xr getextattr 8 ,
+.Xr setextattr 8 ,
+.Xr extattr 9
+.Sh HISTORY
+Extended attribute support was developed as part of the
+.Tn TrustedBSD
+Project, and introduced in
+.Fx 5.0 .
+It was developed to support security extensions requiring additional labels
+to be associated with each file or directory.
diff --git a/lib/libc/posix1e/extattr.c b/lib/libc/posix1e/extattr.c
new file mode 100644
index 00000000000..d76d1d369b5
--- /dev/null
+++ b/lib/libc/posix1e/extattr.c
@@ -0,0 +1,83 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2001 Robert N. M. Watson
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * TrustedBSD: Utility functions for extended attributes.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/lib/libc/posix1e/extattr.c 326193 2017-11-25 17:12:48Z pfg $");
+#else
+__RCSID("$NetBSD: extattr.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/extattr.h>
+
+#include <errno.h>
+#include <libutil.h>
+#include <string.h>
+
+int
+extattr_namespace_to_string(int attrnamespace, char **string)
+{
+
+ switch(attrnamespace) {
+ case EXTATTR_NAMESPACE_USER:
+ if (string != NULL)
+ *string = strdup(EXTATTR_NAMESPACE_USER_STRING);
+ return (0);
+
+ case EXTATTR_NAMESPACE_SYSTEM:
+ if (string != NULL)
+ *string = strdup(EXTATTR_NAMESPACE_SYSTEM_STRING);
+ return (0);
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+}
+
+int
+extattr_string_to_namespace(const char *string, int *attrnamespace)
+{
+
+ if (!strcmp(string, EXTATTR_NAMESPACE_USER_STRING)) {
+ if (attrnamespace != NULL)
+ *attrnamespace = EXTATTR_NAMESPACE_USER;
+ return (0);
+ } else if (!strcmp(string, EXTATTR_NAMESPACE_SYSTEM_STRING)) {
+ if (attrnamespace != NULL)
+ *attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
+ return (0);
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+}
diff --git a/lib/libc/posix1e/posix1e.3 b/lib/libc/posix1e/posix1e.3
new file mode 100644
index 00000000000..69bca7480a0
--- /dev/null
+++ b/lib/libc/posix1e/posix1e.3
@@ -0,0 +1,118 @@
+.\"-
+.\" Copyright (c) 2000, 2009 Robert N. M. Watson
+.\" 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.
+.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/lib/libc/posix1e/posix1e.3 318704 2017-05-23 07:05:34Z ngie $
+.\"
+.Dd February 25, 2016
+.Dt POSIX1E 3
+.Os
+.Sh NAME
+.Nm posix1e
+.Nd introduction to the POSIX.1e security API
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.In sys/mac.h
+.Sh DESCRIPTION
+POSIX.1e describes five security extensions to the POSIX.1 API: Access
+Control Lists (ACLs), Auditing, Capabilities, Mandatory Access Control, and
+Information Flow Labels.
+While IEEE POSIX.1e D17 specification has not been standardized, several of
+its interfaces are widely used.
+.Pp
+.Fx
+implements POSIX.1e interface for access control lists, described in
+.Xr acl 3 ,
+and supports ACLs on the
+.Xr ffs 7
+file system; ACLs must be administratively enabled using
+.Xr tunefs 8 .
+.Pp
+.Fx
+implements a POSIX.1e-like mandatory access control interface, described in
+.Xr mac 3 ,
+although with a number of extensions and important semantic differences.
+.Pp
+.Fx
+does not implement the POSIX.1e audit, privilege (capability), or information
+flow label APIs.
+However,
+.Fx
+does implement the
+.Xr libbsm 3
+audit API.
+It also provides
+.Xr capsicum 4 ,
+a lightweight OS capability and sandbox framework implementing a
+hybrid capability system model.
+.Sh ENVIRONMENT
+POSIX.1e assigns security attributes to all objects, extending the security
+functionality described in POSIX.1.
+These additional attributes store fine-grained discretionary access control
+information and mandatory access control labels; for files, they are stored
+in extended attributes, described in
+.Xr extattr 3 .
+.Pp
+POSIX.2c describes
+a set of userland utilities for manipulating these attributes, including
+.Xr getfacl 1
+and
+.Xr setfacl 1
+for access control lists, and
+.Xr getfmac 8
+and
+.Xr setfmac 8
+for mandatory access control labels.
+.Sh SEE ALSO
+.Xr getfacl 1 ,
+.Xr setfacl 1 ,
+.Xr extattr 2 ,
+.Xr acl 3 ,
+.Xr extattr 3 ,
+.Xr libbsm 3 ,
+.Xr libcasper 3 ,
+.Xr mac 3 ,
+.Xr capsicum 4 ,
+.Xr ffs 7 ,
+.Xr getfmac 8 ,
+.Xr setfmac 8 ,
+.Xr tunefs 8 ,
+.Xr acl 9 ,
+.Xr extattr 9 ,
+.Xr mac 9
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ;
+most features were available as of
+.Fx 5.0 .
+.Sh AUTHORS
+.An Robert N M Watson
+.An Chris D. Faulhaber
+.An Thomas Moestl
+.An Ilmar S Habibulin
diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
index 7eddf7e3fc1..83e3bbc523f 100644
--- a/lib/libc/sys/Makefile.inc
+++ b/lib/libc/sys/Makefile.inc
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.inc,v 1.242 2019/09/22 22:59:38 christos Exp $
+# $NetBSD: Makefile.inc,v 1.243 2020/05/16 18:31:47 christos Exp $
# @(#)Makefile.inc 8.3 (Berkeley) 10/24/94
# sys sources
@@ -89,8 +89,13 @@ ASM_GLUE+= tmp___${glue:.c=}50.S
.endfor
# modules with default implementations on all architectures:
-ASM= access.S acct.S \
- bind.S \
+ASM=\
+ __acl_get_link.S __acl_set_link.S __acl_delete_link.S \
+ __acl_aclcheck_link.S __acl_get_file.S __acl_set_file.S __acl_get_fd.S \
+ __acl_set_fd.S __acl_delete_file.S __acl_delete_fd.S \
+ __acl_aclcheck_file.S __acl_aclcheck_fd.S \
+ access.S acct.S \
+ bind.S \
chdir.S chflags.S chmod.S chown.S chroot.S clock_nanosleep.S \
clock_getcpuclockid2.S \
__clock_getres50.S __clock_gettime50.S \
@@ -118,6 +123,7 @@ ASM= access.S acct.S \
_ksem_post.S _ksem_timedwait.S _ksem_trywait.S _ksem_unlink.S \
_ksem_wait.S _ksem_open.S \
lchflags.S lchmod.S lchown.S lfs_bmapv.S lfs_markv.S lfs_segclean.S \
+ lpathconf.S \
__lfs_segwait50.S link.S linkat.S listen.S __lstat50.S \
__lutimes50.S _lwp_create.S _lwp_exit.S _lwp_kill.S \
___lwp_park60.S _lwp_self.S _lwp_wait.S _lwp_unpark.S \
diff --git a/lib/libc/sys/makelintstub b/lib/libc/sys/makelintstub
index cdf2600a0c1..928d032f535 100755
--- a/lib/libc/sys/makelintstub
+++ b/lib/libc/sys/makelintstub
@@ -1,5 +1,5 @@
#!/bin/sh -
-# $NetBSD: makelintstub,v 1.26 2016/04/03 00:48:29 christos Exp $
+# $NetBSD: makelintstub,v 1.27 2020/05/16 18:31:47 christos Exp $
#
# Copyright (c) 1996, 1997 Christopher G. Demetriou
# All rights reserved.
@@ -60,6 +60,7 @@ header()
*/
#include <sys/param.h>
+ #include <sys/acl.h>
#include <sys/aio.h>
#include <sys/time.h>
#include <sys/mount.h>
diff --git a/sbin/mount_ffs/mount_ffs.c b/sbin/mount_ffs/mount_ffs.c
index 09930941f4a..c10f9ca76a3 100644
--- a/sbin/mount_ffs/mount_ffs.c
+++ b/sbin/mount_ffs/mount_ffs.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mount_ffs.c,v 1.28 2012/10/19 17:09:07 drochner Exp $ */
+/* $NetBSD: mount_ffs.c,v 1.29 2020/05/16 18:31:47 christos Exp $ */
/*-
* Copyright (c) 1993, 1994
@@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1993, 1994\
#if 0
static char sccsid[] = "@(#)mount_ufs.c 8.4 (Berkeley) 4/26/95";
#else
-__RCSID("$NetBSD: mount_ffs.c,v 1.28 2012/10/19 17:09:07 drochner Exp $");
+__RCSID("$NetBSD: mount_ffs.c,v 1.29 2020/05/16 18:31:47 christos Exp $");
#endif
#endif /* not lint */
@@ -64,6 +64,8 @@ __dead static void ffs_usage(void);
static const struct mntopt mopts[] = {
MOPT_STDOPTS,
+ MOPT_ACLS,
+ MOPT_POSIX1EACLS,
MOPT_ASYNC,
MOPT_SYNC,
MOPT_UPDATE,
diff --git a/sbin/tunefs/tunefs.8 b/sbin/tunefs/tunefs.8
index 31b47cdac6f..5cef38d8dc6 100644
--- a/sbin/tunefs/tunefs.8
+++ b/sbin/tunefs/tunefs.8
@@ -1,4 +1,4 @@
-.\" $NetBSD: tunefs.8,v 1.44 2014/08/09 10:41:05 wiz Exp $
+.\" $NetBSD: tunefs.8,v 1.45 2020/05/16 18:31:47 christos Exp $
.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" @(#)tunefs.8 8.3 (Berkeley) 5/3/95
.\"
-.Dd August 9, 2014
+.Dd April 7, 2020
.Dt TUNEFS 8
.Os
.Sh NAME
@@ -38,11 +38,13 @@
.Sh SYNOPSIS
.Nm
.Op Fl AFN
+.Op Fl a Cm enable | disable
.Op Fl e Ar maxbpg
.Op Fl g Ar avgfilesize
.Op Fl h Ar avgfpdir
.Op Fl l Ar logsize
.Op Fl m Ar minfree
+.Op Fl n Cm enable | disable
.Op Fl o Ar optimize_preference
.Op Fl q Ar quota
.Op Fl S Ar sectorsize
@@ -78,6 +80,8 @@ will be accessed
Display all the settable options
(after any changes from the tuning options)
but do not cause any of them to be changed.
+.It Fl a Cm enable | disable
+Turn on/off the administrative NFSv4 ACL enable flag.
.It Fl e Ar maxbpg
This indicates the maximum number of blocks any single file can
allocate out of a cylinder group before it is forced to begin
@@ -130,6 +134,8 @@ running out of full sized blocks.
For values of minfree greater than or equal to 5%,
fragmentation is unlikely to be problematical, and
the file system can be optimized for time.
+.It Fl p Cm enable | disable
+Turn on/off the administrative POSIX.1e ACL enable flag.
.Pp
.Ar optimize_preference
can be specified as either
diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c
index a0a7382b0c1..5f3481d3061 100644
--- a/sbin/tunefs/tunefs.c
+++ b/sbin/tunefs/tunefs.c
@@ -1,4 +1,4 @@
-/* $NetBSD: tunefs.c,v 1.51 2020/04/09 14:44:38 christos Exp $ */
+/* $NetBSD: tunefs.c,v 1.52 2020/05/16 18:31:47 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
#if 0
static char sccsid[] = "@(#)tunefs.c 8.3 (Berkeley) 5/3/95";
#else
-__RCSID("$NetBSD: tunefs.c,v 1.51 2020/04/09 14:44:38 christos Exp $");
+__RCSID("$NetBSD: tunefs.c,v 1.52 2020/05/16 18:31:47 christos Exp $");
#endif
#endif /* not lint */
@@ -101,16 +101,18 @@ __dead static void usage(void);
int
main(int argc, char *argv[])
{
- int i, ch, Aflag, Fflag, Nflag, openflags;
+ int i, ch, aflag, pflag, Aflag, Fflag, Nflag, openflags;
const char *special, *chg[2];
char device[MAXPATHLEN];
int maxbpg, minfree, optim, secsize;
int avgfilesize, avgfpdir, active;
long long logfilesize;
int secshift, fsbtodb;
+ const char *avalue, *pvalue, *name;
struct statvfs sfs;
- Aflag = Fflag = Nflag = 0;
+ aflag = pflag = Aflag = Fflag = Nflag = 0;
+ avalue = pvalue = NULL;
maxbpg = minfree = optim = secsize = -1;
avgfilesize = avgfpdir = -1;
logfilesize = -1;
@@ -118,7 +120,7 @@ main(int argc, char *argv[])
chg[FS_OPTSPACE] = "space";
chg[FS_OPTTIME] = "time";
- while ((ch = getopt(argc, argv, "AFNe:g:h:l:m:o:q:S:")) != -1) {
+ while ((ch = getopt(argc, argv, "AFNa:e:g:h:l:m:o:p:q:S:")) != -1) {
switch (ch) {
case 'A':
@@ -133,6 +135,17 @@ main(int argc, char *argv[])
Nflag++;
break;
+ case 'a':
+ name = "ACLs";
+ avalue = optarg;
+ if (strcmp(avalue, "enable") &&
+ strcmp(avalue, "disable")) {
+ errx(10, "bad %s (options are %s)",
+ name, "`enable' or `disable'");
+ }
+ aflag = 1;
+ break;
+
case 'e':
maxbpg = strsuftoll(
"maximum blocks per file in a cylinder group",
@@ -170,6 +183,18 @@ main(int argc, char *argv[])
"bad %s (options are `space' or `time')",
"optimization preference");
break;
+
+ case 'p':
+ name = "POSIX1e ACLs";
+ pvalue = optarg;
+ if (strcmp(pvalue, "enable") &&
+ strcmp(pvalue, "disable")) {
+ errx(10, "bad %s (options are %s)",
+ name, "`enable' or `disable'");
+ }
+ pflag = 1;
+ break;
+
case 'q':
if (strcmp(optarg, "user") == 0)
userquota = Q2_EN;
@@ -182,6 +207,7 @@ main(int argc, char *argv[])
else
errx(11, "invalid quota type %s", optarg);
break;
+
case 'S':
secsize = strsuftoll("physical sector size",
optarg, 0, INT_MAX);
@@ -189,6 +215,7 @@ main(int argc, char *argv[])
if (secsize != 0 && 1 << secshift != secsize)
errx(12, "sector size %d is not a power of two", secsize);
break;
+
default:
usage();
}
@@ -330,9 +357,55 @@ main(int argc, char *argv[])
* if we disabled all quotas, FS_DOQUOTA2 and associated inode(s) will
* be cleared by kernel or fsck.
*/
+ if (aflag) {
+ name = "ACLs";
+ if (strcmp(avalue, "enable") == 0) {
+ if (sblock.fs_flags & FS_ACLS) {
+ warnx("%s remains unchanged as enabled", name);
+ } else if (sblock.fs_flags & FS_POSIX1EACLS) {
+ warnx("%s and POSIX.1e ACLs are mutually "
+ "exclusive", name);
+ } else {
+ sblock.fs_flags |= FS_ACLS;
+ printf("%s set\n", name);
+ }
+ } else if (strcmp(avalue, "disable") == 0) {
+ if ((~sblock.fs_flags & FS_ACLS) == FS_ACLS) {
+ warnx("%s remains unchanged as disabled",
+ name);
+ } else {
+ sblock.fs_flags &= ~FS_ACLS;
+ printf("%s cleared\n", name);
+ }
+ }
+ }
+
+ if (pflag) {
+ name = "POSIX1e ACLs";
+ if (strcmp(pvalue, "enable") == 0) {
+ if (sblock.fs_flags & FS_POSIX1EACLS) {
+ warnx("%s remains unchanged as enabled", name);
+ } else if (sblock.fs_flags & FS_ACLS) {
+ warnx("%s and ACLs are mutually "
+ "exclusive", name);
+ } else {
+ sblock.fs_flags |= FS_POSIX1EACLS;
+ printf("%s set", name);
+ }
+ } else if (strcmp(pvalue, "disable") == 0) {
+ if ((~sblock.fs_flags & FS_POSIX1EACLS) ==
+ FS_POSIX1EACLS) {
+ warnx("%s remains unchanged as disabled",
+ name);
+ } else {
+ sblock.fs_flags &= ~FS_POSIX1EACLS;
+ printf("%s cleared", name);
+ }
+ }
+ }
if (Nflag) {
- printf("tunefs: current settings of %s\n", special);
+ printf("%s: current settings of %s\n", getprogname(), special);
printf("\tmaximum contiguous block count %d\n",
sblock.fs_maxcontig);
printf("\tmaximum blocks per file in a cylinder group %d\n",
@@ -358,8 +431,12 @@ main(int argc, char *argv[])
} else {
printf(" disabled\n");
}
- printf("tunefs: no changes made\n");
- exit(0);
+ printf("\tPOSIX.1e ACLs %s\n",
+ (sblock.fs_flags & FS_POSIX1EACLS) ? "enabled" : "disabled");
+ printf("\tACLs %s\n",
+ (sblock.fs_flags & FS_ACLS) ? "enabled" : "disabled");
+ printf("%s: no changes made\n", getprogname());
+ return 0;
}
memcpy(&buf, (char *)&sblock, SBLOCKSIZE);
@@ -527,11 +604,13 @@ usage(void)
fprintf(stderr, "usage: tunefs [-AFN] tuneup-options special-device\n");
fprintf(stderr, "where tuneup-options are:\n");
+ fprintf(stderr, "\t-a ACLS: `enable' or `disable'\n");
fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
fprintf(stderr, "\t-g average file size\n");
fprintf(stderr, "\t-h expected number of files per directory\n");
fprintf(stderr, "\t-l journal log file size (`0' to clear journal)\n");
fprintf(stderr, "\t-m minimum percentage of free space\n");
+ fprintf(stderr, "\t-p POSIX.1e ACLS: `enable' or `disable'\n");
fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
fprintf(stderr, "\t-q quota type (`[no]user' or `[no]group')\n");
fprintf(stderr, "\t-S sector size\n");
diff --git a/sys/arch/amd64/amd64/genassym.cf b/sys/arch/amd64/amd64/genassym.cf
index d2ae3ccd274..c58f6150fb1 100644
--- a/sys/arch/amd64/amd64/genassym.cf
+++ b/sys/arch/amd64/amd64/genassym.cf
@@ -1,4 +1,4 @@
-# $NetBSD: genassym.cf,v 1.84 2020/05/02 16:44:34 bouyer Exp $
+# $NetBSD: genassym.cf,v 1.85 2020/05/16 18:31:47 christos Exp $
#
# Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -82,6 +82,7 @@ include <sys/rwlock.h>
include <sys/cpu_data.h>
include <sys/evcnt.h>
include <sys/cpu.h>
+include <sys/acl.h>
include <netinet/in.h>
include <netinet/in_systm.h>
diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
index 843638e8f42..50346814eca 100644
--- a/sys/arch/amd64/conf/GENERIC
+++ b/sys/arch/amd64/conf/GENERIC
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.567 2020/05/02 16:44:35 bouyer Exp $
+# $NetBSD: GENERIC,v 1.568 2020/05/16 18:31:48 christos Exp $
#
# GENERIC machine description file
#
@@ -22,7 +22,7 @@ include "arch/amd64/conf/std.amd64"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "GENERIC-$Revision: 1.567 $"
+#ident "GENERIC-$Revision: 1.568 $"
maxusers 64 # estimated number of users
@@ -197,6 +197,7 @@ options WAPBL # File system journaling support
# Note that UFS_DIRHASH is suspected of causing kernel memory corruption.
# It is not recommended for general use.
#options UFS_DIRHASH # UFS Large Directory Hashing - Experimental
+options UFS_ACL # UFS Access Control Lists
#options FFS_NO_SNAPSHOT # No FFS snapshot support
options UFS_EXTATTR # Extended attribute support for UFS1
# ext2fs
diff --git a/sys/coda/coda_vnops.c b/sys/coda/coda_vnops.c
index 335b983a182..383fdc72e2e 100644
--- a/sys/coda/coda_vnops.c
+++ b/sys/coda/coda_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: coda_vnops.c,v 1.111 2020/04/13 19:23:17 ad Exp $ */
+/* $NetBSD: coda_vnops.c,v 1.112 2020/05/16 18:31:48 christos Exp $ */
/*
*
@@ -46,7 +46,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: coda_vnops.c,v 1.111 2020/04/13 19:23:17 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: coda_vnops.c,v 1.112 2020/05/16 18:31:48 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -106,6 +106,7 @@ const struct vnodeopv_entry_desc coda_vnodeop_entries[] = {
{ &vop_open_desc, coda_open }, /* open */
{ &vop_close_desc, coda_close }, /* close */
{ &vop_access_desc, coda_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* access */
{ &vop_getattr_desc, coda_getattr }, /* getattr */
{ &vop_setattr_desc, coda_setattr }, /* setattr */
{ &vop_read_desc, coda_read }, /* read */
@@ -662,19 +663,20 @@ coda_access(void *v)
struct vop_access_args *ap = v;
vnode_t *vp = ap->a_vp;
struct cnode *cp = VTOC(vp);
- int mode = ap->a_mode;
+ accmode_t accmode = ap->a_accmode;
kauth_cred_t cred = ap->a_cred;
/* locals */
int error;
MARK_ENTRY(CODA_ACCESS_STATS);
+ KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND)) == 0);
/* Check for access of control object. Only read access is
allowed on it. */
if (IS_CTL_VP(vp)) {
/* bogus hack - all will be marked as successes */
MARK_INT_SAT(CODA_ACCESS_STATS);
- return(((mode & VREAD) && !(mode & (VWRITE | VEXEC)))
+ return(((accmode & VREAD) && !(accmode & (VWRITE | VEXEC)))
? 0 : EACCES);
}
@@ -684,7 +686,7 @@ coda_access(void *v)
* lookup access to it.
*/
if (coda_access_cache) {
- if ((vp->v_type == VDIR) && (mode & VEXEC)) {
+ if ((vp->v_type == VDIR) && (accmode & VEXEC)) {
if (coda_nc_lookup(cp, ".", 1, cred)) {
MARK_INT_SAT(CODA_ACCESS_STATS);
return(0); /* it was in the cache */
@@ -692,7 +694,7 @@ coda_access(void *v)
}
}
- error = venus_access(vtomi(vp), &cp->c_fid, mode, cred, curlwp);
+ error = venus_access(vtomi(vp), &cp->c_fid, accmode, cred, curlwp);
return(error);
}
diff --git a/sys/compat/netbsd32/files.netbsd32 b/sys/compat/netbsd32/files.netbsd32
index d02160b0d4f..d8294aefb21 100644
--- a/sys/compat/netbsd32/files.netbsd32
+++ b/sys/compat/netbsd32/files.netbsd32
@@ -1,4 +1,4 @@
-# $NetBSD: files.netbsd32,v 1.51 2020/04/26 18:53:33 thorpej Exp $
+# $NetBSD: files.netbsd32,v 1.52 2020/05/16 18:31:48 christos Exp $
#
# config file description for machine-independent netbsd32 compat code.
# included by ports that need it.
@@ -10,6 +10,7 @@ define compat_netbsd32
#makeoptions drmkms CPPFLAGS+="-DNETBSD32_DRMKMS"
+file compat/netbsd32/netbsd32_acl.c compat_netbsd32
file compat/netbsd32/netbsd32_core.c compat_netbsd32 & coredump
file compat/netbsd32/netbsd32_exec_elf32.c compat_netbsd32 & exec_elf32
file compat/netbsd32/netbsd32_exec_aout.c compat_netbsd32 & exec_aout
diff --git a/sys/compat/netbsd32/netbsd32.h b/sys/compat/netbsd32/netbsd32.h
index 491524d70a3..8ad5049d0ef 100644
--- a/sys/compat/netbsd32/netbsd32.h
+++ b/sys/compat/netbsd32/netbsd32.h
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32.h,v 1.132 2019/12/24 14:50:59 kamil Exp $ */
+/* $NetBSD: netbsd32.h,v 1.133 2020/05/16 18:31:48 christos Exp $ */
/*
* Copyright (c) 1998, 2001, 2008, 2015 Matthew R. Green
@@ -190,6 +190,7 @@ typedef netbsd32_pointer_t netbsd32_caddr_t;
typedef netbsd32_pointer_t netbsd32_lwpctlp;
typedef netbsd32_pointer_t netbsd32_pid_tp;
typedef netbsd32_pointer_t netbsd32_psetidp_t;
+typedef netbsd32_pointer_t netbsd32_aclp_t;
/*
* now, the compatibility structures and their fake pointer types.
diff --git a/sys/compat/netbsd32/netbsd32_acl.c b/sys/compat/netbsd32/netbsd32_acl.c
new file mode 100644
index 00000000000..5862c2dd2f9
--- /dev/null
+++ b/sys/compat/netbsd32/netbsd32_acl.c
@@ -0,0 +1,216 @@
+/* $NetBSD: netbsd32_acl.c,v 1.1 2020/05/16 18:31:48 christos Exp $ */
+
+/*-
+ * Copyright (c) 2020 The NetBSD Foundation.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_acl.c,v 1.1 2020/05/16 18:31:48 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/lwp.h>
+#include <sys/vnode.h>
+#include <sys/namei.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/acl.h>
+#include <sys/syscallargs.h>
+
+#include <compat/netbsd32/netbsd32.h>
+#include <compat/netbsd32/netbsd32_syscallargs.h>
+#include <compat/netbsd32/netbsd32_conv.h>
+
+/* Syscalls conversion */
+int
+netbsd32___acl_get_file(struct lwp *l,
+ const struct netbsd32___acl_get_file_args *uap, register_t *retval)
+{
+
+ return kern___acl_get_path(l, SCARG_P32(uap, path), SCARG(uap, type),
+ SCARG_P32(uap, aclp), NSM_FOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file path, get an ACL for it; don't follow links.
+ */
+int
+netbsd32___acl_get_link(struct lwp *l,
+ const struct netbsd32___acl_get_link_args *uap, register_t *retval)
+{
+
+ return kern___acl_get_path(l, SCARG_P32(uap, path), SCARG(uap, type),
+ SCARG_P32(uap, aclp), NSM_NOFOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file path, set an ACL for it.
+ */
+int
+netbsd32___acl_set_file(struct lwp *l,
+ const struct netbsd32___acl_set_file_args *uap, register_t *retval)
+{
+
+ return kern___acl_set_path(l, SCARG_P32(uap, path), SCARG(uap, type),
+ SCARG_P32(uap, aclp), NSM_FOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file path, set an ACL for it; don't follow links.
+ */
+int
+netbsd32___acl_set_link(struct lwp *l,
+ const struct netbsd32___acl_set_link_args *uap, register_t *retval)
+{
+
+ return kern___acl_set_path(l, SCARG_P32(uap, path), SCARG(uap, type),
+ SCARG_P32(uap, aclp), NSM_NOFOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file descriptor, get an ACL for it.
+ */
+int
+netbsd32___acl_get_fd(struct lwp *l,
+ const struct netbsd32___acl_get_fd_args *uap, register_t *retval)
+{
+ struct file *fp;
+ int error;
+ error = fd_getvnode(SCARG(uap, filedes), &fp);
+ if (error == 0) {
+ error = vacl_get_acl(l, fp->f_vnode, SCARG(uap, type),
+ SCARG_P32(uap, aclp));
+ fd_putfile(SCARG(uap, filedes));
+ }
+ return error;
+}
+
+/*
+ * Given a file descriptor, set an ACL for it.
+ */
+int
+netbsd32___acl_set_fd(struct lwp *l,
+ const struct netbsd32___acl_set_fd_args *uap, register_t *retval)
+{
+ struct file *fp;
+ int error;
+
+ error = fd_getvnode(SCARG(uap, filedes), &fp);
+ if (error == 0) {
+ error = vacl_set_acl(l, fp->f_vnode, SCARG(uap, type),
+ SCARG_P32(uap, aclp));
+ fd_putfile(SCARG(uap, filedes));
+ }
+ return error;
+}
+
+/*
+ * Given a file path, delete an ACL from it.
+ */
+int
+netbsd32___acl_delete_file(struct lwp *l,
+ const struct netbsd32___acl_delete_file_args *uap, register_t *retval)
+{
+
+ return kern___acl_delete_path(l, SCARG_P32(uap, path), SCARG(uap, type),
+ NSM_FOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file path, delete an ACL from it; don't follow links.
+ */
+int
+netbsd32___acl_delete_link(struct lwp *l,
+ const struct netbsd32___acl_delete_link_args *uap, register_t *retval)
+{
+ return kern___acl_delete_path(l, SCARG_P32(uap, path), SCARG(uap, type),
+ NSM_NOFOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file path, delete an ACL from it.
+ */
+int
+netbsd32___acl_delete_fd(struct lwp *l,
+ const struct netbsd32___acl_delete_fd_args *uap, register_t *retval)
+{
+ struct file *fp;
+ int error;
+
+ error = fd_getvnode(SCARG(uap, filedes), &fp);
+ if (error == 0) {
+ error = vacl_delete(l, fp->f_vnode, SCARG(uap, type));
+ fd_putfile(SCARG(uap, filedes));
+ }
+ return error;
+}
+
+/*
+ * Given a file path, check an ACL for it.
+ */
+int
+netbsd32___acl_aclcheck_file(struct lwp *l,
+ const struct netbsd32___acl_aclcheck_file_args *uap, register_t *retval)
+{
+
+ return kern___acl_aclcheck_path(l, SCARG_P32(uap, path),
+ SCARG(uap, type), SCARG_P32(uap, aclp), NSM_FOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file path, check an ACL for it; don't follow links.
+ */
+int
+netbsd32___acl_aclcheck_link(struct lwp *l,
+ const struct netbsd32___acl_aclcheck_link_args *uap, register_t *retval)
+{
+
+ return kern___acl_aclcheck_path(l, SCARG_P32(uap, path),
+ SCARG(uap, type), SCARG_P32(uap, aclp), NSM_NOFOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file descriptor, check an ACL for it.
+ */
+int
+netbsd32___acl_aclcheck_fd(struct lwp *l,
+ const struct netbsd32___acl_aclcheck_fd_args *uap, register_t *retval)
+{
+ struct file *fp;
+ int error;
+
+ error = fd_getvnode(SCARG(uap, filedes), &fp);
+ if (error == 0) {
+ error = vacl_aclcheck(l, fp->f_vnode, SCARG(uap, type),
+ SCARG_P32(uap, aclp));
+ fd_putfile(SCARG(uap, filedes));
+ }
+ return error;
+}
diff --git a/sys/compat/netbsd32/netbsd32_netbsd.c b/sys/compat/netbsd32/netbsd32_netbsd.c
index 092f56e605d..f764168ffcb 100644
--- a/sys/compat/netbsd32/netbsd32_netbsd.c
+++ b/sys/compat/netbsd32/netbsd32_netbsd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_netbsd.c,v 1.228 2019/06/20 03:31:54 kamil Exp $ */
+/* $NetBSD: netbsd32_netbsd.c,v 1.229 2020/05/16 18:31:48 christos Exp $ */
/*
* Copyright (c) 1998, 2001, 2008, 2018 Matthew R. Green
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.228 2019/06/20 03:31:54 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.229 2020/05/16 18:31:48 christos Exp $");
/*
* below are all the standard NetBSD system calls, in the 32bit
@@ -1253,6 +1253,21 @@ netbsd32_seteuid(struct lwp *l, const struct netbsd32_seteuid_args *uap, registe
}
int
+netbsd32_lpathconf(struct lwp *l, const struct netbsd32_lpathconf_args *uap, register_t *retval)
+{
+ /* {
+ syscallarg(netbsd32_charp) path;
+ syscallarg(int) name;
+ } */
+ struct sys_lpathconf_args ua;
+
+ NETBSD32TOP_UAP(path, const char);
+ NETBSD32TO64_UAP(name);
+
+ return sys_lpathconf(l, &ua, retval);
+}
+
+int
netbsd32_pathconf(struct lwp *l, const struct netbsd32_pathconf_args *uap, register_t *retval)
{
/* {
diff --git a/sys/compat/netbsd32/netbsd32_syscall.h b/sys/compat/netbsd32/netbsd32_syscall.h
index ccc4c68031d..e462803861f 100644
--- a/sys/compat/netbsd32/netbsd32_syscall.h
+++ b/sys/compat/netbsd32/netbsd32_syscall.h
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_syscall.h,v 1.153 2020/04/26 19:18:52 thorpej Exp $ */
+/* $NetBSD: netbsd32_syscall.h,v 1.154 2020/05/16 18:31:48 christos Exp $ */
/*
* System call numbers.
@@ -1284,6 +1284,45 @@
/* syscall: "netbsd32___fhstatvfs190" ret: "int" args: "netbsd32_voidp" "netbsd32_size_t" "netbsd32_statvfsp_t" "int" */
#define NETBSD32_SYS_netbsd32___fhstatvfs190 486
-#define NETBSD32_SYS_MAXSYSCALL 487
+/* syscall: "netbsd32___acl_get_link" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */
+#define NETBSD32_SYS_netbsd32___acl_get_link 487
+
+/* syscall: "netbsd32___acl_set_link" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */
+#define NETBSD32_SYS_netbsd32___acl_set_link 488
+
+/* syscall: "netbsd32___acl_delete_link" ret: "int" args: "const netbsd32_charp" "acl_type_t" */
+#define NETBSD32_SYS_netbsd32___acl_delete_link 489
+
+/* syscall: "netbsd32___acl_aclcheck_link" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */
+#define NETBSD32_SYS_netbsd32___acl_aclcheck_link 490
+
+/* syscall: "netbsd32___acl_get_file" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */
+#define NETBSD32_SYS_netbsd32___acl_get_file 491
+
+/* syscall: "netbsd32___acl_set_file" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */
+#define NETBSD32_SYS_netbsd32___acl_set_file 492
+
+/* syscall: "netbsd32___acl_get_fd" ret: "int" args: "int" "acl_type_t" "netbsd32_aclp_t" */
+#define NETBSD32_SYS_netbsd32___acl_get_fd 493
+
+/* syscall: "netbsd32___acl_set_fd" ret: "int" args: "int" "acl_type_t" "netbsd32_aclp_t" */
+#define NETBSD32_SYS_netbsd32___acl_set_fd 494
+
+/* syscall: "netbsd32___acl_delete_file" ret: "int" args: "const netbsd32_charp" "acl_type_t" */
+#define NETBSD32_SYS_netbsd32___acl_delete_file 495
+
+/* syscall: "netbsd32___acl_delete_fd" ret: "int" args: "int" "acl_type_t" */
+#define NETBSD32_SYS_netbsd32___acl_delete_fd 496
+
+/* syscall: "netbsd32___acl_aclcheck_file" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */
+#define NETBSD32_SYS_netbsd32___acl_aclcheck_file 497
+
+/* syscall: "netbsd32___acl_aclcheck_fd" ret: "int" args: "int" "acl_type_t" "netbsd32_aclp_t" */
+#define NETBSD32_SYS_netbsd32___acl_aclcheck_fd 498
+
+/* syscall: "netbsd32_lpathconf" ret: "long" args: "const netbsd32_charp" "int" */
+#define NETBSD32_SYS_netbsd32_lpathconf 499
+
+#define NETBSD32_SYS_MAXSYSCALL 500
#define NETBSD32_SYS_NSYSENT 512
#endif /* _NETBSD32_SYS_SYSCALL_H_ */
diff --git a/sys/compat/netbsd32/netbsd32_syscallargs.h b/sys/compat/netbsd32/netbsd32_syscallargs.h
index e6807165a82..4b9e4a341d0 100644
--- a/sys/compat/netbsd32/netbsd32_syscallargs.h
+++ b/sys/compat/netbsd32/netbsd32_syscallargs.h
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_syscallargs.h,v 1.152 2020/04/26 19:18:52 thorpej Exp $ */
+/* $NetBSD: netbsd32_syscallargs.h,v 1.153 2020/05/16 18:31:48 christos Exp $ */
/*
* System call argument lists.
@@ -2669,6 +2669,93 @@ struct netbsd32___fhstatvfs190_args {
};
check_syscall_args(netbsd32___fhstatvfs190)
+struct netbsd32___acl_get_link_args {
+ syscallarg(const netbsd32_charp) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(netbsd32_aclp_t) aclp;
+};
+check_syscall_args(netbsd32___acl_get_link)
+
+struct netbsd32___acl_set_link_args {
+ syscallarg(const netbsd32_charp) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(netbsd32_aclp_t) aclp;
+};
+check_syscall_args(netbsd32___acl_set_link)
+
+struct netbsd32___acl_delete_link_args {
+ syscallarg(const netbsd32_charp) path;
+ syscallarg(acl_type_t) type;
+};
+check_syscall_args(netbsd32___acl_delete_link)
+
+struct netbsd32___acl_aclcheck_link_args {
+ syscallarg(const netbsd32_charp) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(netbsd32_aclp_t) aclp;
+};
+check_syscall_args(netbsd32___acl_aclcheck_link)
+
+struct netbsd32___acl_get_file_args {
+ syscallarg(const netbsd32_charp) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(netbsd32_aclp_t) aclp;
+};
+check_syscall_args(netbsd32___acl_get_file)
+
+struct netbsd32___acl_set_file_args {
+ syscallarg(const netbsd32_charp) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(netbsd32_aclp_t) aclp;
+};
+check_syscall_args(netbsd32___acl_set_file)
+
+struct netbsd32___acl_get_fd_args {
+ syscallarg(int) filedes;
+ syscallarg(acl_type_t) type;
+ syscallarg(netbsd32_aclp_t) aclp;
+};
+check_syscall_args(netbsd32___acl_get_fd)
+
+struct netbsd32___acl_set_fd_args {
+ syscallarg(int) filedes;
+ syscallarg(acl_type_t) type;
+ syscallarg(netbsd32_aclp_t) aclp;
+};
+check_syscall_args(netbsd32___acl_set_fd)
+
+struct netbsd32___acl_delete_file_args {
+ syscallarg(const netbsd32_charp) path;
+ syscallarg(acl_type_t) type;
+};
+check_syscall_args(netbsd32___acl_delete_file)
+
+struct netbsd32___acl_delete_fd_args {
+ syscallarg(int) filedes;
+ syscallarg(acl_type_t) type;
+};
+check_syscall_args(netbsd32___acl_delete_fd)
+
+struct netbsd32___acl_aclcheck_file_args {
+ syscallarg(const netbsd32_charp) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(netbsd32_aclp_t) aclp;
+};
+check_syscall_args(netbsd32___acl_aclcheck_file)
+
+struct netbsd32___acl_aclcheck_fd_args {
+ syscallarg(int) filedes;
+ syscallarg(acl_type_t) type;
+ syscallarg(netbsd32_aclp_t) aclp;
+};
+check_syscall_args(netbsd32___acl_aclcheck_fd)
+
+struct netbsd32_lpathconf_args {
+ syscallarg(const netbsd32_charp) path;
+ syscallarg(int) name;
+};
+check_syscall_args(netbsd32_lpathconf)
+
/*
* System call prototypes.
*/
@@ -3503,4 +3590,30 @@ int netbsd32___fstatvfs190(struct lwp *, const struct netbsd32___fstatvfs190_arg
int netbsd32___fhstatvfs190(struct lwp *, const struct netbsd32___fhstatvfs190_args *, register_t *);
+int netbsd32___acl_get_link(struct lwp *, const struct netbsd32___acl_get_link_args *, register_t *);
+
+int netbsd32___acl_set_link(struct lwp *, const struct netbsd32___acl_set_link_args *, register_t *);
+
+int netbsd32___acl_delete_link(struct lwp *, const struct netbsd32___acl_delete_link_args *, register_t *);
+
+int netbsd32___acl_aclcheck_link(struct lwp *, const struct netbsd32___acl_aclcheck_link_args *, register_t *);
+
+int netbsd32___acl_get_file(struct lwp *, const struct netbsd32___acl_get_file_args *, register_t *);
+
+int netbsd32___acl_set_file(struct lwp *, const struct netbsd32___acl_set_file_args *, register_t *);
+
+int netbsd32___acl_get_fd(struct lwp *, const struct netbsd32___acl_get_fd_args *, register_t *);
+
+int netbsd32___acl_set_fd(struct lwp *, const struct netbsd32___acl_set_fd_args *, register_t *);
+
+int netbsd32___acl_delete_file(struct lwp *, const struct netbsd32___acl_delete_file_args *, register_t *);
+
+int netbsd32___acl_delete_fd(struct lwp *, const struct netbsd32___acl_delete_fd_args *, register_t *);
+
+int netbsd32___acl_aclcheck_file(struct lwp *, const struct netbsd32___acl_aclcheck_file_args *, register_t *);
+
+int netbsd32___acl_aclcheck_fd(struct lwp *, const struct netbsd32___acl_aclcheck_fd_args *, register_t *);
+
+int netbsd32_lpathconf(struct lwp *, const struct netbsd32_lpathconf_args *, register_t *);
+
#endif /* _NETBSD32_SYS_SYSCALLARGS_H_ */
diff --git a/sys/compat/netbsd32/netbsd32_syscalls.c b/sys/compat/netbsd32/netbsd32_syscalls.c
index 8724c630b32..d97a1b1fb8b 100644
--- a/sys/compat/netbsd32/netbsd32_syscalls.c
+++ b/sys/compat/netbsd32/netbsd32_syscalls.c
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_syscalls.c,v 1.152 2020/04/26 19:18:52 thorpej Exp $ */
+/* $NetBSD: netbsd32_syscalls.c,v 1.153 2020/05/16 18:31:48 christos Exp $ */
/*
* System call names.
@@ -8,7 +8,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_syscalls.c,v 1.152 2020/04/26 19:18:52 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_syscalls.c,v 1.153 2020/05/16 18:31:48 christos Exp $");
#if defined(_KERNEL_OPT)
#if defined(_KERNEL_OPT)
@@ -525,19 +525,19 @@ const char *const netbsd32_syscallnames[] = {
/* 484 */ "netbsd32___statvfs190",
/* 485 */ "netbsd32___fstatvfs190",
/* 486 */ "netbsd32___fhstatvfs190",
- /* 487 */ "# filler",
- /* 488 */ "# filler",
- /* 489 */ "# filler",
- /* 490 */ "# filler",
- /* 491 */ "# filler",
- /* 492 */ "# filler",
- /* 493 */ "# filler",
- /* 494 */ "# filler",
- /* 495 */ "# filler",
- /* 496 */ "# filler",
- /* 497 */ "# filler",
- /* 498 */ "# filler",
- /* 499 */ "# filler",
+ /* 487 */ "netbsd32___acl_get_link",
+ /* 488 */ "netbsd32___acl_set_link",
+ /* 489 */ "netbsd32___acl_delete_link",
+ /* 490 */ "netbsd32___acl_aclcheck_link",
+ /* 491 */ "netbsd32___acl_get_file",
+ /* 492 */ "netbsd32___acl_set_file",
+ /* 493 */ "netbsd32___acl_get_fd",
+ /* 494 */ "netbsd32___acl_set_fd",
+ /* 495 */ "netbsd32___acl_delete_file",
+ /* 496 */ "netbsd32___acl_delete_fd",
+ /* 497 */ "netbsd32___acl_aclcheck_file",
+ /* 498 */ "netbsd32___acl_aclcheck_fd",
+ /* 499 */ "netbsd32_lpathconf",
/* 500 */ "# filler",
/* 501 */ "# filler",
/* 502 */ "# filler",
@@ -1050,19 +1050,19 @@ const char *const altnetbsd32_syscallnames[] = {
/* 484 */ "statvfs1",
/* 485 */ "fstatvfs1",
/* 486 */ "fhstatvfs1",
- /* 487 */ NULL, /* filler */
- /* 488 */ NULL, /* filler */
- /* 489 */ NULL, /* filler */
- /* 490 */ NULL, /* filler */
- /* 491 */ NULL, /* filler */
- /* 492 */ NULL, /* filler */
- /* 493 */ NULL, /* filler */
- /* 494 */ NULL, /* filler */
- /* 495 */ NULL, /* filler */
- /* 496 */ NULL, /* filler */
- /* 497 */ NULL, /* filler */
- /* 498 */ NULL, /* filler */
- /* 499 */ NULL, /* filler */
+ /* 487 */ "__acl_get_link",
+ /* 488 */ "__acl_set_link",
+ /* 489 */ "__acl_delete_link",
+ /* 490 */ "__acl_aclcheck_link",
+ /* 491 */ "__acl_get_file",
+ /* 492 */ "__acl_set_file",
+ /* 493 */ "__acl_get_fd",
+ /* 494 */ "__acl_set_fd",
+ /* 495 */ "__acl_delete_file",
+ /* 496 */ "__acl_delete_fd",
+ /* 497 */ "__acl_aclcheck_file",
+ /* 498 */ "__acl_aclcheck_fd",
+ /* 499 */ "lpathconf",
/* 500 */ NULL, /* filler */
/* 501 */ NULL, /* filler */
/* 502 */ NULL, /* filler */
diff --git a/sys/compat/netbsd32/netbsd32_syscalls_autoload.c b/sys/compat/netbsd32/netbsd32_syscalls_autoload.c
index 4f96637710b..0556fe60af6 100644
--- a/sys/compat/netbsd32/netbsd32_syscalls_autoload.c
+++ b/sys/compat/netbsd32/netbsd32_syscalls_autoload.c
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_syscalls_autoload.c,v 1.32 2020/04/26 19:18:52 thorpej Exp $ */
+/* $NetBSD: netbsd32_syscalls_autoload.c,v 1.33 2020/05/16 18:31:48 christos Exp $ */
/*
* System call autoload table.
@@ -8,7 +8,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_syscalls_autoload.c,v 1.32 2020/04/26 19:18:52 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_syscalls_autoload.c,v 1.33 2020/05/16 18:31:48 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
diff --git a/sys/compat/netbsd32/netbsd32_sysent.c b/sys/compat/netbsd32/netbsd32_sysent.c
index 7fe7f9e5b2c..f6740e7f55c 100644
--- a/sys/compat/netbsd32/netbsd32_sysent.c
+++ b/sys/compat/netbsd32/netbsd32_sysent.c
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_sysent.c,v 1.151 2020/04/26 19:18:52 thorpej Exp $ */
+/* $NetBSD: netbsd32_sysent.c,v 1.152 2020/05/16 18:31:48 christos Exp $ */
/*
* System call switch table.
@@ -8,7 +8,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_sysent.c,v 1.151 2020/04/26 19:18:52 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_sysent.c,v 1.152 2020/05/16 18:31:48 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
@@ -2009,44 +2009,57 @@ struct sysent netbsd32_sysent[] = {
.sy_call = (sy_call_t *)netbsd32___fhstatvfs190
}, /* 486 = netbsd32___fhstatvfs190 */
{
- .sy_call = sys_nosys,
- }, /* 487 = filler */
+ ns(struct netbsd32___acl_get_link_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_get_link
+ }, /* 487 = netbsd32___acl_get_link */
{
- .sy_call = sys_nosys,
- }, /* 488 = filler */
+ ns(struct netbsd32___acl_set_link_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_set_link
+ }, /* 488 = netbsd32___acl_set_link */
{
- .sy_call = sys_nosys,
- }, /* 489 = filler */
+ ns(struct netbsd32___acl_delete_link_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_delete_link
+ }, /* 489 = netbsd32___acl_delete_link */
{
- .sy_call = sys_nosys,
- }, /* 490 = filler */
+ ns(struct netbsd32___acl_aclcheck_link_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_aclcheck_link
+ }, /* 490 = netbsd32___acl_aclcheck_link */
{
- .sy_call = sys_nosys,
- }, /* 491 = filler */
+ ns(struct netbsd32___acl_get_file_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_get_file
+ }, /* 491 = netbsd32___acl_get_file */
{
- .sy_call = sys_nosys,
- }, /* 492 = filler */
+ ns(struct netbsd32___acl_set_file_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_set_file
+ }, /* 492 = netbsd32___acl_set_file */
{
- .sy_call = sys_nosys,
- }, /* 493 = filler */
+ ns(struct netbsd32___acl_get_fd_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_get_fd
+ }, /* 493 = netbsd32___acl_get_fd */
{
- .sy_call = sys_nosys,
- }, /* 494 = filler */
+ ns(struct netbsd32___acl_set_fd_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_set_fd
+ }, /* 494 = netbsd32___acl_set_fd */
{
- .sy_call = sys_nosys,
- }, /* 495 = filler */
+ ns(struct netbsd32___acl_delete_file_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_delete_file
+ }, /* 495 = netbsd32___acl_delete_file */
{
- .sy_call = sys_nosys,
- }, /* 496 = filler */
+ ns(struct netbsd32___acl_delete_fd_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_delete_fd
+ }, /* 496 = netbsd32___acl_delete_fd */
{
- .sy_call = sys_nosys,
- }, /* 497 = filler */
+ ns(struct netbsd32___acl_aclcheck_file_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_aclcheck_file
+ }, /* 497 = netbsd32___acl_aclcheck_file */
{
- .sy_call = sys_nosys,
- }, /* 498 = filler */
+ ns(struct netbsd32___acl_aclcheck_fd_args),
+ .sy_call = (sy_call_t *)netbsd32___acl_aclcheck_fd
+ }, /* 498 = netbsd32___acl_aclcheck_fd */
{
- .sy_call = sys_nosys,
- }, /* 499 = filler */
+ ns(struct netbsd32_lpathconf_args),
+ .sy_call = (sy_call_t *)netbsd32_lpathconf
+ }, /* 499 = netbsd32_lpathconf */
{
.sy_call = sys_nosys,
}, /* 500 = filler */
diff --git a/sys/compat/netbsd32/netbsd32_systrace_args.c b/sys/compat/netbsd32/netbsd32_systrace_args.c
index 21a37ee6c6a..439cfc96396 100644
--- a/sys/compat/netbsd32/netbsd32_systrace_args.c
+++ b/sys/compat/netbsd32/netbsd32_systrace_args.c
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_systrace_args.c,v 1.43 2020/04/26 19:18:52 thorpej Exp $ */
+/* $NetBSD: netbsd32_systrace_args.c,v 1.44 2020/05/16 18:31:48 christos Exp $ */
/*
* System call argument to DTrace register array converstion.
@@ -3548,6 +3548,119 @@ systrace_args(register_t sysnum, const void *params, uintptr_t *uarg, size_t *n_
*n_args = 4;
break;
}
+ /* netbsd32___acl_get_link */
+ case 487: {
+ const struct netbsd32___acl_get_link_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */
+ *n_args = 3;
+ break;
+ }
+ /* netbsd32___acl_set_link */
+ case 488: {
+ const struct netbsd32___acl_set_link_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */
+ *n_args = 3;
+ break;
+ }
+ /* netbsd32___acl_delete_link */
+ case 489: {
+ const struct netbsd32___acl_delete_link_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ *n_args = 2;
+ break;
+ }
+ /* netbsd32___acl_aclcheck_link */
+ case 490: {
+ const struct netbsd32___acl_aclcheck_link_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */
+ *n_args = 3;
+ break;
+ }
+ /* netbsd32___acl_get_file */
+ case 491: {
+ const struct netbsd32___acl_get_file_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */
+ *n_args = 3;
+ break;
+ }
+ /* netbsd32___acl_set_file */
+ case 492: {
+ const struct netbsd32___acl_set_file_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */
+ *n_args = 3;
+ break;
+ }
+ /* netbsd32___acl_get_fd */
+ case 493: {
+ const struct netbsd32___acl_get_fd_args *p = params;
+ iarg[0] = SCARG(p, filedes); /* int */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */
+ *n_args = 3;
+ break;
+ }
+ /* netbsd32___acl_set_fd */
+ case 494: {
+ const struct netbsd32___acl_set_fd_args *p = params;
+ iarg[0] = SCARG(p, filedes); /* int */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */
+ *n_args = 3;
+ break;
+ }
+ /* netbsd32___acl_delete_file */
+ case 495: {
+ const struct netbsd32___acl_delete_file_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ *n_args = 2;
+ break;
+ }
+ /* netbsd32___acl_delete_fd */
+ case 496: {
+ const struct netbsd32___acl_delete_fd_args *p = params;
+ iarg[0] = SCARG(p, filedes); /* int */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ *n_args = 2;
+ break;
+ }
+ /* netbsd32___acl_aclcheck_file */
+ case 497: {
+ const struct netbsd32___acl_aclcheck_file_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */
+ *n_args = 3;
+ break;
+ }
+ /* netbsd32___acl_aclcheck_fd */
+ case 498: {
+ const struct netbsd32___acl_aclcheck_fd_args *p = params;
+ iarg[0] = SCARG(p, filedes); /* int */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */
+ *n_args = 3;
+ break;
+ }
+ /* netbsd32_lpathconf */
+ case 499: {
+ const struct netbsd32_lpathconf_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */
+ iarg[1] = SCARG(p, name); /* int */
+ *n_args = 2;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9597,6 +9710,202 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
};
break;
+ /* netbsd32___acl_get_link */
+ case 487:
+ switch(ndx) {
+ case 0:
+ p = "const netbsd32_charp";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "netbsd32_aclp_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32___acl_set_link */
+ case 488:
+ switch(ndx) {
+ case 0:
+ p = "const netbsd32_charp";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "netbsd32_aclp_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32___acl_delete_link */
+ case 489:
+ switch(ndx) {
+ case 0:
+ p = "const netbsd32_charp";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32___acl_aclcheck_link */
+ case 490:
+ switch(ndx) {
+ case 0:
+ p = "const netbsd32_charp";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "netbsd32_aclp_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32___acl_get_file */
+ case 491:
+ switch(ndx) {
+ case 0:
+ p = "const netbsd32_charp";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "netbsd32_aclp_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32___acl_set_file */
+ case 492:
+ switch(ndx) {
+ case 0:
+ p = "const netbsd32_charp";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "netbsd32_aclp_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32___acl_get_fd */
+ case 493:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "netbsd32_aclp_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32___acl_set_fd */
+ case 494:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "netbsd32_aclp_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32___acl_delete_file */
+ case 495:
+ switch(ndx) {
+ case 0:
+ p = "const netbsd32_charp";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32___acl_delete_fd */
+ case 496:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32___acl_aclcheck_file */
+ case 497:
+ switch(ndx) {
+ case 0:
+ p = "const netbsd32_charp";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "netbsd32_aclp_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32___acl_aclcheck_fd */
+ case 498:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "netbsd32_aclp_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* netbsd32_lpathconf */
+ case 499:
+ switch(ndx) {
+ case 0:
+ p = "const netbsd32_charp";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11599,6 +11908,71 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* netbsd32___acl_get_link */
+ case 487:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32___acl_set_link */
+ case 488:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32___acl_delete_link */
+ case 489:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32___acl_aclcheck_link */
+ case 490:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32___acl_get_file */
+ case 491:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32___acl_set_file */
+ case 492:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32___acl_get_fd */
+ case 493:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32___acl_set_fd */
+ case 494:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32___acl_delete_file */
+ case 495:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32___acl_delete_fd */
+ case 496:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32___acl_aclcheck_file */
+ case 497:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32___acl_aclcheck_fd */
+ case 498:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* netbsd32_lpathconf */
+ case 499:
+ if (ndx == 0 || ndx == 1)
+ p = "long";
+ break;
default:
break;
};
diff --git a/sys/compat/netbsd32/syscalls.master b/sys/compat/netbsd32/syscalls.master
index bd8bf3645cf..56071d3cdfe 100644
--- a/sys/compat/netbsd32/syscalls.master
+++ b/sys/compat/netbsd32/syscalls.master
@@ -1,4 +1,4 @@
- $NetBSD: syscalls.master,v 1.137 2020/04/26 19:18:36 thorpej Exp $
+ $NetBSD: syscalls.master,v 1.138 2020/05/16 18:31:48 christos Exp $
; from: NetBSD: syscalls.master,v 1.81 1998/07/05 08:49:50 jonathan Exp
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@@ -1172,3 +1172,37 @@
486 STD { int|netbsd32|90|fhstatvfs1(netbsd32_voidp fhp, \
netbsd32_size_t fh_size, netbsd32_statvfsp_t buf, \
int flags); }
+487 STD { int|netbsd32||__acl_get_link( \
+ const netbsd32_charp path, \
+ acl_type_t type, netbsd32_aclp_t aclp); }
+488 STD { int|netbsd32||__acl_set_link( \
+ const netbsd32_charp path, \
+ acl_type_t type, netbsd32_aclp_t aclp); }
+489 STD { int|netbsd32||__acl_delete_link( \
+ const netbsd32_charp path, \
+ acl_type_t type); }
+490 STD { int|netbsd32||__acl_aclcheck_link( \
+ const netbsd32_charp path, \
+ acl_type_t type, netbsd32_aclp_t aclp); }
+491 STD { int|netbsd32||__acl_get_file( \
+ const netbsd32_charp path, \
+ acl_type_t type, netbsd32_aclp_t aclp); }
+492 STD { int|netbsd32||__acl_set_file( \
+ const netbsd32_charp path, \
+ acl_type_t type, netbsd32_aclp_t aclp); }
+493 STD { int|netbsd32||__acl_get_fd(int filedes, \
+ acl_type_t type, netbsd32_aclp_t aclp); }
+494 STD { int|netbsd32||__acl_set_fd(int filedes, \
+ acl_type_t type, netbsd32_aclp_t aclp); }
+495 STD { int|netbsd32||__acl_delete_file( \
+ const netbsd32_charp path, \
+ acl_type_t type); }
+496 STD { int|netbsd32||__acl_delete_fd(int filedes, \
+ acl_type_t type); }
+497 STD { int|netbsd32||__acl_aclcheck_file( \
+ const netbsd32_charp path, \
+ acl_type_t type, netbsd32_aclp_t aclp); }
+498 STD { int|netbsd32||__acl_aclcheck_fd(int filedes, \
+ acl_type_t type, netbsd32_aclp_t aclp); }
+499 STD { long|netbsd32||lpathconf(const netbsd32_charp path, \
+ int name); }
diff --git a/sys/fs/adosfs/advnops.c b/sys/fs/adosfs/advnops.c
index ec9916d3ae8..ab599d49225 100644
--- a/sys/fs/adosfs/advnops.c
+++ b/sys/fs/adosfs/advnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: advnops.c,v 1.53 2020/04/23 21:47:07 ad Exp $ */
+/* $NetBSD: advnops.c,v 1.54 2020/05/16 18:31:48 christos Exp $ */
/*
* Copyright (c) 1994 Christian E. Hopps
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: advnops.c,v 1.53 2020/04/23 21:47:07 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: advnops.c,v 1.54 2020/05/16 18:31:48 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -101,6 +101,7 @@ const struct vnodeopv_entry_desc adosfs_vnodeop_entries[] = {
{ &vop_open_desc, adosfs_open }, /* open */
{ &vop_close_desc, adosfs_close }, /* close */
{ &vop_access_desc, adosfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, adosfs_getattr }, /* getattr */
{ &vop_setattr_desc, adosfs_setattr }, /* setattr */
{ &vop_read_desc, adosfs_read }, /* read */
@@ -749,7 +750,7 @@ reterr:
}
static int
-adosfs_check_possible(struct vnode *vp, struct anode *ap, mode_t mode)
+adosfs_check_possible(struct vnode *vp, struct anode *ap, accmode_t accmode)
{
/*
@@ -757,7 +758,7 @@ adosfs_check_possible(struct vnode *vp, struct anode *ap, mode_t mode)
* fifo, or a block or character device resident on the
* file system.
*/
- if (mode & VWRITE) {
+ if (accmode & VWRITE) {
switch (vp->v_type) {
case VDIR:
case VLNK:
@@ -772,14 +773,14 @@ adosfs_check_possible(struct vnode *vp, struct anode *ap, mode_t mode)
}
static int
-adosfs_check_permitted(struct vnode *vp, struct anode *ap, mode_t mode,
+adosfs_check_permitted(struct vnode *vp, struct anode *ap, accmode_t accmode,
kauth_cred_t cred)
{
mode_t file_mode = adunixprot(ap->adprot) & ap->amp->mask;
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
- vp->v_type, file_mode), vp, NULL, genfs_can_access(vp->v_type,
- file_mode, ap->uid, ap->gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, file_mode), vp, NULL, genfs_can_access(vp,
+ cred, ap->uid, ap->gid, file_mode, NULL, accmode));
}
int
@@ -787,7 +788,7 @@ adosfs_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *sp = v;
struct anode *ap;
@@ -806,11 +807,11 @@ adosfs_access(void *v)
}
#endif
- error = adosfs_check_possible(vp, ap, sp->a_mode);
+ error = adosfs_check_possible(vp, ap, sp->a_accmode);
if (error)
return error;
- error = adosfs_check_permitted(vp, ap, sp->a_mode, sp->a_cred);
+ error = adosfs_check_permitted(vp, ap, sp->a_accmode, sp->a_cred);
#ifdef ADOSFS_DIAGNOSTIC
printf(" %d)", error);
diff --git a/sys/fs/autofs/autofs_vnops.c b/sys/fs/autofs/autofs_vnops.c
index 0c0b424cd3e..98d59e0dd62 100644
--- a/sys/fs/autofs/autofs_vnops.c
+++ b/sys/fs/autofs/autofs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: autofs_vnops.c,v 1.5 2020/01/17 20:08:07 ad Exp $ */
+/* $NetBSD: autofs_vnops.c,v 1.6 2020/05/16 18:31:48 christos Exp $ */
/*-
* Copyright (c) 2017 The NetBSD Foundation, Inc.
* Copyright (c) 2016 The DragonFly Project
@@ -34,7 +34,7 @@
*
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: autofs_vnops.c,v 1.5 2020/01/17 20:08:07 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: autofs_vnops.c,v 1.6 2020/05/16 18:31:48 christos Exp $");
#include "autofs.h"
@@ -591,6 +591,7 @@ static const struct vnodeopv_entry_desc autofs_vnodeop_entries[] = {
{ &vop_open_desc, autofs_open },
{ &vop_close_desc, autofs_close },
{ &vop_access_desc, autofs_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_getattr_desc, autofs_getattr },
{ &vop_fsync_desc, autofs_fsync },
{ &vop_mkdir_desc, autofs_mkdir },
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c
index f8c410a1a28..3b148f17a5a 100644
--- a/sys/fs/cd9660/cd9660_vnops.c
+++ b/sys/fs/cd9660/cd9660_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cd9660_vnops.c,v 1.56 2020/04/23 21:47:07 ad Exp $ */
+/* $NetBSD: cd9660_vnops.c,v 1.57 2020/05/16 18:31:48 christos Exp $ */
/*-
* Copyright (c) 1994
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd9660_vnops.c,v 1.56 2020/04/23 21:47:07 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd9660_vnops.c,v 1.57 2020/05/16 18:31:48 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -85,7 +85,7 @@ int iso_uiodir(struct isoreaddir *, struct dirent *, off_t);
int iso_shipdir(struct isoreaddir *);
static int
-cd9660_check_possible(struct vnode *vp, struct iso_node *ip, mode_t mode)
+cd9660_check_possible(struct vnode *vp, struct iso_node *ip, accmode_t accmode)
{
/*
@@ -93,7 +93,7 @@ cd9660_check_possible(struct vnode *vp, struct iso_node *ip, mode_t mode)
* fifo, or a block or character device resident on the
* file system.
*/
- if (mode & VWRITE) {
+ if (accmode & VWRITE) {
switch (vp->v_type) {
case VDIR:
case VLNK:
@@ -113,14 +113,14 @@ cd9660_check_possible(struct vnode *vp, struct iso_node *ip, mode_t mode)
* super user is granted all permissions.
*/
static int
-cd9660_check_permitted(struct vnode *vp, struct iso_node *ip, mode_t mode,
+cd9660_check_permitted(struct vnode *vp, struct iso_node *ip, accmode_t accmode,
kauth_cred_t cred)
{
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
vp->v_type, ip->inode.iso_mode & ALLPERMS), vp, NULL,
- genfs_can_access(vp->v_type, ip->inode.iso_mode & ALLPERMS,
- ip->inode.iso_uid, ip->inode.iso_gid, mode, cred));
+ genfs_can_access(vp, cred, ip->inode.iso_uid, ip->inode.iso_gid,
+ ip->inode.iso_mode & ALLPERMS, NULL, accmode));
}
int
@@ -128,18 +128,18 @@ cd9660_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
struct iso_node *ip = VTOI(vp);
int error;
- error = cd9660_check_possible(vp, ip, ap->a_mode);
+ error = cd9660_check_possible(vp, ip, ap->a_accmode);
if (error)
return error;
- error = cd9660_check_permitted(vp, ip, ap->a_mode, ap->a_cred);
+ error = cd9660_check_permitted(vp, ip, ap->a_accmode, ap->a_cred);
return error;
}
@@ -855,6 +855,7 @@ const struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
{ &vop_open_desc, cd9660_open }, /* open */
{ &vop_close_desc, cd9660_close }, /* close */
{ &vop_access_desc, cd9660_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, cd9660_getattr }, /* getattr */
{ &vop_setattr_desc, cd9660_setattr }, /* setattr */
{ &vop_read_desc, cd9660_read }, /* read */
@@ -907,6 +908,7 @@ const struct vnodeopv_entry_desc cd9660_specop_entries[] = {
{ &vop_open_desc, spec_open }, /* open */
{ &vop_close_desc, spec_close }, /* close */
{ &vop_access_desc, cd9660_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, cd9660_getattr }, /* getattr */
{ &vop_setattr_desc, cd9660_setattr }, /* setattr */
{ &vop_read_desc, spec_read }, /* read */
@@ -957,6 +959,7 @@ const struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
{ &vop_open_desc, vn_fifo_bypass }, /* open */
{ &vop_close_desc, vn_fifo_bypass }, /* close */
{ &vop_access_desc, cd9660_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, cd9660_getattr }, /* getattr */
{ &vop_setattr_desc, cd9660_setattr }, /* setattr */
{ &vop_read_desc, vn_fifo_bypass }, /* read */
diff --git a/sys/fs/efs/efs_vnops.c b/sys/fs/efs/efs_vnops.c
index 9ca534d0e5e..88a46a3ba68 100644
--- a/sys/fs/efs/efs_vnops.c
+++ b/sys/fs/efs/efs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: efs_vnops.c,v 1.39 2020/04/23 21:47:07 ad Exp $ */
+/* $NetBSD: efs_vnops.c,v 1.40 2020/05/16 18:31:48 christos Exp $ */
/*
* Copyright (c) 2006 Stephen M. Rumble <rumble@ephemeral.org>
@@ -17,7 +17,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: efs_vnops.c,v 1.39 2020/04/23 21:47:07 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: efs_vnops.c,v 1.40 2020/05/16 18:31:48 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -115,10 +115,10 @@ efs_lookup(void *v)
}
static int
-efs_check_possible(struct vnode *vp, struct efs_inode *eip, mode_t mode)
+efs_check_possible(struct vnode *vp, struct efs_inode *eip, accmode_t accmode)
{
- if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY))
+ if ((accmode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY))
return (EROFS);
return 0;
@@ -131,13 +131,13 @@ efs_check_possible(struct vnode *vp, struct efs_inode *eip, mode_t mode)
* Returns 0 on success.
*/
static int
-efs_check_permitted(struct vnode *vp, struct efs_inode *eip, mode_t mode,
+efs_check_permitted(struct vnode *vp, struct efs_inode *eip, accmode_t accmode,
kauth_cred_t cred)
{
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
- vp->v_type, eip->ei_mode), vp, NULL, genfs_can_access(vp->v_type,
- eip->ei_mode, eip->ei_uid, eip->ei_gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, eip->ei_mode), vp, NULL, genfs_can_access(vp,
+ cred, eip->ei_uid, eip->ei_gid, eip->ei_mode, NULL, accmode));
}
static int
@@ -146,18 +146,18 @@ efs_access(void *v)
struct vop_access_args /* {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
struct ucred *a_cred;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
struct efs_inode *eip = EFS_VTOI(vp);
int error;
- error = efs_check_possible(vp, eip, ap->a_mode);
+ error = efs_check_possible(vp, eip, ap->a_accmode);
if (error)
return error;
- error = efs_check_permitted(vp, eip, ap->a_mode, ap->a_cred);
+ error = efs_check_permitted(vp, eip, ap->a_accmode, ap->a_cred);
return error;
}
@@ -789,6 +789,7 @@ const struct vnodeopv_entry_desc efs_vnodeop_entries[] = {
{ &vop_open_desc, genfs_nullop }, /* open */
{ &vop_close_desc, genfs_nullop }, /* close */
{ &vop_access_desc, efs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, efs_getattr }, /* getattr */
{ &vop_setattr_desc, genfs_eopnotsupp}, /* setattr */
{ &vop_read_desc, efs_read }, /* read */
@@ -847,6 +848,7 @@ const struct vnodeopv_entry_desc efs_specop_entries[] = {
{ &vop_open_desc, spec_open }, /* open */
{ &vop_close_desc, spec_close }, /* close */
{ &vop_access_desc, efs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, efs_getattr }, /* getattr */
{ &vop_setattr_desc, genfs_eopnotsupp}, /* setattr */
{ &vop_read_desc, spec_read }, /* read */
@@ -905,6 +907,7 @@ const struct vnodeopv_entry_desc efs_fifoop_entries[] = {
{ &vop_open_desc, vn_fifo_bypass }, /* open */
{ &vop_close_desc, vn_fifo_bypass }, /* close */
{ &vop_access_desc, efs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, efs_getattr }, /* getattr */
{ &vop_setattr_desc, genfs_eopnotsupp}, /* setattr */
{ &vop_read_desc, vn_fifo_bypass }, /* read */
diff --git a/sys/fs/filecorefs/filecore_vnops.c b/sys/fs/filecorefs/filecore_vnops.c
index 5f71c8e6968..1ae0f8ede34 100644
--- a/sys/fs/filecorefs/filecore_vnops.c
+++ b/sys/fs/filecorefs/filecore_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: filecore_vnops.c,v 1.45 2020/04/23 21:47:07 ad Exp $ */
+/* $NetBSD: filecore_vnops.c,v 1.46 2020/05/16 18:31:49 christos Exp $ */
/*-
* Copyright (c) 1994 The Regents of the University of California.
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: filecore_vnops.c,v 1.45 2020/04/23 21:47:07 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: filecore_vnops.c,v 1.46 2020/05/16 18:31:49 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -122,14 +122,14 @@ filecore_check_possible(struct vnode *vp, struct filecore_node *ip,
*/
static int
filecore_check_permitted(struct vnode *vp, struct filecore_node *ip,
- mode_t mode, kauth_cred_t cred)
+ accmode_t accmode, kauth_cred_t cred)
{
struct filecore_mnt *fcmp = ip->i_mnt;
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
vp->v_type, filecore_mode(ip)), vp, NULL,
- genfs_can_access(vp->v_type, filecore_mode(ip), fcmp->fc_uid,
- fcmp->fc_gid, mode, cred));
+ genfs_can_access(vp, cred, fcmp->fc_uid, fcmp->fc_gid,
+ filecore_mode(ip), NULL, accmode));
}
int
@@ -137,18 +137,18 @@ filecore_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
struct filecore_node *ip = VTOI(vp);
int error;
- error = filecore_check_possible(vp, ip, ap->a_mode);
+ error = filecore_check_possible(vp, ip, ap->a_accmode);
if (error)
return error;
- error = filecore_check_permitted(vp, ip, ap->a_mode, ap->a_cred);
+ error = filecore_check_permitted(vp, ip, ap->a_accmode, ap->a_cred);
return error;
}
@@ -560,6 +560,7 @@ const struct vnodeopv_entry_desc filecore_vnodeop_entries[] = {
{ &vop_open_desc, filecore_open }, /* open */
{ &vop_close_desc, filecore_close }, /* close */
{ &vop_access_desc, filecore_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, filecore_getattr }, /* getattr */
{ &vop_setattr_desc, filecore_setattr }, /* setattr */
{ &vop_read_desc, filecore_read }, /* read */
diff --git a/sys/fs/hfs/hfs_vnops.c b/sys/fs/hfs/hfs_vnops.c
index 3363e4d1d79..e615158159e 100644
--- a/sys/fs/hfs/hfs_vnops.c
+++ b/sys/fs/hfs/hfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hfs_vnops.c,v 1.35 2020/04/23 21:47:07 ad Exp $ */
+/* $NetBSD: hfs_vnops.c,v 1.36 2020/05/16 18:31:49 christos Exp $ */
/*-
* Copyright (c) 2005, 2007 The NetBSD Foundation, Inc.
@@ -101,7 +101,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hfs_vnops.c,v 1.35 2020/04/23 21:47:07 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hfs_vnops.c,v 1.36 2020/05/16 18:31:49 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_ipsec.h"
@@ -162,6 +162,7 @@ const struct vnodeopv_entry_desc hfs_vnodeop_entries[] = {
{ &vop_open_desc, hfs_vop_open }, /* open */
{ &vop_close_desc, hfs_vop_close }, /* close */
{ &vop_access_desc, hfs_vop_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, hfs_vop_getattr }, /* getattr */
{ &vop_setattr_desc, hfs_vop_setattr }, /* setattr */
{ &vop_read_desc, hfs_vop_read }, /* read */
@@ -218,6 +219,7 @@ const struct vnodeopv_entry_desc hfs_specop_entries[] = {
{ &vop_open_desc, spec_open }, /* open */
{ &vop_close_desc, spec_close }, /* close */
{ &vop_access_desc, hfs_vop_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, hfs_vop_getattr }, /* getattr */
{ &vop_setattr_desc, hfs_vop_setattr }, /* setattr */
{ &vop_read_desc, spec_read }, /* read */
@@ -276,6 +278,7 @@ const struct vnodeopv_entry_desc hfs_fifoop_entries[] = {
{ &vop_open_desc, vn_fifo_bypass }, /* open */
{ &vop_close_desc, vn_fifo_bypass }, /* close */
{ &vop_access_desc, hfs_vop_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, hfs_vop_getattr }, /* getattr */
{ &vop_setattr_desc, hfs_vop_setattr }, /* setattr */
{ &vop_read_desc, vn_fifo_bypass }, /* read */
@@ -531,7 +534,7 @@ hfs_vop_close(void *v)
}
static int
-hfs_check_possible(struct vnode *vp, mode_t mode)
+hfs_check_possible(struct vnode *vp, accmode_t accmode)
{
/*
@@ -539,7 +542,7 @@ hfs_check_possible(struct vnode *vp, mode_t mode)
* since we have no write support yet.
*/
- if (mode & VWRITE) {
+ if (accmode & VWRITE) {
switch (vp->v_type) {
case VDIR:
case VLNK:
@@ -554,13 +557,13 @@ hfs_check_possible(struct vnode *vp, mode_t mode)
}
static int
-hfs_check_permitted(vnode_t *vp, struct vattr *va, mode_t mode,
+hfs_check_permitted(vnode_t *vp, struct vattr *va, accmode_t accmode,
kauth_cred_t cred)
{
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
- va->va_type, va->va_mode), vp, NULL, genfs_can_access(va->va_type,
- va->va_mode, va->va_uid, va->va_gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ va->va_type, va->va_mode), vp, NULL, genfs_can_access(vp, cred,
+ va->va_uid, va->va_gid, va->va_mode, NULL, accmode));
}
int
@@ -568,7 +571,7 @@ hfs_vop_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ int a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vattr va;
@@ -576,14 +579,14 @@ hfs_vop_access(void *v)
DPRINTF(("VOP = hfs_vop_access()\n"));
- error = hfs_check_possible(ap->a_vp, ap->a_mode);
+ error = hfs_check_possible(ap->a_vp, ap->a_accmode);
if (error)
return error;
if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0)
return error;
- error = hfs_check_permitted(ap->a_vp, &va, ap->a_mode, ap->a_cred);
+ error = hfs_check_permitted(ap->a_vp, &va, ap->a_accmode, ap->a_cred);
return error;
}
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index a214734ea55..c80e43d9b3c 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: msdosfs_vnops.c,v 1.102 2020/04/23 21:47:07 ad Exp $ */
+/* $NetBSD: msdosfs_vnops.c,v 1.103 2020/05/16 18:31:49 christos Exp $ */
/*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.102 2020/04/23 21:47:07 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.103 2020/05/16 18:31:49 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -180,7 +180,7 @@ msdosfs_close(void *v)
}
static int
-msdosfs_check_possible(struct vnode *vp, struct denode *dep, mode_t mode)
+msdosfs_check_possible(struct vnode *vp, struct denode *dep, accmode_t accmode)
{
/*
@@ -188,7 +188,7 @@ msdosfs_check_possible(struct vnode *vp, struct denode *dep, mode_t mode)
* unless the file is a socket, fifo, or a block or
* character device resident on the file system.
*/
- if (mode & VWRITE) {
+ if (accmode & VWRITE) {
switch (vp->v_type) {
case VDIR:
case VLNK:
@@ -204,7 +204,7 @@ msdosfs_check_possible(struct vnode *vp, struct denode *dep, mode_t mode)
}
static int
-msdosfs_check_permitted(struct vnode *vp, struct denode *dep, mode_t mode,
+msdosfs_check_permitted(struct vnode *vp, struct denode *dep, accmode_t accmode,
kauth_cred_t cred)
{
struct msdosfsmount *pmp = dep->de_pmp;
@@ -217,9 +217,9 @@ msdosfs_check_permitted(struct vnode *vp, struct denode *dep, mode_t mode,
file_mode &= (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask);
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
- vp->v_type, file_mode), vp, NULL, genfs_can_access(vp->v_type,
- file_mode, pmp->pm_uid, pmp->pm_gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, file_mode), vp, NULL, genfs_can_access(vp, cred,
+ pmp->pm_uid, pmp->pm_gid, file_mode, NULL, accmode));
}
int
@@ -227,18 +227,18 @@ msdosfs_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
struct denode *dep = VTODE(vp);
int error;
- error = msdosfs_check_possible(vp, dep, ap->a_mode);
+ error = msdosfs_check_possible(vp, dep, ap->a_accmode);
if (error)
return error;
- error = msdosfs_check_permitted(vp, dep, ap->a_mode, ap->a_cred);
+ error = msdosfs_check_permitted(vp, dep, ap->a_accmode, ap->a_cred);
return error;
}
@@ -371,8 +371,8 @@ msdosfs_setattr(void *v)
goto bad;
}
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES,
- ap->a_vp, NULL, genfs_can_chtimes(ap->a_vp, vap->va_vaflags,
- pmp->pm_uid, cred));
+ ap->a_vp, NULL, genfs_can_chtimes(ap->a_vp, cred,
+ pmp->pm_uid, vap->va_vaflags));
if (error)
goto bad;
if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 &&
@@ -395,7 +395,7 @@ msdosfs_setattr(void *v)
goto bad;
}
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp,
- NULL, genfs_can_chflags(cred, vp->v_type, pmp->pm_uid, false));
+ NULL, genfs_can_chflags(vp, cred, pmp->pm_uid, false));
if (error)
goto bad;
/* We ignore the read and execute bits. */
@@ -415,7 +415,7 @@ msdosfs_setattr(void *v)
goto bad;
}
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp,
- NULL, genfs_can_chflags(cred, vp->v_type, pmp->pm_uid, false));
+ NULL, genfs_can_chflags(vp, cred, pmp->pm_uid, false));
if (error)
goto bad;
if (vap->va_flags & SF_ARCHIVED)
@@ -1847,6 +1847,7 @@ const struct vnodeopv_entry_desc msdosfs_vnodeop_entries[] = {
{ &vop_open_desc, genfs_nullop }, /* open */
{ &vop_close_desc, msdosfs_close }, /* close */
{ &vop_access_desc, msdosfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, msdosfs_getattr }, /* getattr */
{ &vop_setattr_desc, msdosfs_setattr }, /* setattr */
{ &vop_read_desc, msdosfs_read }, /* read */
diff --git a/sys/fs/nilfs/nilfs_vnops.c b/sys/fs/nilfs/nilfs_vnops.c
index 61467729cb6..b811c994904 100644
--- a/sys/fs/nilfs/nilfs_vnops.c
+++ b/sys/fs/nilfs/nilfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: nilfs_vnops.c,v 1.40 2020/04/23 21:47:07 ad Exp $ */
+/* $NetBSD: nilfs_vnops.c,v 1.41 2020/05/16 18:31:49 christos Exp $ */
/*
* Copyright (c) 2008, 2009 Reinoud Zandijk
@@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.40 2020/04/23 21:47:07 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.41 2020/05/16 18:31:49 christos Exp $");
#endif /* not lint */
@@ -987,7 +987,7 @@ nilfs_close(void *v)
/* --------------------------------------------------------------------- */
static int
-nilfs_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode)
+nilfs_check_possible(struct vnode *vp, struct vattr *vap, accmode_t accmode)
{
int flags;
@@ -1000,7 +1000,7 @@ nilfs_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode)
* normal nodes: check if we're on a read-only mounted
* filingsystem and bomb out if we're trying to write.
*/
- if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY))
+ if ((accmode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY))
return EROFS;
break;
case VBLK:
@@ -1020,21 +1020,21 @@ nilfs_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode)
/* noone may write immutable files */
/* TODO: get chflags(2) flags */
flags = 0;
- if ((mode & VWRITE) && (flags & IMMUTABLE))
+ if ((accmode & VWRITE) && (flags & IMMUTABLE))
return EPERM;
return 0;
}
static int
-nilfs_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode,
+nilfs_check_permitted(struct vnode *vp, struct vattr *vap, accmode_t accmode,
kauth_cred_t cred)
{
/* ask the generic genfs_can_access to advice on security */
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
- vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp->v_type,
- vap->va_mode, vap->va_uid, vap->va_gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp, cred,
+ vap->va_uid, vap->va_gid, vap->va_mode, NULL, accmode));
}
int
@@ -1042,12 +1042,12 @@ nilfs_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
struct proc *a_p;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
- mode_t mode = ap->a_mode;
+ accmode_t accmode = ap->a_accmode;
kauth_cred_t cred = ap->a_cred;
/* struct nilfs_node *nilfs_node = VTOI(vp); */
struct vattr vap;
@@ -1059,11 +1059,11 @@ nilfs_access(void *v)
if (error)
return error;
- error = nilfs_check_possible(vp, &vap, mode);
+ error = nilfs_check_possible(vp, &vap, accmode);
if (error)
return error;
- error = nilfs_check_permitted(vp, &vap, mode, cred);
+ error = nilfs_check_permitted(vp, &vap, accmode, cred);
return error;
}
@@ -1549,6 +1549,7 @@ const struct vnodeopv_entry_desc nilfs_vnodeop_entries[] = {
{ &vop_open_desc, nilfs_open }, /* open */
{ &vop_close_desc, nilfs_close }, /* close */
{ &vop_access_desc, nilfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, nilfs_getattr }, /* getattr */
{ &vop_setattr_desc, nilfs_setattr }, /* setattr */ /* TODO chflags */
{ &vop_read_desc, nilfs_read }, /* read */
diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c
index 5e006fdcfb1..b5dd2b2770f 100644
--- a/sys/fs/ntfs/ntfs_vnops.c
+++ b/sys/fs/ntfs/ntfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ntfs_vnops.c,v 1.63 2017/05/26 14:34:20 riastradh Exp $ */
+/* $NetBSD: ntfs_vnops.c,v 1.64 2020/05/16 18:31:49 christos Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ntfs_vnops.c,v 1.63 2017/05/26 14:34:20 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ntfs_vnops.c,v 1.64 2020/05/16 18:31:49 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -399,7 +399,7 @@ ntfs_write(void *v)
}
static int
-ntfs_check_possible(struct vnode *vp, struct ntnode *ip, mode_t mode)
+ntfs_check_possible(struct vnode *vp, struct ntnode *ip, accmode_t accmode)
{
/*
@@ -407,7 +407,7 @@ ntfs_check_possible(struct vnode *vp, struct ntnode *ip, mode_t mode)
* unless the file is a socket, fifo, or a block or
* character device resident on the file system.
*/
- if (mode & VWRITE) {
+ if (accmode & VWRITE) {
switch ((int)vp->v_type) {
case VDIR:
case VLNK:
@@ -422,16 +422,16 @@ ntfs_check_possible(struct vnode *vp, struct ntnode *ip, mode_t mode)
}
static int
-ntfs_check_permitted(struct vnode *vp, struct ntnode *ip, mode_t mode,
+ntfs_check_permitted(struct vnode *vp, struct ntnode *ip, accmode_t accmode,
kauth_cred_t cred)
{
mode_t file_mode;
file_mode = ip->i_mp->ntm_mode | (S_IXUSR|S_IXGRP|S_IXOTH);
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, vp->v_type,
- file_mode), vp, NULL, genfs_can_access(vp->v_type, file_mode,
- ip->i_mp->ntm_uid, ip->i_mp->ntm_gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, file_mode), vp, NULL, genfs_can_access(vp, cred,
+ ip->i_mp->ntm_uid, ip->i_mp->ntm_gid, file_mode, NULL, accmode));
}
int
@@ -439,7 +439,7 @@ ntfs_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
@@ -448,11 +448,11 @@ ntfs_access(void *v)
dprintf(("ntfs_access: %llu\n", (unsigned long long)ip->i_number));
- error = ntfs_check_possible(vp, ip, ap->a_mode);
+ error = ntfs_check_possible(vp, ip, ap->a_accmode);
if (error)
return error;
- error = ntfs_check_permitted(vp, ip, ap->a_mode, ap->a_cred);
+ error = ntfs_check_permitted(vp, ip, ap->a_accmode, ap->a_cred);
return error;
}
@@ -814,6 +814,7 @@ const struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
{ &vop_open_desc, (vop_t *) ntfs_open }, /* open */
{ &vop_close_desc,(vop_t *) ntfs_close }, /* close */
{ &vop_access_desc, (vop_t *) ntfs_access }, /* access */
+ { &vop_accessx_desc, (vop_t *) genfs_accessx }, /* accessx */
{ &vop_getattr_desc, (vop_t *) ntfs_getattr }, /* getattr */
{ &vop_setattr_desc, genfs_eopnotsupp }, /* setattr */
{ &vop_read_desc, (vop_t *) ntfs_read }, /* read */
diff --git a/sys/fs/ptyfs/ptyfs_vnops.c b/sys/fs/ptyfs/ptyfs_vnops.c
index a28358b110b..8a507b861d8 100644
--- a/sys/fs/ptyfs/ptyfs_vnops.c
+++ b/sys/fs/ptyfs/ptyfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ptyfs_vnops.c,v 1.58 2020/04/13 19:23:18 ad Exp $ */
+/* $NetBSD: ptyfs_vnops.c,v 1.59 2020/05/16 18:31:49 christos Exp $ */
/*
* Copyright (c) 1993, 1995
@@ -76,7 +76,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ptyfs_vnops.c,v 1.58 2020/04/13 19:23:18 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ptyfs_vnops.c,v 1.59 2020/05/16 18:31:49 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -172,6 +172,7 @@ const struct vnodeopv_entry_desc ptyfs_vnodeop_entries[] = {
{ &vop_open_desc, ptyfs_open }, /* open */
{ &vop_close_desc, ptyfs_close }, /* close */
{ &vop_access_desc, ptyfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, ptyfs_getattr }, /* getattr */
{ &vop_setattr_desc, ptyfs_setattr }, /* setattr */
{ &vop_read_desc, ptyfs_read }, /* read */
@@ -435,7 +436,7 @@ ptyfs_setattr(void *v)
}
error = kauth_authorize_vnode(cred, action, vp, NULL,
- genfs_can_chflags(cred, vp->v_type, ptyfs->ptyfs_uid,
+ genfs_can_chflags(vp, cred, ptyfs->ptyfs_uid,
changing_sysflags));
if (error)
return error;
@@ -469,8 +470,8 @@ ptyfs_setattr(void *v)
if ((ptyfs->ptyfs_flags & SF_SNAPSHOT) != 0)
return EPERM;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
- NULL, genfs_can_chtimes(vp, vap->va_vaflags,
- ptyfs->ptyfs_uid, cred));
+ NULL, genfs_can_chtimes(vp, cred, ptyfs->ptyfs_uid,
+ vap->va_vaflags));
if (error)
return (error);
if (vap->va_atime.tv_sec != VNOVAL)
@@ -516,8 +517,8 @@ ptyfs_chmod(struct vnode *vp, mode_t mode, kauth_cred_t cred, struct lwp *l)
int error;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp,
- NULL, genfs_can_chmod(vp->v_type, cred, ptyfs->ptyfs_uid,
- ptyfs->ptyfs_gid, mode));
+ NULL, genfs_can_chmod(vp, cred, ptyfs->ptyfs_uid, ptyfs->ptyfs_gid,
+ mode));
if (error)
return (error);
@@ -543,7 +544,7 @@ ptyfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred,
gid = ptyfs->ptyfs_gid;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp,
- NULL, genfs_can_chown(cred, ptyfs->ptyfs_uid, ptyfs->ptyfs_gid,
+ NULL, genfs_can_chown(vp, cred, ptyfs->ptyfs_uid, ptyfs->ptyfs_gid,
uid, gid));
if (error)
return (error);
@@ -567,7 +568,7 @@ ptyfs_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vattr va;
@@ -577,9 +578,9 @@ ptyfs_access(void *v)
return error;
return kauth_authorize_vnode(ap->a_cred,
- KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode),
- ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode, va.va_uid,
- va.va_gid, ap->a_mode, ap->a_cred));
+ KAUTH_ACCESS_ACTION(ap->a_accmode, ap->a_vp->v_type, va.va_mode),
+ ap->a_vp, NULL, genfs_can_access(ap->a_vp, ap->a_cred, va.va_uid,
+ va.va_gid, va.va_mode, NULL, ap->a_accmode));
}
/*
diff --git a/sys/fs/puffs/puffs_vnops.c b/sys/fs/puffs/puffs_vnops.c
index 40f40690f58..667ec01a563 100644
--- a/sys/fs/puffs/puffs_vnops.c
+++ b/sys/fs/puffs/puffs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: puffs_vnops.c,v 1.216 2020/05/15 19:28:10 maxv Exp $ */
+/* $NetBSD: puffs_vnops.c,v 1.217 2020/05/16 18:31:49 christos Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.216 2020/05/15 19:28:10 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.217 2020/05/16 18:31:49 christos Exp $");
#include <sys/param.h>
#include <sys/buf.h>
@@ -111,6 +111,7 @@ const struct vnodeopv_entry_desc puffs_vnodeop_entries[] = {
{ &vop_open_desc, puffs_vnop_open }, /* REAL open */
{ &vop_close_desc, puffs_vnop_checkop }, /* close */
{ &vop_access_desc, puffs_vnop_access }, /* REAL access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */
{ &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */
{ &vop_read_desc, puffs_vnop_checkop }, /* read */
@@ -168,6 +169,7 @@ const struct vnodeopv_entry_desc puffs_specop_entries[] = {
{ &vop_open_desc, spec_open }, /* spec_open */
{ &vop_close_desc, spec_close }, /* spec_close */
{ &vop_access_desc, puffs_vnop_checkop }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */
{ &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */
{ &vop_read_desc, puffs_vnop_spec_read }, /* update, read */
@@ -227,6 +229,7 @@ const struct vnodeopv_entry_desc puffs_fifoop_entries[] = {
{ &vop_open_desc, vn_fifo_bypass }, /* open */
{ &vop_close_desc, vn_fifo_bypass }, /* close */
{ &vop_access_desc, puffs_vnop_checkop }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */
{ &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */
{ &vop_read_desc, puffs_vnop_fifo_read }, /* read, update */
@@ -285,6 +288,7 @@ const struct vnodeopv_entry_desc puffs_msgop_entries[] = {
{ &vop_open_desc, puffs_vnop_open }, /* open */
{ &vop_close_desc, puffs_vnop_close }, /* close */
{ &vop_access_desc, puffs_vnop_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, puffs_vnop_getattr }, /* getattr */
{ &vop_setattr_desc, puffs_vnop_setattr }, /* setattr */
{ &vop_read_desc, puffs_vnop_read }, /* read */
@@ -959,16 +963,16 @@ puffs_vnop_access(void *v)
struct vop_access_args /* {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
PUFFS_MSG_VARS(vn, access);
struct vnode *vp = ap->a_vp;
struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
- int mode = ap->a_mode;
+ accmode_t accmode = ap->a_accmode;
int error;
- if (mode & VWRITE) {
+ if (accmode & VWRITE) {
switch (vp->v_type) {
case VDIR:
case VLNK:
@@ -986,7 +990,7 @@ puffs_vnop_access(void *v)
return 0;
PUFFS_MSG_ALLOC(vn, access);
- access_msg->pvnr_mode = ap->a_mode;
+ access_msg->pvnr_mode = ap->a_accmode;
puffs_credcvt(&access_msg->pvnr_cred, ap->a_cred);
puffs_msg_setinfo(park_access, PUFFSOP_VN,
PUFFS_VN_ACCESS, VPTOPNC(vp));
diff --git a/sys/fs/sysvbfs/sysvbfs.c b/sys/fs/sysvbfs/sysvbfs.c
index 549aecfb286..584ba71ed4c 100644
--- a/sys/fs/sysvbfs/sysvbfs.c
+++ b/sys/fs/sysvbfs/sysvbfs.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sysvbfs.c,v 1.17 2018/05/28 21:04:37 chs Exp $ */
+/* $NetBSD: sysvbfs.c,v 1.18 2020/05/16 18:31:49 christos Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysvbfs.c,v 1.17 2018/05/28 21:04:37 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysvbfs.c,v 1.18 2020/05/16 18:31:49 christos Exp $");
#include <sys/resource.h>
#include <sys/param.h>
@@ -55,6 +55,7 @@ const struct vnodeopv_entry_desc sysvbfs_vnodeop_entries[] = {
{ &vop_open_desc, sysvbfs_open }, /* open */
{ &vop_close_desc, sysvbfs_close }, /* close */
{ &vop_access_desc, sysvbfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, sysvbfs_getattr }, /* getattr */
{ &vop_setattr_desc, sysvbfs_setattr }, /* setattr */
{ &vop_read_desc, sysvbfs_read }, /* read */
diff --git a/sys/fs/sysvbfs/sysvbfs_vnops.c b/sys/fs/sysvbfs/sysvbfs_vnops.c
index 615fc76a504..496bedfea41 100644
--- a/sys/fs/sysvbfs/sysvbfs_vnops.c
+++ b/sys/fs/sysvbfs/sysvbfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sysvbfs_vnops.c,v 1.65 2020/04/23 21:47:08 ad Exp $ */
+/* $NetBSD: sysvbfs_vnops.c,v 1.66 2020/05/16 18:31:49 christos Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysvbfs_vnops.c,v 1.65 2020/04/23 21:47:08 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysvbfs_vnops.c,v 1.66 2020/05/16 18:31:49 christos Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -249,13 +249,13 @@ sysvbfs_check_possible(struct vnode *vp, struct sysvbfs_node *bnode,
static int
sysvbfs_check_permitted(struct vnode *vp, struct sysvbfs_node *bnode,
- mode_t mode, kauth_cred_t cred)
+ accmode_t accmode, kauth_cred_t cred)
{
struct bfs_fileattr *attr = &bnode->inode->attr;
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
- vp->v_type, attr->mode), vp, NULL, genfs_can_access(vp->v_type,
- attr->mode, attr->uid, attr->gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, attr->mode), vp, NULL, genfs_can_access(vp, cred,
+ attr->uid, attr->gid, attr->mode, NULL, accmode));
}
int
@@ -263,7 +263,7 @@ sysvbfs_access(void *arg)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = arg;
struct vnode *vp = ap->a_vp;
@@ -272,11 +272,11 @@ sysvbfs_access(void *arg)
DPRINTF("%s:\n", __func__);
- error = sysvbfs_check_possible(vp, bnode, ap->a_mode);
+ error = sysvbfs_check_possible(vp, bnode, ap->a_accmode);
if (error)
return error;
- error = sysvbfs_check_permitted(vp, bnode, ap->a_mode, ap->a_cred);
+ error = sysvbfs_check_permitted(vp, bnode, ap->a_accmode, ap->a_cred);
return error;
}
@@ -359,7 +359,7 @@ sysvbfs_setattr(void *arg)
(vap->va_gid != (gid_t)VNOVAL) ? vap->va_gid : attr->gid;
error = kauth_authorize_vnode(cred,
KAUTH_VNODE_CHANGE_OWNERSHIP, vp, NULL,
- genfs_can_chown(cred, attr->uid, attr->gid, uid, gid));
+ genfs_can_chown(vp, cred, attr->uid, attr->gid, uid, gid));
if (error)
return error;
attr->uid = uid;
@@ -386,7 +386,7 @@ sysvbfs_setattr(void *arg)
if (vap->va_mode != (mode_t)VNOVAL) {
mode_t mode = vap->va_mode;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY,
- vp, NULL, genfs_can_chmod(vp->v_type, cred, attr->uid,
+ vp, NULL, genfs_can_chmod(vp, cred, attr->uid,
attr->gid, mode));
if (error)
return error;
@@ -397,8 +397,8 @@ sysvbfs_setattr(void *arg)
(vap->va_mtime.tv_sec != VNOVAL) ||
(vap->va_ctime.tv_sec != VNOVAL)) {
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
- NULL, genfs_can_chtimes(vp, vap->va_vaflags, attr->uid,
- cred));
+ NULL, genfs_can_chtimes(vp, cred, attr->uid,
+ vap->va_vaflags));
if (error)
return error;
diff --git a/sys/fs/tmpfs/tmpfs_fifoops.c b/sys/fs/tmpfs/tmpfs_fifoops.c
index 7a6f7a7525f..41c5abdc628 100644
--- a/sys/fs/tmpfs/tmpfs_fifoops.c
+++ b/sys/fs/tmpfs/tmpfs_fifoops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: tmpfs_fifoops.c,v 1.11 2014/07/25 08:20:52 dholland Exp $ */
+/* $NetBSD: tmpfs_fifoops.c,v 1.12 2020/05/16 18:31:49 christos Exp $ */
/*
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_fifoops.c,v 1.11 2014/07/25 08:20:52 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_fifoops.c,v 1.12 2020/05/16 18:31:49 christos Exp $");
#include <sys/param.h>
#include <sys/vnode.h>
@@ -55,6 +55,7 @@ const struct vnodeopv_entry_desc tmpfs_fifoop_entries[] = {
{ &vop_open_desc, tmpfs_fifo_open },
{ &vop_close_desc, tmpfs_fifo_close },
{ &vop_access_desc, tmpfs_fifo_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_getattr_desc, tmpfs_fifo_getattr },
{ &vop_setattr_desc, tmpfs_fifo_setattr },
{ &vop_read_desc, tmpfs_fifo_read },
diff --git a/sys/fs/tmpfs/tmpfs_specops.c b/sys/fs/tmpfs/tmpfs_specops.c
index 051b9d37d7f..3686880d525 100644
--- a/sys/fs/tmpfs/tmpfs_specops.c
+++ b/sys/fs/tmpfs/tmpfs_specops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: tmpfs_specops.c,v 1.12 2014/07/25 08:20:52 dholland Exp $ */
+/* $NetBSD: tmpfs_specops.c,v 1.13 2020/05/16 18:31:49 christos Exp $ */
/*
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_specops.c,v 1.12 2014/07/25 08:20:52 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_specops.c,v 1.13 2020/05/16 18:31:49 christos Exp $");
#include <sys/param.h>
#include <sys/vnode.h>
@@ -58,6 +58,7 @@ const struct vnodeopv_entry_desc tmpfs_specop_entries[] = {
{ &vop_open_desc, tmpfs_spec_open },
{ &vop_close_desc, tmpfs_spec_close },
{ &vop_access_desc, tmpfs_spec_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_getattr_desc, tmpfs_spec_getattr },
{ &vop_setattr_desc, tmpfs_spec_setattr },
{ &vop_read_desc, tmpfs_spec_read },
diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c
index 67fe1b53107..033b90f369d 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: tmpfs_subr.c,v 1.110 2020/05/12 23:17:41 ad Exp $ */
+/* $NetBSD: tmpfs_subr.c,v 1.111 2020/05/16 18:31:49 christos Exp $ */
/*
* Copyright (c) 2005-2013 The NetBSD Foundation, Inc.
@@ -73,7 +73,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.110 2020/05/12 23:17:41 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.111 2020/05/16 18:31:49 christos Exp $");
#include <sys/param.h>
#include <sys/cprng.h>
@@ -988,8 +988,7 @@ tmpfs_chflags(vnode_t *vp, int flags, kauth_cred_t cred, lwp_t *l)
}
error = kauth_authorize_vnode(cred, action, vp, NULL,
- genfs_can_chflags(cred, vp->v_type, node->tn_uid,
- changing_sysflags));
+ genfs_can_chflags(vp, cred, node->tn_uid, changing_sysflags));
if (error)
return error;
@@ -1034,7 +1033,7 @@ tmpfs_chmod(vnode_t *vp, mode_t mode, kauth_cred_t cred, lwp_t *l)
return EPERM;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp,
- NULL, genfs_can_chmod(vp->v_type, cred, node->tn_uid, node->tn_gid, mode));
+ NULL, genfs_can_chmod(vp, cred, node->tn_uid, node->tn_gid, mode));
if (error) {
return error;
}
@@ -1077,7 +1076,7 @@ tmpfs_chown(vnode_t *vp, uid_t uid, gid_t gid, kauth_cred_t cred, lwp_t *l)
return EPERM;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp,
- NULL, genfs_can_chown(cred, node->tn_uid, node->tn_gid, uid,
+ NULL, genfs_can_chown(vp, cred, node->tn_uid, node->tn_gid, uid,
gid));
if (error) {
return error;
@@ -1164,7 +1163,7 @@ tmpfs_chtimes(vnode_t *vp, const struct timespec *atime,
return EPERM;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, NULL,
- genfs_can_chtimes(vp, vaflags, node->tn_uid, cred));
+ genfs_can_chtimes(vp, cred, node->tn_uid, vaflags));
if (error)
return error;
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index 8cb985ffa00..357be786ea1 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: tmpfs_vnops.c,v 1.137 2020/05/15 22:15:43 ad Exp $ */
+/* $NetBSD: tmpfs_vnops.c,v 1.138 2020/05/16 18:31:49 christos Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.137 2020/05/15 22:15:43 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.138 2020/05/16 18:31:49 christos Exp $");
#include <sys/param.h>
#include <sys/dirent.h>
@@ -70,6 +70,7 @@ const struct vnodeopv_entry_desc tmpfs_vnodeop_entries[] = {
{ &vop_open_desc, tmpfs_open },
{ &vop_close_desc, tmpfs_close },
{ &vop_access_desc, tmpfs_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_getattr_desc, tmpfs_getattr },
{ &vop_setattr_desc, tmpfs_setattr },
{ &vop_read_desc, tmpfs_read },
@@ -269,7 +270,7 @@ tmpfs_lookup(void *v)
if ((dnode->tn_mode & S_ISTXT) != 0) {
error = kauth_authorize_vnode(cnp->cn_cred,
KAUTH_VNODE_DELETE, tnode->tn_vnode,
- dnode->tn_vnode, genfs_can_sticky(cnp->cn_cred,
+ dnode->tn_vnode, genfs_can_sticky(dvp, cnp->cn_cred,
dnode->tn_uid, tnode->tn_uid));
if (error) {
error = EPERM;
@@ -377,14 +378,14 @@ tmpfs_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
vnode_t *vp = ap->a_vp;
- mode_t mode = ap->a_mode;
+ accmode_t accmode = ap->a_accmode;
kauth_cred_t cred = ap->a_cred;
tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
- const bool writing = (mode & VWRITE) != 0;
+ const bool writing = (accmode & VWRITE) != 0;
KASSERT(VOP_ISLOCKED(vp));
@@ -409,9 +410,9 @@ tmpfs_access(void *v)
return EPERM;
}
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
- vp->v_type, node->tn_mode), vp, NULL, genfs_can_access(vp->v_type,
- node->tn_mode, node->tn_uid, node->tn_gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, node->tn_mode), vp, NULL, genfs_can_access(vp, cred,
+ node->tn_uid, node->tn_gid, node->tn_mode, NULL, accmode));
}
int
diff --git a/sys/fs/udf/udf_vnops.c b/sys/fs/udf/udf_vnops.c
index 5cb22489b39..47c041cdf4e 100644
--- a/sys/fs/udf/udf_vnops.c
+++ b/sys/fs/udf/udf_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_vnops.c,v 1.112 2020/04/23 21:47:08 ad Exp $ */
+/* $NetBSD: udf_vnops.c,v 1.113 2020/05/16 18:31:50 christos Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.112 2020/04/23 21:47:08 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.113 2020/05/16 18:31:50 christos Exp $");
#endif /* not lint */
@@ -826,7 +826,7 @@ udf_lookup(void *v)
udf_getownership(dir_node, &d_uid, &d_gid);
error = kauth_authorize_vnode(cnp->cn_cred,
KAUTH_VNODE_DELETE, res_node->vnode,
- dir_node->vnode, genfs_can_sticky(cnp->cn_cred,
+ dir_node->vnode, genfs_can_sticky(dvp, cnp->cn_cred,
d_uid, d_uid));
if (error) {
error = EPERM;
@@ -1041,7 +1041,7 @@ udf_chown(struct vnode *vp, uid_t new_uid, gid_t new_gid,
/* check permissions */
error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP,
- vp, NULL, genfs_can_chown(cred, uid, gid, new_uid, new_gid));
+ vp, NULL, genfs_can_chown(vp, cred, uid, gid, new_uid, new_gid));
if (error)
return (error);
@@ -1078,7 +1078,7 @@ udf_chmod(struct vnode *vp, mode_t mode, kauth_cred_t cred)
/* check permissions */
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp,
- NULL, genfs_can_chmod(vp->v_type, cred, uid, gid, mode));
+ NULL, genfs_can_chmod(vp, cred, uid, gid, mode));
if (error)
return (error);
@@ -1187,7 +1187,7 @@ udf_chtimes(struct vnode *vp,
/* check permissions */
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
- NULL, genfs_can_chtimes(vp, setattrflags, uid, cred));
+ NULL, genfs_can_chtimes(vp, cred, uid, setattrflags));
if (error)
return (error);
@@ -1437,13 +1437,13 @@ udf_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode)
}
static int
-udf_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode,
+udf_check_permitted(struct vnode *vp, struct vattr *vap, accmode_t accmode,
kauth_cred_t cred)
{
/* ask the generic genfs_can_access to advice on security */
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
- vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp->v_type,
- vap->va_mode, vap->va_uid, vap->va_gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp, cred,
+ vap->va_uid, vap->va_gid, vap->va_mode, NULL, accmode));
}
int
@@ -1451,12 +1451,12 @@ udf_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
struct proc *a_p;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
- mode_t mode = ap->a_mode;
+ accmode_t accmode = ap->a_accmode;
kauth_cred_t cred = ap->a_cred;
/* struct udf_node *udf_node = VTOI(vp); */
struct vattr vap;
@@ -1468,11 +1468,11 @@ udf_access(void *v)
if (error)
return error;
- error = udf_check_possible(vp, &vap, mode);
+ error = udf_check_possible(vp, &vap, accmode);
if (error)
return error;
- error = udf_check_permitted(vp, &vap, mode, cred);
+ error = udf_check_permitted(vp, &vap, accmode, cred);
return error;
}
@@ -2179,6 +2179,7 @@ const struct vnodeopv_entry_desc udf_vnodeop_entries[] = {
{ &vop_open_desc, udf_open }, /* open */
{ &vop_close_desc, udf_close }, /* close */
{ &vop_access_desc, udf_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, udf_getattr }, /* getattr */
{ &vop_setattr_desc, udf_setattr }, /* setattr */ /* TODO chflags */
{ &vop_read_desc, udf_read }, /* read */
diff --git a/sys/fs/union/union_vnops.c b/sys/fs/union/union_vnops.c
index 80e64870cce..97fafbcb3a1 100644
--- a/sys/fs/union/union_vnops.c
+++ b/sys/fs/union/union_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: union_vnops.c,v 1.72 2020/02/23 15:46:41 ad Exp $ */
+/* $NetBSD: union_vnops.c,v 1.73 2020/05/16 18:31:50 christos Exp $ */
/*
* Copyright (c) 1992, 1993, 1994, 1995
@@ -72,7 +72,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.72 2020/02/23 15:46:41 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.73 2020/05/16 18:31:50 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -151,6 +151,7 @@ const struct vnodeopv_entry_desc union_vnodeop_entries[] = {
{ &vop_open_desc, union_open }, /* open */
{ &vop_close_desc, union_close }, /* close */
{ &vop_access_desc, union_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, union_getattr }, /* getattr */
{ &vop_setattr_desc, union_setattr }, /* setattr */
{ &vop_read_desc, union_read }, /* read */
@@ -708,7 +709,7 @@ union_access(void *v)
struct vop_access_args /* {
struct vnodeop_desc *a_desc;
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
@@ -721,7 +722,7 @@ union_access(void *v)
* unless the file is a socket, fifo, or a block or
* character device resident on the file system.
*/
- if (ap->a_mode & VWRITE) {
+ if (ap->a_accmode & VWRITE) {
switch (vp->v_type) {
case VDIR:
case VLNK:
diff --git a/sys/fs/unionfs/unionfs_vnops.c b/sys/fs/unionfs/unionfs_vnops.c
index 25864baa88f..37abb21c18e 100644
--- a/sys/fs/unionfs/unionfs_vnops.c
+++ b/sys/fs/unionfs/unionfs_vnops.c
@@ -1821,6 +1821,7 @@ const struct vnodeopv_entry_desc unionfs_vnodeop_entries[] = {
{ &vop_open_desc, unionfs_open }, /* open */
{ &vop_close_desc, unionfs_close }, /* close */
{ &vop_access_desc, unionfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, unionfs_getattr }, /* getattr */
{ &vop_setattr_desc, unionfs_setattr }, /* setattr */
{ &vop_read_desc, unionfs_read }, /* read */
diff --git a/sys/fs/v7fs/v7fs_extern.c b/sys/fs/v7fs/v7fs_extern.c
index 93fe79313a4..294f0f35e69 100644
--- a/sys/fs/v7fs/v7fs_extern.c
+++ b/sys/fs/v7fs/v7fs_extern.c
@@ -1,4 +1,4 @@
-/* $NetBSD: v7fs_extern.c,v 1.6 2018/05/28 21:04:38 chs Exp $ */
+/* $NetBSD: v7fs_extern.c,v 1.7 2020/05/16 18:31:50 christos Exp $ */
/*-
* Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: v7fs_extern.c,v 1.6 2018/05/28 21:04:38 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: v7fs_extern.c,v 1.7 2020/05/16 18:31:50 christos Exp $");
#if defined _KERNEL_OPT
#include "opt_v7fs.h"
@@ -61,6 +61,7 @@ const struct vnodeopv_entry_desc v7fs_vnodeop_entries[] = {
{ &vop_open_desc, v7fs_open }, /* open */
{ &vop_close_desc, v7fs_close }, /* close */
{ &vop_access_desc, v7fs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, v7fs_getattr }, /* getattr */
{ &vop_setattr_desc, v7fs_setattr }, /* setattr */
{ &vop_read_desc, v7fs_read }, /* read */
@@ -110,6 +111,7 @@ const struct vnodeopv_entry_desc v7fs_specop_entries[] = {
{ &vop_open_desc, spec_open }, /* open */
{ &vop_close_desc, spec_close }, /* close */
{ &vop_access_desc, v7fs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, v7fs_getattr }, /* getattr */
{ &vop_setattr_desc, v7fs_setattr }, /* setattr */
{ &vop_read_desc, spec_read }, /* read */
@@ -158,6 +160,7 @@ const struct vnodeopv_entry_desc v7fs_fifoop_entries[] = {
{ &vop_open_desc, vn_fifo_bypass }, /* open */
{ &vop_close_desc, vn_fifo_bypass }, /* close */
{ &vop_access_desc, v7fs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, v7fs_getattr }, /* getattr */
{ &vop_setattr_desc, v7fs_setattr }, /* setattr */
{ &vop_read_desc, vn_fifo_bypass }, /* read */
diff --git a/sys/fs/v7fs/v7fs_vnops.c b/sys/fs/v7fs/v7fs_vnops.c
index ae7f698f02c..72be7d4724e 100644
--- a/sys/fs/v7fs/v7fs_vnops.c
+++ b/sys/fs/v7fs/v7fs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: v7fs_vnops.c,v 1.29 2020/04/23 21:47:08 ad Exp $ */
+/* $NetBSD: v7fs_vnops.c,v 1.30 2020/05/16 18:31:50 christos Exp $ */
/*-
* Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: v7fs_vnops.c,v 1.29 2020/04/23 21:47:08 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: v7fs_vnops.c,v 1.30 2020/05/16 18:31:50 christos Exp $");
#if defined _KERNEL_OPT
#include "opt_v7fs.h"
#endif
@@ -372,33 +372,33 @@ v7fs_check_possible(struct vnode *vp, struct v7fs_node *v7node,
static int
v7fs_check_permitted(struct vnode *vp, struct v7fs_node *v7node,
- mode_t mode, kauth_cred_t cred)
+ accmode_t accmode, kauth_cred_t cred)
{
struct v7fs_inode *inode = &v7node->inode;
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
- vp->v_type, inode->mode), vp, NULL, genfs_can_access(vp->v_type,
- inode->mode, inode->uid, inode->gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, inode->mode), vp, NULL, genfs_can_access(vp, cred,
+ inode->uid, inode->gid, inode->mode, NULL, accmode));
}
int
v7fs_access(void *v)
{
struct vop_access_args /* {
- struct vnode *a_vp;
- int a_mode;
- kauth_cred_t a_cred;
- } */ *ap = v;
+ struct vnode *a_vp;
+ accmode_t a_accmode;
+ kauth_cred_t a_cred;
+ } */ *ap = v;
struct vnode *vp = ap->a_vp;
struct v7fs_node *v7node = vp->v_data;
int error;
- error = v7fs_check_possible(vp, v7node, ap->a_mode);
+ error = v7fs_check_possible(vp, v7node, ap->a_accmode);
if (error)
return error;
- error = v7fs_check_permitted(vp, v7node, ap->a_mode, ap->a_cred);
+ error = v7fs_check_permitted(vp, v7node, ap->a_accmode, ap->a_cred);
return error;
}
@@ -492,7 +492,7 @@ v7fs_setattr(void *v)
/* File pointer mode. */
if (vap->va_flags != VNOVAL) {
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS,
- vp, NULL, genfs_can_chflags(cred, vp->v_type, inode->uid,
+ vp, NULL, genfs_can_chflags(vp, cred, inode->uid,
false));
if (error)
return error;
@@ -515,7 +515,7 @@ v7fs_setattr(void *v)
uid = vap->va_uid;
error = kauth_authorize_vnode(cred,
KAUTH_VNODE_CHANGE_OWNERSHIP, vp, NULL,
- genfs_can_chown(cred, inode->uid, inode->gid, uid,
+ genfs_can_chown(vp, cred, inode->uid, inode->gid, uid,
gid));
if (error)
return error;
@@ -525,7 +525,7 @@ v7fs_setattr(void *v)
gid = vap->va_gid;
error = kauth_authorize_vnode(cred,
KAUTH_VNODE_CHANGE_OWNERSHIP, vp, NULL,
- genfs_can_chown(cred, inode->uid, inode->gid, uid,
+ genfs_can_chown(vp, cred, inode->uid, inode->gid, uid,
gid));
if (error)
return error;
@@ -534,7 +534,7 @@ v7fs_setattr(void *v)
if (vap->va_mode != (mode_t)VNOVAL) {
mode_t mode = vap->va_mode;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY,
- vp, NULL, genfs_can_chmod(vp->v_type, cred, inode->uid, inode->gid,
+ vp, NULL, genfs_can_chmod(vp, cred, inode->uid, inode->gid,
mode));
if (error) {
return error;
@@ -545,8 +545,8 @@ v7fs_setattr(void *v)
(vap->va_mtime.tv_sec != VNOVAL) ||
(vap->va_ctime.tv_sec != VNOVAL)) {
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
- NULL, genfs_can_chtimes(vp, vap->va_vaflags, inode->uid,
- cred));
+ NULL, genfs_can_chtimes(vp, cred, inode->uid,
+ vap->va_vaflags));
if (error)
return error;
diff --git a/sys/kern/files.kern b/sys/kern/files.kern
index 8ace446adf8..b3c6ddf4516 100644
--- a/sys/kern/files.kern
+++ b/sys/kern/files.kern
@@ -1,4 +1,4 @@
-# $NetBSD: files.kern,v 1.47 2020/04/30 03:28:18 riastradh Exp $
+# $NetBSD: files.kern,v 1.48 2020/05/16 18:31:50 christos Exp $
#
# kernel sources
@@ -96,6 +96,8 @@ file kern/kern_uuid.c kern
file kern/kgdb_stub.c kgdb
file kern/sched_4bsd.c sched_4bsd
file kern/sched_m2.c sched_m2
+file kern/subr_acl_posix1e.c kern
+file kern/subr_acl_nfs4.c kern
file kern/subr_asan.c kasan
file kern/subr_autoconf.c kern
file kern/subr_blist.c vmswap
@@ -192,6 +194,7 @@ file kern/uipc_syscalls.c kern
file kern/uipc_usrreq.c kern
define vfs: kern
+file kern/vfs_acl.c vfs
file kern/vfs_bio.c vfs
file kern/vfs_cache.c vfs
file kern/vfs_cwd.c vfs
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
index 0d4427998dd..b477ce7b32e 100644
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -1,4 +1,4 @@
-/* $NetBSD: init_sysent.c,v 1.331 2020/04/26 19:16:36 thorpej Exp $ */
+/* $NetBSD: init_sysent.c,v 1.332 2020/05/16 18:31:50 christos Exp $ */
/*
* System call switch table.
@@ -8,7 +8,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: init_sysent.c,v 1.331 2020/04/26 19:16:36 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: init_sysent.c,v 1.332 2020/05/16 18:31:50 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_modular.h"
@@ -23,6 +23,7 @@ __KERNEL_RCSID(0, "$NetBSD: init_sysent.c,v 1.331 2020/04/26 19:16:36 thorpej Ex
#include <sys/sched.h>
#include <sys/idtype.h>
#include <sys/syscallargs.h>
+#include <sys/acl.h>
#ifdef COMPAT_43
#define compat_43(func) __CONCAT(compat_43_,func)
@@ -2365,44 +2366,69 @@ struct sysent sysent[] = {
.sy_call = (sy_call_t *)sys___fhstatvfs190
}, /* 486 = __fhstatvfs190 */
{
- .sy_call = sys_nosys,
- }, /* 487 = filler */
+ ns(struct sys___acl_get_link_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys___acl_get_link
+ }, /* 487 = __acl_get_link */
{
- .sy_call = sys_nosys,
- }, /* 488 = filler */
+ ns(struct sys___acl_set_link_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys___acl_set_link
+ }, /* 488 = __acl_set_link */
{
- .sy_call = sys_nosys,
- }, /* 489 = filler */
+ ns(struct sys___acl_delete_link_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys___acl_delete_link
+ }, /* 489 = __acl_delete_link */
{
- .sy_call = sys_nosys,
- }, /* 490 = filler */
+ ns(struct sys___acl_aclcheck_link_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys___acl_aclcheck_link
+ }, /* 490 = __acl_aclcheck_link */
{
- .sy_call = sys_nosys,
- }, /* 491 = filler */
+ ns(struct sys___acl_get_file_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys___acl_get_file
+ }, /* 491 = __acl_get_file */
{
- .sy_call = sys_nosys,
- }, /* 492 = filler */
+ ns(struct sys___acl_set_file_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys___acl_set_file
+ }, /* 492 = __acl_set_file */
{
- .sy_call = sys_nosys,
- }, /* 493 = filler */
+ ns(struct sys___acl_get_fd_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys___acl_get_fd
+ }, /* 493 = __acl_get_fd */
{
- .sy_call = sys_nosys,
- }, /* 494 = filler */
+ ns(struct sys___acl_set_fd_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys___acl_set_fd
+ }, /* 494 = __acl_set_fd */
{
- .sy_call = sys_nosys,
- }, /* 495 = filler */
+ ns(struct sys___acl_delete_file_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys___acl_delete_file
+ }, /* 495 = __acl_delete_file */
{
- .sy_call = sys_nosys,
- }, /* 496 = filler */
+ ns(struct sys___acl_delete_fd_args),
+ .sy_call = (sy_call_t *)sys___acl_delete_fd
+ }, /* 496 = __acl_delete_fd */
{
- .sy_call = sys_nosys,
- }, /* 497 = filler */
+ ns(struct sys___acl_aclcheck_file_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys___acl_aclcheck_file
+ }, /* 497 = __acl_aclcheck_file */
{
- .sy_call = sys_nosys,
- }, /* 498 = filler */
+ ns(struct sys___acl_aclcheck_fd_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys___acl_aclcheck_fd
+ }, /* 498 = __acl_aclcheck_fd */
{
- .sy_call = sys_nosys,
- }, /* 499 = filler */
+ ns(struct sys_lpathconf_args),
+ .sy_flags = SYCALL_ARG_PTR,
+ .sy_call = (sy_call_t *)sys_lpathconf
+ }, /* 499 = lpathconf */
{
.sy_call = sys_nosys,
}, /* 500 = filler */
diff --git a/sys/kern/kern_auth.c b/sys/kern/kern_auth.c
index dd2b95985bb..0b49deb3b87 100644
--- a/sys/kern/kern_auth.c
+++ b/sys/kern/kern_auth.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_auth.c,v 1.77 2018/09/03 16:29:35 riastradh Exp $ */
+/* $NetBSD: kern_auth.c,v 1.78 2020/05/16 18:31:50 christos Exp $ */
/*-
* Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org>
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.77 2018/09/03 16:29:35 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.78 2020/05/16 18:31:50 christos Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -1090,18 +1090,19 @@ kauth_authorize_device_passthru(kauth_cred_t cred, dev_t dev, u_long bits,
}
kauth_action_t
-kauth_mode_to_action(mode_t mode)
+kauth_accmode_to_action(accmode_t accmode)
{
kauth_action_t action = 0;
- if (mode & VREAD)
+ // XXX: Revisit we need to have a richer set of kauth primitives
+ // We also get only the Unix perms here sometimes
+ if (accmode & (VSTAT_PERMS|VREAD))
action |= KAUTH_VNODE_READ_DATA;
- if (mode & VWRITE)
+ if (accmode & (VMODIFY_PERMS|VADMIN_PERMS))
action |= KAUTH_VNODE_WRITE_DATA;
- if (mode & VEXEC)
+ if (accmode & VEXEC)
action |= KAUTH_VNODE_EXECUTE;
-
- return action;
+ return action == 0 ? KAUTH_VNODE_ACCESS : action;
}
kauth_action_t
diff --git a/sys/kern/subr_acl_nfs4.c b/sys/kern/subr_acl_nfs4.c
new file mode 100644
index 00000000000..21d19daf59f
--- /dev/null
+++ b/sys/kern/subr_acl_nfs4.c
@@ -0,0 +1,614 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2008-2010 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+/*
+ * ACL support routines specific to NFSv4 access control lists. These are
+ * utility routines for code common across file systems implementing NFSv4
+ * ACLs.
+ */
+
+#ifdef _KERNEL
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/sys/kern/subr_acl_nfs4.c 341827 2018-12-11 19:32:16Z mjg $");
+#endif
+__KERNEL_RCSID(0, "$NetBSD: subr_acl_nfs4.c,v 1.1 2020/05/16 18:31:50 christos Exp $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/acl.h>
+#include <sys/kauth.h>
+
+static void acl_nfs4_trivial_from_mode(struct acl *aclp, mode_t mode);
+
+
+#else
+
+#include <errno.h>
+#include <assert.h>
+#include <sys/acl.h>
+#include <sys/stat.h>
+#define KASSERT(a) assert(a)
+
+#endif /* !_KERNEL */
+
+#if 0
+static int
+_acl_entry_matches(struct acl_entry *ae, acl_tag_t tag, acl_perm_t perm,
+ acl_entry_type_t entry_type)
+{
+ if (ae->ae_tag != tag)
+ return (0);
+
+ if (ae->ae_id != ACL_UNDEFINED_ID)
+ return (0);
+
+ if (ae->ae_perm != perm)
+ return (0);
+
+ if (ae->ae_entry_type != entry_type)
+ return (0);
+
+ if (ae->ae_flags != 0)
+ return (0);
+
+ return (1);
+}
+#endif
+
+static struct acl_entry *
+_acl_append(struct acl *aclp, acl_tag_t tag, acl_perm_t perm,
+ acl_entry_type_t entry_type)
+{
+ struct acl_entry *ae;
+
+ KASSERT(aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES);
+
+ ae = &(aclp->acl_entry[aclp->acl_cnt]);
+ aclp->acl_cnt++;
+
+ ae->ae_tag = tag;
+ ae->ae_id = ACL_UNDEFINED_ID;
+ ae->ae_perm = perm;
+ ae->ae_entry_type = entry_type;
+ ae->ae_flags = 0;
+
+ return (ae);
+}
+
+#if 0
+static struct acl_entry *
+_acl_duplicate_entry(struct acl *aclp, unsigned int entry_index)
+{
+ size_t i;
+
+ KASSERT(aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES);
+
+ for (i = aclp->acl_cnt; i > entry_index; i--)
+ aclp->acl_entry[i] = aclp->acl_entry[i - 1];
+
+ aclp->acl_cnt++;
+
+ return (&(aclp->acl_entry[entry_index + 1]));
+}
+#endif
+
+
+#ifdef _KERNEL
+void
+acl_nfs4_sync_acl_from_mode(struct acl *aclp, mode_t mode,
+ int file_owner_id)
+{
+
+ acl_nfs4_trivial_from_mode(aclp, mode);
+}
+#endif /* _KERNEL */
+
+void
+__acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp)
+{
+ size_t i;
+ mode_t old_mode = *_mode, mode = 0, seen = 0;
+ const struct acl_entry *ae;
+
+ KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES);
+
+ /*
+ * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt
+ *
+ * 3.16.6.1. Recomputing mode upon SETATTR of ACL
+ */
+
+ for (i = 0; i < aclp->acl_cnt; i++) {
+ ae = &(aclp->acl_entry[i]);
+
+ if (ae->ae_entry_type != ACL_ENTRY_TYPE_ALLOW &&
+ ae->ae_entry_type != ACL_ENTRY_TYPE_DENY)
+ continue;
+
+ if (ae->ae_flags & ACL_ENTRY_INHERIT_ONLY)
+ continue;
+
+ if (ae->ae_tag == ACL_USER_OBJ) {
+ if ((ae->ae_perm & ACL_READ_DATA) &&
+ ((seen & S_IRUSR) == 0)) {
+ seen |= S_IRUSR;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IRUSR;
+ }
+ if ((ae->ae_perm & ACL_WRITE_DATA) &&
+ ((seen & S_IWUSR) == 0)) {
+ seen |= S_IWUSR;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IWUSR;
+ }
+ if ((ae->ae_perm & ACL_EXECUTE) &&
+ ((seen & S_IXUSR) == 0)) {
+ seen |= S_IXUSR;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IXUSR;
+ }
+ } else if (ae->ae_tag == ACL_GROUP_OBJ) {
+ if ((ae->ae_perm & ACL_READ_DATA) &&
+ ((seen & S_IRGRP) == 0)) {
+ seen |= S_IRGRP;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IRGRP;
+ }
+ if ((ae->ae_perm & ACL_WRITE_DATA) &&
+ ((seen & S_IWGRP) == 0)) {
+ seen |= S_IWGRP;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IWGRP;
+ }
+ if ((ae->ae_perm & ACL_EXECUTE) &&
+ ((seen & S_IXGRP) == 0)) {
+ seen |= S_IXGRP;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IXGRP;
+ }
+ } else if (ae->ae_tag == ACL_EVERYONE) {
+ if (ae->ae_perm & ACL_READ_DATA) {
+ if ((seen & S_IRUSR) == 0) {
+ seen |= S_IRUSR;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IRUSR;
+ }
+ if ((seen & S_IRGRP) == 0) {
+ seen |= S_IRGRP;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IRGRP;
+ }
+ if ((seen & S_IROTH) == 0) {
+ seen |= S_IROTH;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IROTH;
+ }
+ }
+ if (ae->ae_perm & ACL_WRITE_DATA) {
+ if ((seen & S_IWUSR) == 0) {
+ seen |= S_IWUSR;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IWUSR;
+ }
+ if ((seen & S_IWGRP) == 0) {
+ seen |= S_IWGRP;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IWGRP;
+ }
+ if ((seen & S_IWOTH) == 0) {
+ seen |= S_IWOTH;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IWOTH;
+ }
+ }
+ if (ae->ae_perm & ACL_EXECUTE) {
+ if ((seen & S_IXUSR) == 0) {
+ seen |= S_IXUSR;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IXUSR;
+ }
+ if ((seen & S_IXGRP) == 0) {
+ seen |= S_IXGRP;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IXGRP;
+ }
+ if ((seen & S_IXOTH) == 0) {
+ seen |= S_IXOTH;
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
+ mode |= S_IXOTH;
+ }
+ }
+ }
+ }
+
+ *_mode = mode | (old_mode & ACL_PRESERVE_MASK);
+}
+
+/*
+ * Populate the ACL with entries inherited from parent_aclp.
+ */
+static void
+acl_nfs4_inherit_entries(const struct acl *parent_aclp,
+ struct acl *child_aclp, mode_t mode, int file_owner_id,
+ int is_directory)
+{
+ int flags, tag;
+ size_t i;
+ const struct acl_entry *parent_entry;
+ struct acl_entry *ae;
+
+ KASSERT(parent_aclp->acl_cnt <= ACL_MAX_ENTRIES);
+
+ for (i = 0; i < parent_aclp->acl_cnt; i++) {
+ parent_entry = &(parent_aclp->acl_entry[i]);
+ flags = parent_entry->ae_flags;
+ tag = parent_entry->ae_tag;
+
+ /*
+ * Don't inherit owner@, group@, or everyone@ entries.
+ */
+ if (tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ ||
+ tag == ACL_EVERYONE)
+ continue;
+
+ /*
+ * Entry is not inheritable at all.
+ */
+ if ((flags & (ACL_ENTRY_DIRECTORY_INHERIT |
+ ACL_ENTRY_FILE_INHERIT)) == 0)
+ continue;
+
+ /*
+ * We're creating a file, but ae is not inheritable
+ * by files.
+ */
+ if (!is_directory && (flags & ACL_ENTRY_FILE_INHERIT) == 0)
+ continue;
+
+ /*
+ * Entry is inheritable only by files, but has NO_PROPAGATE
+ * flag set, and we're creating a directory, so it wouldn't
+ * propagate to any file in that directory anyway.
+ */
+ if (is_directory &&
+ (flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0 &&
+ (flags & ACL_ENTRY_NO_PROPAGATE_INHERIT))
+ continue;
+
+ /*
+ * Entry qualifies for being inherited.
+ */
+ KASSERT(child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES);
+ ae = &(child_aclp->acl_entry[child_aclp->acl_cnt]);
+ *ae = *parent_entry;
+ child_aclp->acl_cnt++;
+
+ ae->ae_flags &= ~ACL_ENTRY_INHERIT_ONLY;
+ ae->ae_flags |= ACL_ENTRY_INHERITED;
+
+ /*
+ * If the type of the ACE is neither ALLOW nor DENY,
+ * then leave it as it is and proceed to the next one.
+ */
+ if (ae->ae_entry_type != ACL_ENTRY_TYPE_ALLOW &&
+ ae->ae_entry_type != ACL_ENTRY_TYPE_DENY)
+ continue;
+
+ /*
+ * If the ACL_ENTRY_NO_PROPAGATE_INHERIT is set, or if
+ * the object being created is not a directory, then clear
+ * the following flags: ACL_ENTRY_NO_PROPAGATE_INHERIT,
+ * ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT,
+ * ACL_ENTRY_INHERIT_ONLY.
+ */
+ if (ae->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT ||
+ !is_directory) {
+ ae->ae_flags &= ~(ACL_ENTRY_NO_PROPAGATE_INHERIT |
+ ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT |
+ ACL_ENTRY_INHERIT_ONLY);
+ }
+
+ /*
+ * If the object is a directory and ACL_ENTRY_FILE_INHERIT
+ * is set, but ACL_ENTRY_DIRECTORY_INHERIT is not set, ensure
+ * that ACL_ENTRY_INHERIT_ONLY is set.
+ */
+ if (is_directory &&
+ (ae->ae_flags & ACL_ENTRY_FILE_INHERIT) &&
+ ((ae->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0)) {
+ ae->ae_flags |= ACL_ENTRY_INHERIT_ONLY;
+ }
+
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_ALLOW &&
+ (ae->ae_flags & ACL_ENTRY_INHERIT_ONLY) == 0) {
+ /*
+ * Some permissions must never be inherited.
+ */
+ ae->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER |
+ ACL_WRITE_NAMED_ATTRS | ACL_WRITE_ATTRIBUTES);
+
+ /*
+ * Others must be masked according to the file mode.
+ */
+ if ((mode & S_IRGRP) == 0)
+ ae->ae_perm &= ~ACL_READ_DATA;
+ if ((mode & S_IWGRP) == 0)
+ ae->ae_perm &=
+ ~(ACL_WRITE_DATA | ACL_APPEND_DATA);
+ if ((mode & S_IXGRP) == 0)
+ ae->ae_perm &= ~ACL_EXECUTE;
+ }
+ }
+}
+
+/*
+ * Calculate inherited ACL in a manner compatible with PSARC/2010/029.
+ * It's also being used to calculate a trivial ACL, by inheriting from
+ * a NULL ACL.
+ */
+static void
+acl_nfs4_compute_inherited_acl_psarc(const struct acl *parent_aclp,
+ struct acl *aclp, mode_t mode, int file_owner_id, int is_directory)
+{
+ acl_perm_t user_allow_first = 0, user_deny = 0, group_deny = 0;
+ acl_perm_t user_allow, group_allow, everyone_allow;
+
+ KASSERT(aclp->acl_cnt == 0);
+
+ user_allow = group_allow = everyone_allow = ACL_READ_ACL |
+ ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS | ACL_SYNCHRONIZE;
+ user_allow |= ACL_WRITE_ACL | ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES |
+ ACL_WRITE_NAMED_ATTRS;
+
+ if (mode & S_IRUSR)
+ user_allow |= ACL_READ_DATA;
+ if (mode & S_IWUSR)
+ user_allow |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
+ if (mode & S_IXUSR)
+ user_allow |= ACL_EXECUTE;
+
+ if (mode & S_IRGRP)
+ group_allow |= ACL_READ_DATA;
+ if (mode & S_IWGRP)
+ group_allow |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
+ if (mode & S_IXGRP)
+ group_allow |= ACL_EXECUTE;
+
+ if (mode & S_IROTH)
+ everyone_allow |= ACL_READ_DATA;
+ if (mode & S_IWOTH)
+ everyone_allow |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
+ if (mode & S_IXOTH)
+ everyone_allow |= ACL_EXECUTE;
+
+ user_deny = ((group_allow | everyone_allow) & ~user_allow);
+ group_deny = everyone_allow & ~group_allow;
+ user_allow_first = group_deny & ~user_deny;
+
+ if (user_allow_first != 0)
+ _acl_append(aclp, ACL_USER_OBJ, user_allow_first,
+ ACL_ENTRY_TYPE_ALLOW);
+ if (user_deny != 0)
+ _acl_append(aclp, ACL_USER_OBJ, user_deny,
+ ACL_ENTRY_TYPE_DENY);
+ if (group_deny != 0)
+ _acl_append(aclp, ACL_GROUP_OBJ, group_deny,
+ ACL_ENTRY_TYPE_DENY);
+
+ if (parent_aclp != NULL)
+ acl_nfs4_inherit_entries(parent_aclp, aclp, mode,
+ file_owner_id, is_directory);
+
+ _acl_append(aclp, ACL_USER_OBJ, user_allow, ACL_ENTRY_TYPE_ALLOW);
+ _acl_append(aclp, ACL_GROUP_OBJ, group_allow, ACL_ENTRY_TYPE_ALLOW);
+ _acl_append(aclp, ACL_EVERYONE, everyone_allow, ACL_ENTRY_TYPE_ALLOW);
+}
+
+#ifdef _KERNEL
+void
+acl_nfs4_compute_inherited_acl(const struct acl *parent_aclp,
+ struct acl *child_aclp, mode_t mode, int file_owner_id,
+ int is_directory)
+{
+
+ acl_nfs4_compute_inherited_acl_psarc(parent_aclp, child_aclp,
+ mode, file_owner_id, is_directory);
+}
+#endif /* _KERNEL */
+
+/*
+ * Calculate trivial ACL in a manner compatible with PSARC/2010/029.
+ * Note that this results in an ACL different from (but semantically
+ * equal to) the "canonical six" trivial ACL computed using algorithm
+ * described in draft-ietf-nfsv4-minorversion1-03.txt, 3.16.6.2.
+ */
+static void
+acl_nfs4_trivial_from_mode(struct acl *aclp, mode_t mode)
+{
+
+ aclp->acl_cnt = 0;
+ acl_nfs4_compute_inherited_acl_psarc(NULL, aclp, mode, -1, -1);
+}
+
+#ifndef _KERNEL
+/*
+ * This routine is used by libc to implement acl_strip_np(3)
+ * and acl_is_trivial_np(3).
+ */
+void
+__acl_nfs4_trivial_from_mode_libc(struct acl *aclp, int mode, int canonical_six)
+{
+
+ aclp->acl_cnt = 0;
+ acl_nfs4_trivial_from_mode(aclp, mode);
+}
+#endif /* !_KERNEL */
+
+#ifdef _KERNEL
+static int
+_acls_are_equal(const struct acl *a, const struct acl *b)
+{
+ int i;
+ const struct acl_entry *entrya, *entryb;
+
+ if (a->acl_cnt != b->acl_cnt)
+ return (0);
+
+ for (i = 0; i < b->acl_cnt; i++) {
+ entrya = &(a->acl_entry[i]);
+ entryb = &(b->acl_entry[i]);
+
+ if (entrya->ae_tag != entryb->ae_tag ||
+ entrya->ae_id != entryb->ae_id ||
+ entrya->ae_perm != entryb->ae_perm ||
+ entrya->ae_entry_type != entryb->ae_entry_type ||
+ entrya->ae_flags != entryb->ae_flags)
+ return (0);
+ }
+
+ return (1);
+}
+
+/*
+ * This routine is used to determine whether to remove extended attribute
+ * that stores ACL contents.
+ */
+int
+acl_nfs4_is_trivial(const struct acl *aclp, int file_owner_id)
+{
+ int trivial;
+ mode_t tmpmode = 0;
+ struct acl *tmpaclp;
+
+ if (aclp->acl_cnt > 6)
+ return (0);
+
+ /*
+ * Compute the mode from the ACL, then compute new ACL from that mode.
+ * If the ACLs are identical, then the ACL is trivial.
+ *
+ * XXX: I guess there is a faster way to do this. However, even
+ * this slow implementation significantly speeds things up
+ * for files that don't have non-trivial ACLs - it's critical
+ * for performance to not use EA when they are not needed.
+ *
+ * First try the PSARC/2010/029 semantics.
+ */
+ tmpaclp = acl_alloc(KM_SLEEP);
+ __acl_nfs4_sync_mode_from_acl(&tmpmode, aclp);
+ acl_nfs4_trivial_from_mode(tmpaclp, tmpmode);
+ trivial = _acls_are_equal(aclp, tmpaclp);
+ if (trivial) {
+ acl_free(tmpaclp);
+ return (trivial);
+ }
+
+ /*
+ * Check if it's a draft-ietf-nfsv4-minorversion1-03.txt trivial ACL.
+ */
+ acl_free(tmpaclp);
+
+ return (trivial);
+}
+
+int
+acl_nfs4_check(const struct acl *aclp, int is_directory)
+{
+ size_t i;
+ const struct acl_entry *ae;
+
+ /*
+ * The spec doesn't seem to say anything about ACL validity.
+ * It seems there is not much to do here. There is even no need
+ * to count "owner@" or "everyone@" (ACL_USER_OBJ and ACL_EVERYONE)
+ * entries, as there can be several of them and that's perfectly
+ * valid. There can be none of them too. Really.
+ */
+
+ if (aclp->acl_cnt > ACL_MAX_ENTRIES || aclp->acl_cnt <= 0)
+ return (EINVAL);
+
+ for (i = 0; i < aclp->acl_cnt; i++) {
+ ae = &(aclp->acl_entry[i]);
+
+ switch (ae->ae_tag) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_EVERYONE:
+ if (ae->ae_id != ACL_UNDEFINED_ID)
+ return (EINVAL);
+ break;
+
+ case ACL_USER:
+ case ACL_GROUP:
+ if (ae->ae_id == ACL_UNDEFINED_ID)
+ return (EINVAL);
+ break;
+
+ default:
+ return (EINVAL);
+ }
+
+ if ((ae->ae_perm | ACL_NFS4_PERM_BITS) != ACL_NFS4_PERM_BITS)
+ return (EINVAL);
+
+ /*
+ * Disallow ACL_ENTRY_TYPE_AUDIT and ACL_ENTRY_TYPE_ALARM for now.
+ */
+ if (ae->ae_entry_type != ACL_ENTRY_TYPE_ALLOW &&
+ ae->ae_entry_type != ACL_ENTRY_TYPE_DENY)
+ return (EINVAL);
+
+ if ((ae->ae_flags | ACL_FLAGS_BITS) != ACL_FLAGS_BITS)
+ return (EINVAL);
+
+ /* Disallow unimplemented flags. */
+ if (ae->ae_flags & (ACL_ENTRY_SUCCESSFUL_ACCESS |
+ ACL_ENTRY_FAILED_ACCESS))
+ return (EINVAL);
+
+ /* Disallow flags not allowed for ordinary files. */
+ if (!is_directory) {
+ if (ae->ae_flags & (ACL_ENTRY_FILE_INHERIT |
+ ACL_ENTRY_DIRECTORY_INHERIT |
+ ACL_ENTRY_NO_PROPAGATE_INHERIT | ACL_ENTRY_INHERIT_ONLY))
+ return (EINVAL);
+ }
+ }
+
+ return (0);
+}
+#endif
diff --git a/sys/kern/subr_acl_posix1e.c b/sys/kern/subr_acl_posix1e.c
new file mode 100644
index 00000000000..99f5bb49aa7
--- /dev/null
+++ b/sys/kern/subr_acl_posix1e.c
@@ -0,0 +1,338 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999-2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * Developed by the TrustedBSD Project.
+ *
+ * ACL support routines specific to POSIX.1e access control lists. These are
+ * utility routines for code common across file systems implementing POSIX.1e
+ * ACLs.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/sys/kern/subr_acl_posix1e.c 341827 2018-12-11 19:32:16Z mjg $");
+#endif
+__KERNEL_RCSID(0, "$NetBSD: subr_acl_posix1e.c,v 1.1 2020/05/16 18:31:50 christos Exp $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/kauth.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <sys/acl.h>
+
+/*
+ * For the purposes of filesystems maintaining the _OBJ entries in an inode
+ * with a mode_t field, this routine converts a mode_t entry to an
+ * acl_perm_t.
+ */
+acl_perm_t
+acl_posix1e_mode_to_perm(acl_tag_t tag, mode_t mode)
+{
+ acl_perm_t perm = 0;
+
+ switch(tag) {
+ case ACL_USER_OBJ:
+ if (mode & S_IXUSR)
+ perm |= ACL_EXECUTE;
+ if (mode & S_IRUSR)
+ perm |= ACL_READ;
+ if (mode & S_IWUSR)
+ perm |= ACL_WRITE;
+ return (perm);
+
+ case ACL_GROUP_OBJ:
+ if (mode & S_IXGRP)
+ perm |= ACL_EXECUTE;
+ if (mode & S_IRGRP)
+ perm |= ACL_READ;
+ if (mode & S_IWGRP)
+ perm |= ACL_WRITE;
+ return (perm);
+
+ case ACL_OTHER:
+ if (mode & S_IXOTH)
+ perm |= ACL_EXECUTE;
+ if (mode & S_IROTH)
+ perm |= ACL_READ;
+ if (mode & S_IWOTH)
+ perm |= ACL_WRITE;
+ return (perm);
+
+ default:
+ printf("%s: invalid tag (%u)\n", __func__, tag);
+ return (0);
+ }
+}
+
+/*
+ * Given inode information (uid, gid, mode), return an acl entry of the
+ * appropriate type.
+ */
+struct acl_entry
+acl_posix1e_mode_to_entry(acl_tag_t tag, uid_t uid, gid_t gid, mode_t mode)
+{
+ struct acl_entry acl_entry;
+
+ acl_entry.ae_tag = tag;
+ acl_entry.ae_perm = acl_posix1e_mode_to_perm(tag, mode);
+ acl_entry.ae_entry_type = 0;
+ acl_entry.ae_flags = 0;
+ switch(tag) {
+ case ACL_USER_OBJ:
+ acl_entry.ae_id = uid;
+ break;
+
+ case ACL_GROUP_OBJ:
+ acl_entry.ae_id = gid;
+ break;
+
+ case ACL_OTHER:
+ acl_entry.ae_id = ACL_UNDEFINED_ID;
+ break;
+
+ default:
+ acl_entry.ae_id = ACL_UNDEFINED_ID;
+ printf("acl_posix1e_mode_to_entry: invalid tag (%d)\n", tag);
+ }
+
+ return (acl_entry);
+}
+
+/*
+ * Utility function to generate a file mode given appropriate ACL entries.
+ */
+mode_t
+acl_posix1e_perms_to_mode(struct acl_entry *acl_user_obj_entry,
+ struct acl_entry *acl_group_obj_entry, struct acl_entry *acl_other_entry)
+{
+ mode_t mode;
+
+ mode = 0;
+ if (acl_user_obj_entry->ae_perm & ACL_EXECUTE)
+ mode |= S_IXUSR;
+ if (acl_user_obj_entry->ae_perm & ACL_READ)
+ mode |= S_IRUSR;
+ if (acl_user_obj_entry->ae_perm & ACL_WRITE)
+ mode |= S_IWUSR;
+ if (acl_group_obj_entry->ae_perm & ACL_EXECUTE)
+ mode |= S_IXGRP;
+ if (acl_group_obj_entry->ae_perm & ACL_READ)
+ mode |= S_IRGRP;
+ if (acl_group_obj_entry->ae_perm & ACL_WRITE)
+ mode |= S_IWGRP;
+ if (acl_other_entry->ae_perm & ACL_EXECUTE)
+ mode |= S_IXOTH;
+ if (acl_other_entry->ae_perm & ACL_READ)
+ mode |= S_IROTH;
+ if (acl_other_entry->ae_perm & ACL_WRITE)
+ mode |= S_IWOTH;
+
+ return (mode);
+}
+
+/*
+ * Utility function to generate a file mode given a complete POSIX.1e access
+ * ACL. Note that if the ACL is improperly formed, this may result in a
+ * panic.
+ */
+mode_t
+acl_posix1e_acl_to_mode(struct acl *acl)
+{
+ struct acl_entry *acl_mask, *acl_user_obj, *acl_group_obj, *acl_other;
+ int i;
+
+ /*
+ * Find the ACL entries relevant to a POSIX permission mode.
+ */
+ acl_user_obj = acl_group_obj = acl_other = acl_mask = NULL;
+ for (i = 0; i < acl->acl_cnt; i++) {
+ switch (acl->acl_entry[i].ae_tag) {
+ case ACL_USER_OBJ:
+ acl_user_obj = &acl->acl_entry[i];
+ break;
+
+ case ACL_GROUP_OBJ:
+ acl_group_obj = &acl->acl_entry[i];
+ break;
+
+ case ACL_OTHER:
+ acl_other = &acl->acl_entry[i];
+ break;
+
+ case ACL_MASK:
+ acl_mask = &acl->acl_entry[i];
+ break;
+
+ case ACL_USER:
+ case ACL_GROUP:
+ break;
+
+ default:
+ panic("acl_posix1e_acl_to_mode: bad ae_tag");
+ }
+ }
+
+ if (acl_user_obj == NULL || acl_group_obj == NULL || acl_other == NULL)
+ panic("acl_posix1e_acl_to_mode: missing base ae_tags");
+
+ /*
+ * POSIX.1e specifies that if there is an ACL_MASK entry, we replace
+ * the mode "group" bits with its permissions. If there isn't, we
+ * use the ACL_GROUP_OBJ permissions.
+ */
+ if (acl_mask != NULL)
+ return (acl_posix1e_perms_to_mode(acl_user_obj, acl_mask,
+ acl_other));
+ else
+ return (acl_posix1e_perms_to_mode(acl_user_obj, acl_group_obj,
+ acl_other));
+}
+
+/*
+ * Perform a syntactic check of the ACL, sufficient to allow an implementing
+ * filesystem to determine if it should accept this and rely on the POSIX.1e
+ * ACL properties.
+ */
+int
+acl_posix1e_check(struct acl *acl)
+{
+ int num_acl_user_obj, num_acl_user, num_acl_group_obj, num_acl_group;
+ int num_acl_mask, num_acl_other, i;
+
+ /*
+ * Verify that the number of entries does not exceed the maximum
+ * defined for acl_t.
+ *
+ * Verify that the correct number of various sorts of ae_tags are
+ * present:
+ * Exactly one ACL_USER_OBJ
+ * Exactly one ACL_GROUP_OBJ
+ * Exactly one ACL_OTHER
+ * If any ACL_USER or ACL_GROUP entries appear, then exactly one
+ * ACL_MASK entry must also appear.
+ *
+ * Verify that all ae_perm entries are in ACL_PERM_BITS.
+ *
+ * Verify all ae_tag entries are understood by this implementation.
+ *
+ * Note: Does not check for uniqueness of qualifier (ae_id) field.
+ */
+ num_acl_user_obj = num_acl_user = num_acl_group_obj = num_acl_group =
+ num_acl_mask = num_acl_other = 0;
+ if (acl->acl_cnt > ACL_MAX_ENTRIES)
+ return (EINVAL);
+ for (i = 0; i < acl->acl_cnt; i++) {
+ struct acl_entry *ae = &acl->acl_entry[i];
+ /*
+ * Check for a valid tag.
+ */
+ switch(ae->ae_tag) {
+ case ACL_USER_OBJ:
+ ae->ae_id = ACL_UNDEFINED_ID; /* XXX */
+ if (ae->ae_id != ACL_UNDEFINED_ID)
+ return (EINVAL);
+ num_acl_user_obj++;
+ break;
+ case ACL_GROUP_OBJ:
+ ae->ae_id = ACL_UNDEFINED_ID; /* XXX */
+ if (ae->ae_id != ACL_UNDEFINED_ID)
+ return (EINVAL);
+ num_acl_group_obj++;
+ break;
+ case ACL_USER:
+ if (ae->ae_id == ACL_UNDEFINED_ID)
+ return (EINVAL);
+ num_acl_user++;
+ break;
+ case ACL_GROUP:
+ if (ae->ae_id == ACL_UNDEFINED_ID)
+ return (EINVAL);
+ num_acl_group++;
+ break;
+ case ACL_OTHER:
+ ae->ae_id = ACL_UNDEFINED_ID; /* XXX */
+ if (ae->ae_id != ACL_UNDEFINED_ID)
+ return (EINVAL);
+ num_acl_other++;
+ break;
+ case ACL_MASK:
+ ae->ae_id = ACL_UNDEFINED_ID; /* XXX */
+ if (ae->ae_id != ACL_UNDEFINED_ID)
+ return (EINVAL);
+ num_acl_mask++;
+ break;
+ default:
+ return (EINVAL);
+ }
+ /*
+ * Check for valid perm entries.
+ */
+ if ((acl->acl_entry[i].ae_perm | ACL_PERM_BITS) !=
+ ACL_PERM_BITS)
+ return (EINVAL);
+ }
+ if ((num_acl_user_obj != 1) || (num_acl_group_obj != 1) ||
+ (num_acl_other != 1) || (num_acl_mask != 0 && num_acl_mask != 1))
+ return (EINVAL);
+ if (((num_acl_group != 0) || (num_acl_user != 0)) &&
+ (num_acl_mask != 1))
+ return (EINVAL);
+ return (0);
+}
+
+/*
+ * Given a requested mode for a new object, and a default ACL, combine the
+ * two to produce a new mode. Be careful not to clear any bits that aren't
+ * intended to be affected by the POSIX.1e ACL. Eventually, this might also
+ * take the cmask as an argument, if we push that down into
+ * per-filesystem-code.
+ */
+mode_t
+acl_posix1e_newfilemode(mode_t cmode, struct acl *dacl)
+{
+ mode_t mode;
+
+ mode = cmode;
+ /*
+ * The current composition policy is that a permission bit must be
+ * set in *both* the ACL and the requested creation mode for it to
+ * appear in the resulting mode/ACL. First clear any possibly
+ * effected bits, then reconstruct.
+ */
+ mode &= ACL_PRESERVE_MASK;
+ mode |= (ACL_OVERRIDE_MASK & cmode & acl_posix1e_acl_to_mode(dacl));
+
+ return (mode);
+}
diff --git a/sys/kern/sys_mqueue.c b/sys/kern/sys_mqueue.c
index d3a9da27609..7b5cdfabb17 100644
--- a/sys/kern/sys_mqueue.c
+++ b/sys/kern/sys_mqueue.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_mqueue.c,v 1.46 2020/03/16 21:20:10 pgoyette Exp $ */
+/* $NetBSD: sys_mqueue.c,v 1.47 2020/05/16 18:31:50 christos Exp $ */
/*
* Copyright (c) 2007-2011 Mindaugas Rasiukevicius <rmind at NetBSD org>
@@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.46 2020/03/16 21:20:10 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.47 2020/05/16 18:31:50 christos Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -393,17 +393,17 @@ mq_close_fop(file_t *fp)
static int
mqueue_access(mqueue_t *mq, int access, kauth_cred_t cred)
{
- mode_t acc_mode = 0;
+ accmode_t accmode = 0;
/* Note the difference between VREAD/VWRITE and FREAD/FWRITE. */
if (access & FREAD) {
- acc_mode |= VREAD;
+ accmode |= VREAD;
}
if (access & FWRITE) {
- acc_mode |= VWRITE;
+ accmode |= VWRITE;
}
- if (genfs_can_access(VNON, mq->mq_mode, mq->mq_euid,
- mq->mq_egid, acc_mode, cred)) {
+ if (genfs_can_access(NULL, cred, mq->mq_euid, mq->mq_egid,
+ mq->mq_mode, NULL, accmode)) {
return EACCES;
}
return 0;
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
index 7a400b9fc8f..feaf1bc7282 100644
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -1,4 +1,4 @@
-/* $NetBSD: syscalls.c,v 1.319 2020/04/26 19:16:36 thorpej Exp $ */
+/* $NetBSD: syscalls.c,v 1.320 2020/05/16 18:31:50 christos Exp $ */
/*
* System call names.
@@ -8,7 +8,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: syscalls.c,v 1.319 2020/04/26 19:16:36 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: syscalls.c,v 1.320 2020/05/16 18:31:50 christos Exp $");
#if defined(_KERNEL_OPT)
#ifdef _KERNEL_OPT
@@ -24,6 +24,7 @@ __KERNEL_RCSID(0, "$NetBSD: syscalls.c,v 1.319 2020/04/26 19:16:36 thorpej Exp $
#include <sys/sched.h>
#include <sys/idtype.h>
#include <sys/syscallargs.h>
+#include <sys/acl.h>
#else /* _KERNEL_OPT */
#include <sys/null.h>
#endif /* _KERNEL_OPT */
@@ -536,19 +537,19 @@ const char *const syscallnames[] = {
/* 484 */ "__statvfs190",
/* 485 */ "__fstatvfs190",
/* 486 */ "__fhstatvfs190",
- /* 487 */ "# filler",
- /* 488 */ "# filler",
- /* 489 */ "# filler",
- /* 490 */ "# filler",
- /* 491 */ "# filler",
- /* 492 */ "# filler",
- /* 493 */ "# filler",
- /* 494 */ "# filler",
- /* 495 */ "# filler",
- /* 496 */ "# filler",
- /* 497 */ "# filler",
- /* 498 */ "# filler",
- /* 499 */ "# filler",
+ /* 487 */ "__acl_get_link",
+ /* 488 */ "__acl_set_link",
+ /* 489 */ "__acl_delete_link",
+ /* 490 */ "__acl_aclcheck_link",
+ /* 491 */ "__acl_get_file",
+ /* 492 */ "__acl_set_file",
+ /* 493 */ "__acl_get_fd",
+ /* 494 */ "__acl_set_fd",
+ /* 495 */ "__acl_delete_file",
+ /* 496 */ "__acl_delete_fd",
+ /* 497 */ "__acl_aclcheck_file",
+ /* 498 */ "__acl_aclcheck_fd",
+ /* 499 */ "lpathconf",
/* 500 */ "# filler",
/* 501 */ "# filler",
/* 502 */ "# filler",
@@ -1073,19 +1074,19 @@ const char *const altsyscallnames[] = {
/* 484 */ "statvfs1",
/* 485 */ "fstatvfs1",
/* 486 */ "fhstatvfs1",
- /* 487 */ NULL, /* filler */
- /* 488 */ NULL, /* filler */
- /* 489 */ NULL, /* filler */
- /* 490 */ NULL, /* filler */
- /* 491 */ NULL, /* filler */
- /* 492 */ NULL, /* filler */
- /* 493 */ NULL, /* filler */
- /* 494 */ NULL, /* filler */
- /* 495 */ NULL, /* filler */
- /* 496 */ NULL, /* filler */
- /* 497 */ NULL, /* filler */
- /* 498 */ NULL, /* filler */
- /* 499 */ NULL, /* filler */
+ /* 487 */ NULL, /* __acl_get_link */
+ /* 488 */ NULL, /* __acl_set_link */
+ /* 489 */ NULL, /* __acl_delete_link */
+ /* 490 */ NULL, /* __acl_aclcheck_link */
+ /* 491 */ NULL, /* __acl_get_file */
+ /* 492 */ NULL, /* __acl_set_file */
+ /* 493 */ NULL, /* __acl_get_fd */
+ /* 494 */ NULL, /* __acl_set_fd */
+ /* 495 */ NULL, /* __acl_delete_file */
+ /* 496 */ NULL, /* __acl_delete_fd */
+ /* 497 */ NULL, /* __acl_aclcheck_file */
+ /* 498 */ NULL, /* __acl_aclcheck_fd */
+ /* 499 */ NULL, /* lpathconf */
/* 500 */ NULL, /* filler */
/* 501 */ NULL, /* filler */
/* 502 */ NULL, /* filler */
diff --git a/sys/kern/syscalls.conf b/sys/kern/syscalls.conf
index 4ae3f6db242..a8c64da8fc3 100644
--- a/sys/kern/syscalls.conf
+++ b/sys/kern/syscalls.conf
@@ -1,11 +1,11 @@
-# $NetBSD: syscalls.conf,v 1.30 2019/09/22 22:59:39 christos Exp $
+# $NetBSD: syscalls.conf,v 1.31 2020/05/16 18:31:50 christos Exp $
sysnames="syscalls.c"
sysnumhdr="../sys/syscall.h"
syssw="init_sysent.c"
systrace="systrace_args.c"
sysarghdr="../sys/syscallargs.h"
-sysarghdrextra='#ifndef RUMP_CLIENT\n#include <sys/idtype.h>\n#include <sys/mount.h>\n#include <sys/sched.h>\n#endif\n\n#include <sys/socket.h>\n\n'
+sysarghdrextra='#ifndef RUMP_CLIENT\n#include <sys/idtype.h>\n#include <sys/mount.h>\n#include <sys/sched.h>\n#include <sys/acl.h>\n#endif\n\n#include <sys/socket.h>\n\n'
sysautoload="syscalls_autoload.c"
sysalign=1
rumpcalls="../rump/librump/rumpkern/rump_syscalls.c"
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 06e6ec031ae..a53b8a25b4b 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -1,4 +1,4 @@
- $NetBSD: syscalls.master,v 1.304 2020/04/26 19:15:55 thorpej Exp $
+ $NetBSD: syscalls.master,v 1.305 2020/05/16 18:31:50 christos Exp $
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@@ -59,6 +59,7 @@
#include <sys/sched.h>
#include <sys/idtype.h>
#include <sys/syscallargs.h>
+#include <sys/acl.h>
%%
@@ -1019,3 +1020,28 @@
struct statvfs *buf, int flags); }
486 STD RUMP { int|sys|90|fhstatvfs1(const void *fhp, \
size_t fh_size, struct statvfs *buf, int flags); }
+487 STD { int|sys||__acl_get_link(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+488 STD { int|sys||__acl_set_link(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+489 STD { int|sys||__acl_delete_link(const char *path, \
+ acl_type_t type); }
+490 STD { int|sys||__acl_aclcheck_link(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+491 STD { int|sys||__acl_get_file(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+492 STD { int|sys||__acl_set_file(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+493 STD { int|sys||__acl_get_fd(int filedes, acl_type_t type, \
+ struct acl *aclp); }
+494 STD { int|sys||__acl_set_fd(int filedes, acl_type_t type, \
+ struct acl *aclp); }
+495 STD { int|sys||__acl_delete_file(const char *path, \
+ acl_type_t type); }
+496 STD { int|sys||__acl_delete_fd(int filedes, \
+ acl_type_t type); }
+497 STD { int|sys||__acl_aclcheck_file(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+498 STD { int|sys||__acl_aclcheck_fd(int filedes, \
+ acl_type_t type, struct acl *aclp); }
+499 STD RUMP { long|sys||lpathconf(const char *path, int name); }
diff --git a/sys/kern/syscalls_autoload.c b/sys/kern/syscalls_autoload.c
index c4d14785c66..917602c9371 100644
--- a/sys/kern/syscalls_autoload.c
+++ b/sys/kern/syscalls_autoload.c
@@ -1,4 +1,4 @@
-/* $NetBSD: syscalls_autoload.c,v 1.36 2020/04/26 19:16:36 thorpej Exp $ */
+/* $NetBSD: syscalls_autoload.c,v 1.37 2020/05/16 18:31:50 christos Exp $ */
/*
* System call autoload table.
@@ -8,7 +8,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: syscalls_autoload.c,v 1.36 2020/04/26 19:16:36 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: syscalls_autoload.c,v 1.37 2020/05/16 18:31:50 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_modular.h"
@@ -23,6 +23,7 @@ __KERNEL_RCSID(0, "$NetBSD: syscalls_autoload.c,v 1.36 2020/04/26 19:16:36 thorp
#include <sys/sched.h>
#include <sys/idtype.h>
#include <sys/syscallargs.h>
+#include <sys/acl.h>
static struct sc_autoload netbsd_syscalls_autoload[] = {
{ SYS_compat_50_wait4, "compat_50" },
{ SYS_compat_43_ocreat, "compat_43" },
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
index 4cb5b48da20..c5b7ca54a0e 100644
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -1,4 +1,4 @@
-/* $NetBSD: systrace_args.c,v 1.38 2020/04/26 19:16:36 thorpej Exp $ */
+/* $NetBSD: systrace_args.c,v 1.39 2020/05/16 18:31:50 christos Exp $ */
/*
* System call argument to DTrace register array converstion.
@@ -3731,6 +3731,119 @@ systrace_args(register_t sysnum, const void *params, uintptr_t *uarg, size_t *n_
*n_args = 4;
break;
}
+ /* sys___acl_get_link */
+ case 487: {
+ const struct sys___acl_get_link_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path); /* const char * */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp); /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* sys___acl_set_link */
+ case 488: {
+ const struct sys___acl_set_link_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path); /* const char * */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp); /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* sys___acl_delete_link */
+ case 489: {
+ const struct sys___acl_delete_link_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path); /* const char * */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ *n_args = 2;
+ break;
+ }
+ /* sys___acl_aclcheck_link */
+ case 490: {
+ const struct sys___acl_aclcheck_link_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path); /* const char * */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp); /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* sys___acl_get_file */
+ case 491: {
+ const struct sys___acl_get_file_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path); /* const char * */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp); /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* sys___acl_set_file */
+ case 492: {
+ const struct sys___acl_set_file_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path); /* const char * */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp); /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* sys___acl_get_fd */
+ case 493: {
+ const struct sys___acl_get_fd_args *p = params;
+ iarg[0] = SCARG(p, filedes); /* int */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp); /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* sys___acl_set_fd */
+ case 494: {
+ const struct sys___acl_set_fd_args *p = params;
+ iarg[0] = SCARG(p, filedes); /* int */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp); /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* sys___acl_delete_file */
+ case 495: {
+ const struct sys___acl_delete_file_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path); /* const char * */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ *n_args = 2;
+ break;
+ }
+ /* sys___acl_delete_fd */
+ case 496: {
+ const struct sys___acl_delete_fd_args *p = params;
+ iarg[0] = SCARG(p, filedes); /* int */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ *n_args = 2;
+ break;
+ }
+ /* sys___acl_aclcheck_file */
+ case 497: {
+ const struct sys___acl_aclcheck_file_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path); /* const char * */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp); /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* sys___acl_aclcheck_fd */
+ case 498: {
+ const struct sys___acl_aclcheck_fd_args *p = params;
+ iarg[0] = SCARG(p, filedes); /* int */
+ iarg[1] = SCARG(p, type); /* acl_type_t */
+ uarg[2] = (intptr_t) SCARG(p, aclp); /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* sys_lpathconf */
+ case 499: {
+ const struct sys_lpathconf_args *p = params;
+ uarg[0] = (intptr_t) SCARG(p, path); /* const char * */
+ iarg[1] = SCARG(p, name); /* int */
+ *n_args = 2;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -10066,6 +10179,202 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
};
break;
+ /* sys___acl_get_link */
+ case 487:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys___acl_set_link */
+ case 488:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys___acl_delete_link */
+ case 489:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys___acl_aclcheck_link */
+ case 490:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys___acl_get_file */
+ case 491:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys___acl_set_file */
+ case 492:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys___acl_get_fd */
+ case 493:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys___acl_set_fd */
+ case 494:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys___acl_delete_file */
+ case 495:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys___acl_delete_fd */
+ case 496:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys___acl_aclcheck_file */
+ case 497:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys___acl_aclcheck_fd */
+ case 498:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sys_lpathconf */
+ case 499:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -12178,6 +12487,71 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* sys___acl_get_link */
+ case 487:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys___acl_set_link */
+ case 488:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys___acl_delete_link */
+ case 489:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys___acl_aclcheck_link */
+ case 490:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys___acl_get_file */
+ case 491:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys___acl_set_file */
+ case 492:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys___acl_get_fd */
+ case 493:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys___acl_set_fd */
+ case 494:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys___acl_delete_file */
+ case 495:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys___acl_delete_fd */
+ case 496:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys___acl_aclcheck_file */
+ case 497:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys___acl_aclcheck_fd */
+ case 498:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sys_lpathconf */
+ case 499:
+ if (ndx == 0 || ndx == 1)
+ p = "long";
+ break;
default:
break;
};
diff --git a/sys/kern/vfs_acl.c b/sys/kern/vfs_acl.c
new file mode 100644
index 00000000000..71fcca945f0
--- /dev/null
+++ b/sys/kern/vfs_acl.c
@@ -0,0 +1,542 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999-2006, 2016-2017 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * Portions of this software were developed by BAE Systems, the University of
+ * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL
+ * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent
+ * Computing (TC) research program.
+ *
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+/*
+ * Developed by the TrustedBSD Project.
+ *
+ * ACL system calls and other functions common across different ACL types.
+ * Type-specific routines go into subr_acl_<type>.c.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/sys/kern/vfs_acl.c 356337 2020-01-03 22:29:58Z mjg $");
+#endif
+__KERNEL_RCSID(0, "$NetBSD: vfs_acl.c,v 1.1 2020/05/16 18:31:50 christos Exp $");
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
+#include <sys/acl.h>
+
+#include <sys/syscallargs.h>
+
+__CTASSERT(ACL_MAX_ENTRIES >= OLDACL_MAX_ENTRIES);
+
+
+int
+acl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest)
+{
+ int i;
+
+ if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES)
+ return EINVAL;
+
+ memset(dest, 0, sizeof(*dest));
+
+ dest->acl_cnt = source->acl_cnt;
+ dest->acl_maxcnt = ACL_MAX_ENTRIES;
+
+ for (i = 0; i < dest->acl_cnt; i++) {
+ dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag;
+ dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id;
+ dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm;
+ }
+
+ return 0;
+}
+
+int
+acl_copy_acl_into_oldacl(const struct acl *source, struct oldacl *dest)
+{
+ int i;
+
+ if (source->acl_cnt > OLDACL_MAX_ENTRIES)
+ return EINVAL;
+
+ memset(dest, 0, sizeof(*dest));
+
+ dest->acl_cnt = source->acl_cnt;
+
+ for (i = 0; i < dest->acl_cnt; i++) {
+ dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag;
+ dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id;
+ dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm;
+ }
+
+ return 0;
+}
+
+/*
+ * At one time, "struct ACL" was extended in order to add support for NFSv4
+ * ACLs. Instead of creating compatibility versions of all the ACL-related
+ * syscalls, they were left intact. It's possible to find out what the code
+ * calling these syscalls (libc) expects basing on "type" argument - if it's
+ * either ACL_TYPE_ACCESS_OLD or ACL_TYPE_DEFAULT_OLD (which previously were
+ * known as ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT), then it's the "struct
+ * oldacl". If it's something else, then it's the new "struct acl". In the
+ * latter case, the routines below just copyin/copyout the contents. In the
+ * former case, they copyin the "struct oldacl" and convert it to the new
+ * format.
+ */
+static int
+acl_copyin(const void *user_acl, struct acl *kernel_acl, acl_type_t type)
+{
+ int error;
+ struct oldacl old;
+
+ switch (type) {
+ case ACL_TYPE_ACCESS_OLD:
+ case ACL_TYPE_DEFAULT_OLD:
+ error = copyin(user_acl, &old, sizeof(old));
+ if (error != 0)
+ break;
+ acl_copy_oldacl_into_acl(&old, kernel_acl);
+ break;
+
+ default:
+ error = copyin(user_acl, kernel_acl, sizeof(*kernel_acl));
+ if (kernel_acl->acl_maxcnt != ACL_MAX_ENTRIES)
+ return EINVAL;
+ }
+
+ return error;
+}
+
+static int
+acl_copyout(const struct acl *kernel_acl, void *user_acl, acl_type_t type)
+{
+ uint32_t am;
+ int error;
+ struct oldacl old;
+
+ switch (type) {
+ case ACL_TYPE_ACCESS_OLD:
+ case ACL_TYPE_DEFAULT_OLD:
+ error = acl_copy_acl_into_oldacl(kernel_acl, &old);
+ if (error != 0)
+ break;
+
+ error = copyout(&old, user_acl, sizeof(old));
+ break;
+
+ default:
+ error = ufetch_32((const uint32_t *)
+ (const void *)((const char *)user_acl +
+ offsetof(struct acl, acl_maxcnt)), &am);
+ if (error)
+ return error;
+ if (am != ACL_MAX_ENTRIES)
+ return EINVAL;
+
+ error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl));
+ }
+
+ return error;
+}
+
+/*
+ * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new"
+ * counterpart. It's required for old (pre-NFSv4 ACLs) libc to work
+ * with new kernel. Fixing 'type' for old binaries with new libc
+ * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold().
+ */
+static int
+acl_type_unold(int type)
+{
+ switch (type) {
+ case ACL_TYPE_ACCESS_OLD:
+ return ACL_TYPE_ACCESS;
+
+ case ACL_TYPE_DEFAULT_OLD:
+ return ACL_TYPE_DEFAULT;
+
+ default:
+ return type;
+ }
+}
+
+/*
+ * These calls wrap the real vnode operations, and are called by the syscall
+ * code once the syscall has converted the path or file descriptor to a vnode
+ * (unlocked). The aclp pointer is assumed still to point to userland, so
+ * this should not be consumed within the kernel except by syscall code.
+ * Other code should directly invoke VOP_{SET,GET}ACL.
+ */
+
+/*
+ * Given a vnode, set its ACL.
+ */
+int
+vacl_set_acl(struct lwp *l, struct vnode *vp, acl_type_t type,
+ const struct acl *aclp)
+{
+ struct acl *inkernelacl;
+ int error;
+
+ inkernelacl = acl_alloc(KM_SLEEP);
+ error = acl_copyin(aclp, inkernelacl, type);
+ if (error != 0)
+ goto out;
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl, l->l_cred);
+ VOP_UNLOCK(vp);
+out:
+ acl_free(inkernelacl);
+ return error;
+}
+
+/*
+ * Given a vnode, get its ACL.
+ */
+int
+vacl_get_acl(struct lwp *l, struct vnode *vp, acl_type_t type,
+ struct acl *aclp)
+{
+ struct acl *inkernelacl;
+ int error;
+
+ inkernelacl = acl_alloc(KM_SLEEP);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl, l->l_cred);
+
+ VOP_UNLOCK(vp);
+ if (error == 0)
+ error = acl_copyout(inkernelacl, aclp, type);
+ acl_free(inkernelacl);
+ return error;
+}
+
+/*
+ * Given a vnode, delete its ACL.
+ */
+int
+vacl_delete(struct lwp *l, struct vnode *vp, acl_type_t type)
+{
+ int error;
+
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ error = VOP_SETACL(vp, acl_type_unold(type), 0, l->l_cred);
+ VOP_UNLOCK(vp);
+ return error;
+}
+
+/*
+ * Given a vnode, check whether an ACL is appropriate for it
+ *
+ * XXXRW: No vnode lock held so can't audit vnode state...?
+ */
+int
+vacl_aclcheck(struct lwp *l, struct vnode *vp, acl_type_t type,
+ const struct acl *aclp)
+{
+ struct acl *inkernelacl;
+ int error;
+
+ inkernelacl = acl_alloc(KM_SLEEP);
+ error = acl_copyin(aclp, inkernelacl, type);
+ if (error != 0)
+ goto out;
+ error = VOP_ACLCHECK(vp, acl_type_unold(type), inkernelacl,
+ l->l_cred);
+out:
+ acl_free(inkernelacl);
+ return error;
+}
+
+/*
+ * syscalls -- convert the path/fd to a vnode, and call vacl_whatever. Don't
+ * need to lock, as the vacl_ code will get/release any locks required.
+ */
+
+/*
+ * Given a file path, get an ACL for it
+ */
+int
+sys___acl_get_file(struct lwp *l,
+ const struct sys___acl_get_file_args *uap, register_t *retval)
+{
+
+ return kern___acl_get_path(l, SCARG(uap, path), SCARG(uap, type),
+ SCARG(uap, aclp), NSM_FOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file path, get an ACL for it; don't follow links.
+ */
+int
+sys___acl_get_link(struct lwp *l,
+ const struct sys___acl_get_link_args *uap, register_t *retval)
+{
+
+ return kern___acl_get_path(l, SCARG(uap, path), SCARG(uap, type),
+ SCARG(uap, aclp), NSM_NOFOLLOW_NOEMULROOT);
+}
+
+int
+kern___acl_get_path(struct lwp *l, const char *path, acl_type_t type,
+ struct acl *aclp, namei_simple_flags_t flags)
+{
+ struct vnode *path_vp;
+ int error;
+
+ error = namei_simple_user(path, flags, &path_vp);
+ if (error == 0) {
+ error = vacl_get_acl(l, path_vp, type, aclp);
+ vrele(path_vp);
+ }
+ return error;
+}
+
+/*
+ * Given a file path, set an ACL for it.
+ */
+int
+sys___acl_set_file(struct lwp *l,
+ const struct sys___acl_set_file_args *uap, register_t *retval)
+{
+
+ return kern___acl_set_path(l, SCARG(uap, path), SCARG(uap, type),
+ SCARG(uap, aclp), NSM_FOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file path, set an ACL for it; don't follow links.
+ */
+int
+sys___acl_set_link(struct lwp *l,
+ const struct sys___acl_set_link_args *uap, register_t *retval)
+{
+
+ return kern___acl_set_path(l, SCARG(uap, path), SCARG(uap, type),
+ SCARG(uap, aclp), NSM_NOFOLLOW_NOEMULROOT);
+}
+
+int
+kern___acl_set_path(struct lwp *l, const char *path,
+ acl_type_t type, const struct acl *aclp, namei_simple_flags_t flags)
+{
+ struct vnode *path_vp;
+ int error;
+
+ error = namei_simple_user(path, flags, &path_vp);
+ if (error == 0) {
+ error = vacl_set_acl(l, path_vp, type, aclp);
+ vrele(path_vp);
+ }
+ return error;
+}
+
+/*
+ * Given a file descriptor, get an ACL for it.
+ */
+int
+sys___acl_get_fd(struct lwp *l, const struct sys___acl_get_fd_args *uap,
+ register_t *retval)
+{
+ struct file *fp;
+ int error;
+ error = fd_getvnode(SCARG(uap, filedes), &fp);
+ if (error == 0) {
+ error = vacl_get_acl(l, fp->f_vnode, SCARG(uap, type),
+ SCARG(uap, aclp));
+ fd_putfile(SCARG(uap, filedes));
+ }
+ return error;
+}
+
+/*
+ * Given a file descriptor, set an ACL for it.
+ */
+int
+sys___acl_set_fd(struct lwp *l, const struct sys___acl_set_fd_args *uap,
+ register_t *retval)
+{
+ struct file *fp;
+ int error;
+
+ error = fd_getvnode(SCARG(uap, filedes), &fp);
+ if (error == 0) {
+ error = vacl_set_acl(l, fp->f_vnode, SCARG(uap, type),
+ SCARG(uap, aclp));
+ fd_putfile(SCARG(uap, filedes));
+ }
+ return error;
+}
+
+/*
+ * Given a file path, delete an ACL from it.
+ */
+int
+sys___acl_delete_file(struct lwp *l,
+ const struct sys___acl_delete_file_args *uap, register_t *retval)
+{
+
+ return kern___acl_delete_path(l, SCARG(uap, path), SCARG(uap, type),
+ NSM_FOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file path, delete an ACL from it; don't follow links.
+ */
+int
+sys___acl_delete_link(struct lwp *l,
+ const struct sys___acl_delete_link_args *uap, register_t *retval)
+{
+
+ return kern___acl_delete_path(l, SCARG(uap, path), SCARG(uap, type),
+ NSM_NOFOLLOW_NOEMULROOT);
+}
+
+int
+kern___acl_delete_path(struct lwp *l, const char *path,
+ acl_type_t type, namei_simple_flags_t flags)
+{
+ struct vnode *path_vp;
+ int error;
+
+ error = namei_simple_user(path, flags, &path_vp);
+ if (error == 0) {
+ error = vacl_delete(l, path_vp, type);
+ vrele(path_vp);
+ }
+ return error;
+}
+
+/*
+ * Given a file path, delete an ACL from it.
+ */
+int
+sys___acl_delete_fd(struct lwp *l,
+ const struct sys___acl_delete_fd_args *uap, register_t *retval)
+{
+ struct file *fp;
+ int error;
+
+ error = fd_getvnode(SCARG(uap, filedes), &fp);
+ if (error == 0) {
+ error = vacl_delete(l, fp->f_vnode, SCARG(uap, type));
+ fd_putfile(SCARG(uap, filedes));
+ }
+ return error;
+}
+
+/*
+ * Given a file path, check an ACL for it.
+ */
+int
+sys___acl_aclcheck_file(struct lwp *l,
+ const struct sys___acl_aclcheck_file_args *uap, register_t *retval)
+{
+
+ return kern___acl_aclcheck_path(l, SCARG(uap, path), SCARG(uap, type),
+ SCARG(uap, aclp), NSM_FOLLOW_NOEMULROOT);
+}
+
+/*
+ * Given a file path, check an ACL for it; don't follow links.
+ */
+int
+sys___acl_aclcheck_link(struct lwp *l,
+ const struct sys___acl_aclcheck_link_args *uap, register_t *retval)
+{
+ return kern___acl_aclcheck_path(l, SCARG(uap, path),
+ SCARG(uap, type), SCARG(uap, aclp), NSM_NOFOLLOW_NOEMULROOT);
+}
+
+int
+kern___acl_aclcheck_path(struct lwp *l, const char *path, acl_type_t type,
+ struct acl *aclp, namei_simple_flags_t flags)
+{
+ struct vnode *path_vp;
+ int error;
+
+ error = namei_simple_user(path, flags, &path_vp);
+ if (error == 0) {
+ error = vacl_aclcheck(l, path_vp, type, aclp);
+ vrele(path_vp);
+
+ }
+ return error;
+}
+
+/*
+ * Given a file descriptor, check an ACL for it.
+ */
+int
+sys___acl_aclcheck_fd(struct lwp *l,
+ const struct sys___acl_aclcheck_fd_args *uap, register_t *retval)
+{
+ struct file *fp;
+ int error;
+
+ error = fd_getvnode(SCARG(uap, filedes), &fp);
+ if (error == 0) {
+ error = vacl_aclcheck(l, fp->f_vnode, SCARG(uap, type),
+ SCARG(uap, aclp));
+ fd_putfile(SCARG(uap, filedes));
+ }
+ return error;
+}
+
+struct acl *
+acl_alloc(int flags)
+{
+ struct acl *aclp;
+
+ aclp = kmem_zalloc(sizeof(*aclp), flags);
+ if (aclp == NULL)
+ return NULL;
+
+ aclp->acl_maxcnt = ACL_MAX_ENTRIES;
+
+ return aclp;
+}
+
+void
+acl_free(struct acl *aclp)
+{
+
+ kmem_free(aclp, sizeof(*aclp));
+}
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index fb400d27cf2..ad6445f7960 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_cache.c,v 1.142 2020/05/12 23:17:41 ad Exp $ */
+/* $NetBSD: vfs_cache.c,v 1.143 2020/05/16 18:31:50 christos Exp $ */
/*-
* Copyright (c) 2008, 2019, 2020 The NetBSD Foundation, Inc.
@@ -172,7 +172,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.142 2020/05/12 23:17:41 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.143 2020/05/16 18:31:50 christos Exp $");
#define __NAMECACHE_PRIVATE
#ifdef _KERNEL_OPT
@@ -689,8 +689,8 @@ cache_lookup_linked(struct vnode *dvp, const char *name, size_t namelen,
KASSERT(dvi->vi_nc_uid != VNOVAL && dvi->vi_nc_gid != VNOVAL);
error = kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(VEXEC,
dvp->v_type, dvi->vi_nc_mode & ALLPERMS), dvp, NULL,
- genfs_can_access(dvp->v_type, dvi->vi_nc_mode & ALLPERMS,
- dvi->vi_nc_uid, dvi->vi_nc_gid, VEXEC, cred));
+ genfs_can_access(dvp, cred, dvi->vi_nc_uid, dvi->vi_nc_gid,
+ dvi->vi_nc_mode & ALLPERMS, NULL, VEXEC));
if (error != 0) {
COUNT(ncs_denied);
return false;
@@ -741,7 +741,7 @@ cache_lookup_linked(struct vnode *dvp, const char *name, size_t namelen,
*/
int
cache_revlookup(struct vnode *vp, struct vnode **dvpp, char **bpp, char *bufp,
- bool checkaccess, int perms)
+ bool checkaccess, accmode_t accmode)
{
vnode_impl_t *vi = VNODE_TO_VIMPL(vp);
struct namecache *ncp;
@@ -772,9 +772,9 @@ cache_revlookup(struct vnode *vp, struct vnode **dvpp, char **bpp, char *bufp,
KASSERT(vi->vi_nc_uid != VNOVAL && vi->vi_nc_gid != VNOVAL);
error = kauth_authorize_vnode(curlwp->l_cred,
KAUTH_ACCESS_ACTION(VEXEC, vp->v_type, vi->vi_nc_mode &
- ALLPERMS), vp, NULL, genfs_can_access(vp->v_type,
- vi->vi_nc_mode & ALLPERMS, vi->vi_nc_uid, vi->vi_nc_gid,
- perms, curlwp->l_cred));
+ ALLPERMS), vp, NULL, genfs_can_access(vp, curlwp->l_cred,
+ vi->vi_nc_uid, vi->vi_nc_gid, vi->vi_nc_mode & ALLPERMS,
+ NULL, accmode));
if (error != 0) {
rw_exit(&vi->vi_nc_listlock);
COUNT(ncs_denied);
diff --git a/sys/kern/vfs_getcwd.c b/sys/kern/vfs_getcwd.c
index 08152628339..7fdf1bbe8e5 100644
--- a/sys/kern/vfs_getcwd.c
+++ b/sys/kern/vfs_getcwd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_getcwd.c,v 1.59 2020/04/21 21:42:47 ad Exp $ */
+/* $NetBSD: vfs_getcwd.c,v 1.60 2020/05/16 18:31:50 christos Exp $ */
/*-
* Copyright (c) 1999, 2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_getcwd.c,v 1.59 2020/04/21 21:42:47 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_getcwd.c,v 1.60 2020/05/16 18:31:50 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -277,7 +277,7 @@ getcwd_common(struct vnode *lvp, struct vnode *rvp, char **bpp, char *bufp,
struct vnode *uvp = NULL;
char *bp = NULL;
int error;
- int perms = VEXEC;
+ accmode_t accmode = VEXEC;
error = 0;
if (rvp == NULL) {
@@ -325,7 +325,7 @@ getcwd_common(struct vnode *lvp, struct vnode *rvp, char **bpp, char *bufp,
if (lvp->v_vflag & VV_ROOT) {
vn_lock(lvp, LK_SHARED | LK_RETRY);
if (chkaccess) {
- error = VOP_ACCESS(lvp, perms, cred);
+ error = VOP_ACCESS(lvp, accmode, cred);
if (error) {
VOP_UNLOCK(lvp);
goto out;
@@ -361,7 +361,7 @@ getcwd_common(struct vnode *lvp, struct vnode *rvp, char **bpp, char *bufp,
if (chkaccess && !cache_have_id(lvp)) {
/* Need exclusive for UFS VOP_GETATTR (itimes) & VOP_LOOKUP. */
vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY);
- error = VOP_ACCESS(lvp, perms, cred);
+ error = VOP_ACCESS(lvp, accmode, cred);
if (error) {
VOP_UNLOCK(lvp);
goto out;
@@ -375,7 +375,7 @@ getcwd_common(struct vnode *lvp, struct vnode *rvp, char **bpp, char *bufp,
* directory..
*/
error = cache_revlookup(lvp, &uvp, &bp, bufp, chkaccess,
- perms);
+ accmode);
if (error == -1) {
if (!locked) {
locked = true;
@@ -398,7 +398,7 @@ getcwd_common(struct vnode *lvp, struct vnode *rvp, char **bpp, char *bufp,
panic("getcwd: oops, went back too far");
}
#endif
- perms = VEXEC | VREAD;
+ accmode = VEXEC | VREAD;
if (bp)
*(--bp) = '/';
vrele(lvp);
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
index f59f632be49..0b19f8ee2c6 100644
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_init.c,v 1.50 2020/02/21 00:26:22 joerg Exp $ */
+/* $NetBSD: vfs_init.c,v 1.51 2020/05/16 18:31:50 christos Exp $ */
/*-
* Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_init.c,v 1.50 2020/02/21 00:26:22 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_init.c,v 1.51 2020/05/16 18:31:50 christos Exp $");
#include <sys/param.h>
#include <sys/mount.h>
@@ -377,10 +377,10 @@ mount_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
result = KAUTH_RESULT_ALLOW;
else if (req == KAUTH_REQ_SYSTEM_MOUNT_DEVICE) {
vnode_t *devvp = arg2;
- mode_t access_mode = (mode_t)(unsigned long)arg3;
+ accmode_t accmode = (accmode_t)(unsigned long)arg3;
int error;
- error = VOP_ACCESS(devvp, access_mode, cred);
+ error = VOP_ACCESS(devvp, accmode, cred);
if (!error)
result = KAUTH_RESULT_ALLOW;
}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 9f78835711c..c8156794f44 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_subr.c,v 1.486 2020/04/21 21:42:47 ad Exp $ */
+/* $NetBSD: vfs_subr.c,v 1.487 2020/05/16 18:31:50 christos Exp $ */
/*-
* Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008, 2019, 2020
@@ -69,7 +69,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.486 2020/04/21 21:42:47 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.487 2020/05/16 18:31:50 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -1138,21 +1138,6 @@ vprint(const char *label, struct vnode *vp)
}
}
-/* Deprecated. Kept for KPI compatibility. */
-int
-vaccess(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid,
- mode_t acc_mode, kauth_cred_t cred)
-{
-
-#ifdef DIAGNOSTIC
- printf("vaccess: deprecated interface used.\n");
-#endif /* DIAGNOSTIC */
-
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(acc_mode,
- type, file_mode), NULL /* This may panic. */, NULL,
- genfs_can_access(type, file_mode, uid, gid, acc_mode, cred));
-}
-
/*
* Given a file system name, look up the vfsops for that
* file system, or return NULL if file system isn't present
@@ -1278,6 +1263,53 @@ vfs_timestamp(struct timespec *ts)
nanotime(ts);
}
+/*
+ * The purpose of this routine is to remove granularity from accmode_t,
+ * reducing it into standard unix access bits - VEXEC, VREAD, VWRITE,
+ * VADMIN and VAPPEND.
+ *
+ * If it returns 0, the caller is supposed to continue with the usual
+ * access checks using 'accmode' as modified by this routine. If it
+ * returns nonzero value, the caller is supposed to return that value
+ * as errno.
+ *
+ * Note that after this routine runs, accmode may be zero.
+ */
+int
+vfs_unixify_accmode(accmode_t *accmode)
+{
+ /*
+ * There is no way to specify explicit "deny" rule using
+ * file mode or POSIX.1e ACLs.
+ */
+ if (*accmode & VEXPLICIT_DENY) {
+ *accmode = 0;
+ return (0);
+ }
+
+ /*
+ * None of these can be translated into usual access bits.
+ * Also, the common case for NFSv4 ACLs is to not contain
+ * either of these bits. Caller should check for VWRITE
+ * on the containing directory instead.
+ */
+ if (*accmode & (VDELETE_CHILD | VDELETE))
+ return (EPERM);
+
+ if (*accmode & VADMIN_PERMS) {
+ *accmode &= ~VADMIN_PERMS;
+ *accmode |= VADMIN;
+ }
+
+ /*
+ * There is no way to deny VREAD_ATTRIBUTES, VREAD_ACL
+ * or VSYNCHRONIZE using file mode or POSIX.1e ACL.
+ */
+ *accmode &= ~(VSTAT_PERMS | VSYNCHRONIZE);
+
+ return (0);
+}
+
time_t rootfstime; /* recorded root fs time, if known */
void
setrootfstime(time_t t)
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index c2d43d6ca6f..d829a057738 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_syscalls.c,v 1.547 2020/04/21 21:42:47 ad Exp $ */
+/* $NetBSD: vfs_syscalls.c,v 1.548 2020/05/16 18:31:50 christos Exp $ */
/*-
* Copyright (c) 2008, 2009, 2019, 2020 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.547 2020/04/21 21:42:47 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.548 2020/05/16 18:31:50 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_fileassoc.h"
@@ -3232,34 +3232,55 @@ sys_fstatat(struct lwp *l, const struct sys_fstatat_args *uap,
return copyout(&sb, SCARG(uap, buf), sizeof(sb));
}
-/*
- * Get configurable pathname variables.
- */
-/* ARGSUSED */
-int
-sys_pathconf(struct lwp *l, const struct sys_pathconf_args *uap, register_t *retval)
+static int
+kern_pathconf(register_t *retval, const char *path, int name, int flag)
{
- /* {
- syscallarg(const char *) path;
- syscallarg(int) name;
- } */
int error;
struct pathbuf *pb;
struct nameidata nd;
- error = pathbuf_copyin(SCARG(uap, path), &pb);
+ error = pathbuf_copyin(path, &pb);
if (error) {
return error;
}
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
+ NDINIT(&nd, LOOKUP, flag | LOCKLEAF | TRYEMULROOT, pb);
if ((error = namei(&nd)) != 0) {
pathbuf_destroy(pb);
- return (error);
+ return error;
}
- error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
+ error = VOP_PATHCONF(nd.ni_vp, name, retval);
vput(nd.ni_vp);
pathbuf_destroy(pb);
- return (error);
+ return error;
+}
+
+/*
+ * Get configurable pathname variables.
+ */
+/* ARGSUSED */
+int
+sys_pathconf(struct lwp *l, const struct sys_pathconf_args *uap,
+ register_t *retval)
+{
+ /* {
+ syscallarg(const char *) path;
+ syscallarg(int) name;
+ } */
+ return kern_pathconf(retval, SCARG(uap, path), SCARG(uap, name),
+ FOLLOW);
+}
+
+/* ARGSUSED */
+int
+sys_lpathconf(struct lwp *l, const struct sys_lpathconf_args *uap,
+ register_t *retval)
+{
+ /* {
+ syscallarg(const char *) path;
+ syscallarg(int) name;
+ } */
+ return kern_pathconf(retval, SCARG(uap, path), SCARG(uap, name),
+ NOFOLLOW);
}
/*
@@ -4393,6 +4414,8 @@ do_sys_renameat(struct lwp *l, int fromfd, const char *from, int tofd,
KASSERT(tdvp != NULL);
KASSERT((tdvp == tvp) || (VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE));
+ if (fvp->v_type == VDIR)
+ tnd.ni_cnd.cn_flags |= WILLBEDIR;
/*
* Make sure neither tdvp nor tvp is locked.
*/
@@ -4683,6 +4706,7 @@ do_sys_mkdirat(struct lwp *l, int fdat, const char *path, mode_t mode,
vattr.va_type = VDIR;
/* We will read cwdi->cwdi_cmask unlocked. */
vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask;
+ nd.ni_cnd.cn_flags |= WILLBEDIR;
error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
if (!error)
vrele(nd.ni_vp);
diff --git a/sys/kern/vfs_xattr.c b/sys/kern/vfs_xattr.c
index bab7d5fddc7..da5aec67146 100644
--- a/sys/kern/vfs_xattr.c
+++ b/sys/kern/vfs_xattr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_xattr.c,v 1.34 2020/04/20 00:34:58 christos Exp $ */
+/* $NetBSD: vfs_xattr.c,v 1.35 2020/05/16 18:31:50 christos Exp $ */
/*-
* Copyright (c) 2005, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_xattr.c,v 1.34 2020/04/20 00:34:58 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_xattr.c,v 1.35 2020/05/16 18:31:50 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -96,7 +96,7 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_xattr.c,v 1.34 2020/04/20 00:34:58 christos Exp
* NOTE: Vnode must be locked.
*/
int
-extattr_check_cred(struct vnode *vp, const char *attr, kauth_cred_t cred,
+extattr_check_cred(struct vnode *vp, int attrspace, kauth_cred_t cred,
int access)
{
@@ -104,7 +104,7 @@ extattr_check_cred(struct vnode *vp, const char *attr, kauth_cred_t cred,
return (0);
return kauth_authorize_vnode(cred, kauth_extattr_action(access), vp,
- NULL, genfs_can_extattr(cred, access, vp, attr));
+ NULL, genfs_can_extattr(vp, cred, access, attrspace));
}
/*
diff --git a/sys/kern/vnode_if.c b/sys/kern/vnode_if.c
index 6e5b4658042..0ee974fd01a 100644
--- a/sys/kern/vnode_if.c
+++ b/sys/kern/vnode_if.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vnode_if.c,v 1.110 2020/02/23 22:15:19 ad Exp $ */
+/* $NetBSD: vnode_if.c,v 1.111 2020/05/16 18:31:50 christos Exp $ */
/*
* Warning: DO NOT EDIT! This file is automatically generated!
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vnode_if.c,v 1.110 2020/02/23 22:15:19 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vnode_if.c,v 1.111 2020/05/16 18:31:50 christos Exp $");
#include <sys/param.h>
#include <sys/mount.h>
@@ -349,7 +349,7 @@ const struct vnodeop_desc vop_access_desc = {
};
int
VOP_ACCESS(struct vnode *vp,
- int mode,
+ accmode_t accmode,
kauth_cred_t cred)
{
int error;
@@ -358,7 +358,7 @@ VOP_ACCESS(struct vnode *vp,
struct mount *mp;
a.a_desc = VDESC(vop_access);
a.a_vp = vp;
- a.a_mode = mode;
+ a.a_accmode = accmode;
a.a_cred = cred;
error = vop_pre(vp, &mp, &mpsafe, FST_NO);
if (error)
@@ -368,6 +368,40 @@ VOP_ACCESS(struct vnode *vp,
return error;
}
+const int vop_accessx_vp_offsets[] = {
+ VOPARG_OFFSETOF(struct vop_accessx_args,a_vp),
+ VDESC_NO_OFFSET
+};
+const struct vnodeop_desc vop_accessx_desc = {
+ VOP_ACCESSX_DESCOFFSET,
+ "vop_accessx",
+ 0,
+ vop_accessx_vp_offsets,
+ VDESC_NO_OFFSET,
+ VOPARG_OFFSETOF(struct vop_accessx_args, a_cred),
+ VDESC_NO_OFFSET,
+};
+int
+VOP_ACCESSX(struct vnode *vp,
+ accmode_t accmode,
+ kauth_cred_t cred)
+{
+ int error;
+ bool mpsafe;
+ struct vop_accessx_args a;
+ struct mount *mp;
+ a.a_desc = VDESC(vop_accessx);
+ a.a_vp = vp;
+ a.a_accmode = accmode;
+ a.a_cred = cred;
+ error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+ if (error)
+ return error;
+ error = (VCALL(vp, VOFFSET(vop_accessx), &a));
+ vop_post(vp, mp, mpsafe, FST_NO);
+ return error;
+}
+
const int vop_getattr_vp_offsets[] = {
VOPARG_OFFSETOF(struct vop_getattr_args,a_vp),
VDESC_NO_OFFSET
@@ -1634,6 +1668,114 @@ VOP_PUTPAGES(struct vnode *vp,
return error;
}
+const int vop_getacl_vp_offsets[] = {
+ VOPARG_OFFSETOF(struct vop_getacl_args,a_vp),
+ VDESC_NO_OFFSET
+};
+const struct vnodeop_desc vop_getacl_desc = {
+ VOP_GETACL_DESCOFFSET,
+ "vop_getacl",
+ 0,
+ vop_getacl_vp_offsets,
+ VDESC_NO_OFFSET,
+ VOPARG_OFFSETOF(struct vop_getacl_args, a_cred),
+ VDESC_NO_OFFSET,
+};
+int
+VOP_GETACL(struct vnode *vp,
+ acl_type_t type,
+ struct acl *aclp,
+ kauth_cred_t cred)
+{
+ int error;
+ bool mpsafe;
+ struct vop_getacl_args a;
+ struct mount *mp;
+ a.a_desc = VDESC(vop_getacl);
+ a.a_vp = vp;
+ a.a_type = type;
+ a.a_aclp = aclp;
+ a.a_cred = cred;
+ error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+ if (error)
+ return error;
+ error = (VCALL(vp, VOFFSET(vop_getacl), &a));
+ vop_post(vp, mp, mpsafe, FST_YES);
+ return error;
+}
+
+const int vop_setacl_vp_offsets[] = {
+ VOPARG_OFFSETOF(struct vop_setacl_args,a_vp),
+ VDESC_NO_OFFSET
+};
+const struct vnodeop_desc vop_setacl_desc = {
+ VOP_SETACL_DESCOFFSET,
+ "vop_setacl",
+ 0,
+ vop_setacl_vp_offsets,
+ VDESC_NO_OFFSET,
+ VOPARG_OFFSETOF(struct vop_setacl_args, a_cred),
+ VDESC_NO_OFFSET,
+};
+int
+VOP_SETACL(struct vnode *vp,
+ acl_type_t type,
+ struct acl *aclp,
+ kauth_cred_t cred)
+{
+ int error;
+ bool mpsafe;
+ struct vop_setacl_args a;
+ struct mount *mp;
+ a.a_desc = VDESC(vop_setacl);
+ a.a_vp = vp;
+ a.a_type = type;
+ a.a_aclp = aclp;
+ a.a_cred = cred;
+ error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+ if (error)
+ return error;
+ error = (VCALL(vp, VOFFSET(vop_setacl), &a));
+ vop_post(vp, mp, mpsafe, FST_YES);
+ return error;
+}
+
+const int vop_aclcheck_vp_offsets[] = {
+ VOPARG_OFFSETOF(struct vop_aclcheck_args,a_vp),
+ VDESC_NO_OFFSET
+};
+const struct vnodeop_desc vop_aclcheck_desc = {
+ VOP_ACLCHECK_DESCOFFSET,
+ "vop_aclcheck",
+ 0,
+ vop_aclcheck_vp_offsets,
+ VDESC_NO_OFFSET,
+ VOPARG_OFFSETOF(struct vop_aclcheck_args, a_cred),
+ VDESC_NO_OFFSET,
+};
+int
+VOP_ACLCHECK(struct vnode *vp,
+ acl_type_t type,
+ struct acl *aclp,
+ kauth_cred_t cred)
+{
+ int error;
+ bool mpsafe;
+ struct vop_aclcheck_args a;
+ struct mount *mp;
+ a.a_desc = VDESC(vop_aclcheck);
+ a.a_vp = vp;
+ a.a_type = type;
+ a.a_aclp = aclp;
+ a.a_cred = cred;
+ error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+ if (error)
+ return error;
+ error = (VCALL(vp, VOFFSET(vop_aclcheck), &a));
+ vop_post(vp, mp, mpsafe, FST_YES);
+ return error;
+}
+
const int vop_closeextattr_vp_offsets[] = {
VOPARG_OFFSETOF(struct vop_closeextattr_args,a_vp),
VDESC_NO_OFFSET
@@ -1864,6 +2006,7 @@ const struct vnodeop_desc * const vfs_op_descs[] = {
&vop_open_desc,
&vop_close_desc,
&vop_access_desc,
+ &vop_accessx_desc,
&vop_getattr_desc,
&vop_setattr_desc,
&vop_read_desc,
@@ -1900,6 +2043,9 @@ const struct vnodeop_desc * const vfs_op_descs[] = {
&vop_whiteout_desc,
&vop_getpages_desc,
&vop_putpages_desc,
+ &vop_getacl_desc,
+ &vop_setacl_desc,
+ &vop_aclcheck_desc,
&vop_closeextattr_desc,
&vop_getextattr_desc,
&vop_listextattr_desc,
diff --git a/sys/kern/vnode_if.sh b/sys/kern/vnode_if.sh
index acf9b14d38c..3d71b523531 100644
--- a/sys/kern/vnode_if.sh
+++ b/sys/kern/vnode_if.sh
@@ -29,7 +29,7 @@ copyright="\
* SUCH DAMAGE.
*/
"
-SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.69 2020/02/23 22:14:04 ad Exp $'
+SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.70 2020/05/16 18:31:50 christos Exp $'
# Script to produce VFS front-end sugar.
#
@@ -269,6 +269,8 @@ BEGIN {
printf("struct flock;\n");
printf("struct knote;\n");
printf("struct vm_page;\n");
+ printf("struct acl;\n");
+ printf("\n#include <sys/acl.h>\n");
}
printf("\n#ifndef _KERNEL\n#include <stdbool.h>\n#endif\n");
if (rump)
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index a1d2a04a339..7cac9c76dcc 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -1,4 +1,4 @@
-# $NetBSD: vnode_if.src,v 1.78 2019/10/11 08:04:52 hannken Exp $
+# $NetBSD: vnode_if.src,v 1.79 2020/05/16 18:31:50 christos Exp $
#
# Copyright (c) 1992, 1993
# The Regents of the University of California. All rights reserved.
@@ -128,7 +128,16 @@ vop_close {
#
vop_access {
IN LOCKED=YES struct vnode *vp;
- IN int mode;
+ IN accmode_t accmode;
+ IN kauth_cred_t cred;
+};
+
+#
+#% accessx vp L L L
+#
+vop_accessx {
+ IN LOCKED=YES struct vnode *vp;
+ IN accmode_t accmode;
IN kauth_cred_t cred;
};
@@ -517,6 +526,36 @@ vop_putpages {
};
#
+#% getacl vp L L L
+#
+vop_getacl {
+ IN struct vnode *vp;
+ IN acl_type_t type;
+ OUT struct acl *aclp;
+ IN kauth_cred_t cred;
+};
+
+#
+#% setacl vp L L L
+#
+vop_setacl {
+ IN struct vnode *vp;
+ IN acl_type_t type;
+ IN struct acl *aclp;
+ IN kauth_cred_t cred;
+};
+
+#
+#% aclcheck vp = = =
+#
+vop_aclcheck {
+ IN struct vnode *vp;
+ IN acl_type_t type;
+ IN struct acl *aclp;
+ IN kauth_cred_t cred;
+};
+
+#
#% closeextattr vp L L L
#
vop_closeextattr {
diff --git a/sys/miscfs/fdesc/fdesc_vnops.c b/sys/miscfs/fdesc/fdesc_vnops.c
index fd590029e96..08d61820547 100644
--- a/sys/miscfs/fdesc/fdesc_vnops.c
+++ b/sys/miscfs/fdesc/fdesc_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fdesc_vnops.c,v 1.132 2020/02/01 02:23:04 riastradh Exp $ */
+/* $NetBSD: fdesc_vnops.c,v 1.133 2020/05/16 18:31:50 christos Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.132 2020/02/01 02:23:04 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.133 2020/05/16 18:31:50 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -125,6 +125,7 @@ const struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
{ &vop_open_desc, fdesc_open }, /* open */
{ &vop_close_desc, fdesc_close }, /* close */
{ &vop_access_desc, fdesc_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, fdesc_getattr }, /* getattr */
{ &vop_setattr_desc, fdesc_setattr }, /* setattr */
{ &vop_read_desc, fdesc_read }, /* read */
diff --git a/sys/miscfs/fifofs/fifo_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c
index c700c3c2f45..9f3a636b802 100644
--- a/sys/miscfs/fifofs/fifo_vnops.c
+++ b/sys/miscfs/fifofs/fifo_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fifo_vnops.c,v 1.79 2017/10/25 08:12:39 maya Exp $ */
+/* $NetBSD: fifo_vnops.c,v 1.80 2020/05/16 18:31:51 christos Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fifo_vnops.c,v 1.79 2017/10/25 08:12:39 maya Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fifo_vnops.c,v 1.80 2020/05/16 18:31:51 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -637,6 +637,7 @@ const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
{ &vop_open_desc, fifo_open }, /* open */
{ &vop_close_desc, fifo_close }, /* close */
{ &vop_access_desc, genfs_ebadf }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, genfs_ebadf }, /* getattr */
{ &vop_setattr_desc, genfs_ebadf }, /* setattr */
{ &vop_read_desc, fifo_read }, /* read */
diff --git a/sys/miscfs/genfs/genfs.h b/sys/miscfs/genfs/genfs.h
index c759441d84a..e8fe535fbc9 100644
--- a/sys/miscfs/genfs/genfs.h
+++ b/sys/miscfs/genfs/genfs.h
@@ -1,4 +1,4 @@
-/* $NetBSD: genfs.h,v 1.33 2017/02/17 08:31:25 hannken Exp $ */
+/* $NetBSD: genfs.h,v 1.34 2020/05/16 18:31:51 christos Exp $ */
#ifndef _MISCFS_GENFS_GENFS_H_
#define _MISCFS_GENFS_GENFS_H_
@@ -8,7 +8,10 @@
struct componentname;
struct mount;
+struct acl;
+int genfs_access(void *);
+int genfs_accessx(void *);
int genfs_badop(void *);
int genfs_nullop(void *);
int genfs_enoioctl(void *);
@@ -48,14 +51,19 @@ void genfs_renamelock_exit(struct mount *);
int genfs_suspendctl(struct mount *, int);
-int genfs_can_access(enum vtype, mode_t, uid_t, gid_t, mode_t,
- kauth_cred_t);
-int genfs_can_chmod(enum vtype, kauth_cred_t, uid_t, gid_t, mode_t);
-int genfs_can_chown(kauth_cred_t, uid_t, gid_t, uid_t, gid_t);
-int genfs_can_chtimes(vnode_t *, u_int, uid_t, kauth_cred_t);
-int genfs_can_chflags(kauth_cred_t, enum vtype, uid_t, bool);
-int genfs_can_sticky(kauth_cred_t, uid_t, uid_t);
-int genfs_can_extattr(kauth_cred_t, int, vnode_t *, const char *);
+int genfs_can_access(struct vnode *, kauth_cred_t, uid_t, gid_t, mode_t,
+ struct acl *, accmode_t);
+int genfs_can_access_acl_posix1e(struct vnode *, kauth_cred_t, uid_t,
+ gid_t, mode_t, struct acl *, accmode_t);
+int genfs_can_access_acl_nfs4(struct vnode *, kauth_cred_t, uid_t, gid_t,
+ mode_t, struct acl *, accmode_t);
+int genfs_can_chmod(struct vnode *, kauth_cred_t, uid_t, gid_t, mode_t);
+int genfs_can_chown(struct vnode *, kauth_cred_t, uid_t, gid_t, uid_t,
+ gid_t);
+int genfs_can_chtimes(struct vnode *, kauth_cred_t, uid_t, u_int);
+int genfs_can_chflags(struct vnode *, kauth_cred_t, uid_t, bool);
+int genfs_can_sticky(struct vnode *, kauth_cred_t, uid_t, uid_t);
+int genfs_can_extattr(struct vnode *, kauth_cred_t, int, int);
/*
* Rename is complicated. Sorry.
diff --git a/sys/miscfs/genfs/genfs_rename.c b/sys/miscfs/genfs/genfs_rename.c
index 45aeb41de62..60557686104 100644
--- a/sys/miscfs/genfs/genfs_rename.c
+++ b/sys/miscfs/genfs/genfs_rename.c
@@ -1,4 +1,4 @@
-/* $NetBSD: genfs_rename.c,v 1.3 2017/03/30 09:11:12 hannken Exp $ */
+/* $NetBSD: genfs_rename.c,v 1.4 2020/05/16 18:31:51 christos Exp $ */
/*-
* Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfs_rename.c,v 1.3 2017/03/30 09:11:12 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_rename.c,v 1.4 2020/05/16 18:31:51 christos Exp $");
#include <sys/param.h>
#include <sys/kauth.h>
@@ -1148,7 +1148,7 @@ genfs_ufslike_check_sticky(kauth_cred_t cred, mode_t dmode, uid_t duid,
{
if ((dmode & S_ISTXT) && (vp != NULL))
- return genfs_can_sticky(cred, duid, uid);
+ return genfs_can_sticky(vp, cred, duid, uid);
return 0;
}
diff --git a/sys/miscfs/genfs/genfs_vnops.c b/sys/miscfs/genfs/genfs_vnops.c
index 80adb11bd71..41cddd38b34 100644
--- a/sys/miscfs/genfs/genfs_vnops.c
+++ b/sys/miscfs/genfs/genfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: genfs_vnops.c,v 1.203 2020/04/25 22:28:47 christos Exp $ */
+/* $NetBSD: genfs_vnops.c,v 1.204 2020/05/16 18:31:51 christos Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -57,7 +57,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.203 2020/04/25 22:28:47 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.204 2020/05/16 18:31:51 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -74,6 +74,7 @@ __KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.203 2020/04/25 22:28:47 christos E
#include <sys/file.h>
#include <sys/kauth.h>
#include <sys/stat.h>
+#include <sys/extattr.h>
#include <miscfs/genfs/genfs.h>
#include <miscfs/genfs/genfs_node.h>
@@ -668,53 +669,519 @@ genfs_node_wrlocked(struct vnode *vp)
return rw_write_held(&gp->g_glock);
}
+static int
+groupmember(gid_t gid, kauth_cred_t cred)
+{
+ int ismember;
+ int error = kauth_cred_ismember_gid(cred, gid, &ismember);
+ if (error)
+ return error;
+ if (kauth_cred_getegid(cred) == gid || ismember)
+ return 0;
+ return -1;
+}
+
/*
- * Do the usual access checking.
- * file_mode, uid and gid are from the vnode in question,
- * while acc_mode and cred are from the VOP_ACCESS parameter list
+ * Common filesystem object access control check routine. Accepts a
+ * vnode, cred, uid, gid, mode, acl, requested access mode.
+ * Returns 0 on success, or an errno on failure.
*/
int
-genfs_can_access(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid,
- mode_t acc_mode, kauth_cred_t cred)
+genfs_can_access(vnode_t *vp, kauth_cred_t cred, uid_t file_uid, gid_t file_gid,
+ mode_t file_mode, struct acl *acl, accmode_t accmode)
{
- mode_t mask;
- int error, ismember;
+ accmode_t dac_granted;
+ int error;
+
+ KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND)) == 0);
+ KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE));
+
+ /*
+ * Look for a normal, non-privileged way to access the file/directory
+ * as requested. If it exists, go with that.
+ */
- mask = 0;
-
- /* Otherwise, check the owner. */
- if (kauth_cred_geteuid(cred) == uid) {
- if (acc_mode & VEXEC)
- mask |= S_IXUSR;
- if (acc_mode & VREAD)
- mask |= S_IRUSR;
- if (acc_mode & VWRITE)
- mask |= S_IWUSR;
- return ((file_mode & mask) == mask ? 0 : EACCES);
+ dac_granted = 0;
+
+ /* Check the owner. */
+ if (kauth_cred_geteuid(cred) == file_uid) {
+ dac_granted |= VADMIN;
+ if (file_mode & S_IXUSR)
+ dac_granted |= VEXEC;
+ if (file_mode & S_IRUSR)
+ dac_granted |= VREAD;
+ if (file_mode & S_IWUSR)
+ dac_granted |= (VWRITE | VAPPEND);
+
+ return (accmode & dac_granted) == accmode ? 0 : EPERM;
}
+ /* Otherwise, check the groups (first match) */
/* Otherwise, check the groups. */
- error = kauth_cred_ismember_gid(cred, gid, &ismember);
- if (error)
- return (error);
- if (kauth_cred_getegid(cred) == gid || ismember) {
- if (acc_mode & VEXEC)
- mask |= S_IXGRP;
- if (acc_mode & VREAD)
- mask |= S_IRGRP;
- if (acc_mode & VWRITE)
- mask |= S_IWGRP;
- return ((file_mode & mask) == mask ? 0 : EACCES);
+ error = groupmember(file_gid, cred);
+ if (error > 0)
+ return error;
+ if (error == 0) {
+ if (file_mode & S_IXGRP)
+ dac_granted |= VEXEC;
+ if (file_mode & S_IRGRP)
+ dac_granted |= VREAD;
+ if (file_mode & S_IWGRP)
+ dac_granted |= (VWRITE | VAPPEND);
+
+ return (accmode & dac_granted) == accmode ? 0 : EACCES;
}
/* Otherwise, check everyone else. */
- if (acc_mode & VEXEC)
- mask |= S_IXOTH;
- if (acc_mode & VREAD)
- mask |= S_IROTH;
- if (acc_mode & VWRITE)
- mask |= S_IWOTH;
- return ((file_mode & mask) == mask ? 0 : EACCES);
+ if (file_mode & S_IXOTH)
+ dac_granted |= VEXEC;
+ if (file_mode & S_IROTH)
+ dac_granted |= VREAD;
+ if (file_mode & S_IWOTH)
+ dac_granted |= (VWRITE | VAPPEND);
+ return (accmode & dac_granted) == accmode ? 0 : EACCES;
+ return (0);
+}
+
+/*
+ * Implement a version of genfs_can_access() that understands POSIX.1e ACL
+ * semantics;
+ * the access ACL has already been prepared for evaluation by the file system
+ * and is passed via 'uid', 'gid', and 'acl'. Return 0 on success, else an
+ * errno value.
+ */
+int
+genfs_can_access_acl_posix1e(vnode_t *vp, kauth_cred_t cred, uid_t file_uid,
+ gid_t file_gid, mode_t file_mode, struct acl *acl, accmode_t accmode)
+{
+ struct acl_entry *acl_other, *acl_mask;
+ accmode_t dac_granted;
+ accmode_t acl_mask_granted;
+ int group_matched, i;
+ int error;
+
+ KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND)) == 0);
+ KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE));
+
+ /*
+ * The owner matches if the effective uid associated with the
+ * credential matches that of the ACL_USER_OBJ entry. While we're
+ * doing the first scan, also cache the location of the ACL_MASK and
+ * ACL_OTHER entries, preventing some future iterations.
+ */
+ acl_mask = acl_other = NULL;
+ for (i = 0; i < acl->acl_cnt; i++) {
+ struct acl_entry *ae = &acl->acl_entry[i];
+ switch (ae->ae_tag) {
+ case ACL_USER_OBJ:
+ if (kauth_cred_geteuid(cred) != file_uid)
+ break;
+ dac_granted = 0;
+ dac_granted |= VADMIN;
+ if (ae->ae_perm & ACL_EXECUTE)
+ dac_granted |= VEXEC;
+ if (ae->ae_perm & ACL_READ)
+ dac_granted |= VREAD;
+ if (ae->ae_perm & ACL_WRITE)
+ dac_granted |= (VWRITE | VAPPEND);
+ goto out;
+
+ case ACL_MASK:
+ acl_mask = ae;
+ break;
+
+ case ACL_OTHER:
+ acl_other = ae;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /*
+ * An ACL_OTHER entry should always exist in a valid access ACL. If
+ * it doesn't, then generate a serious failure. For now, this means
+ * a debugging message and EPERM, but in the future should probably
+ * be a panic.
+ */
+ if (acl_other == NULL) {
+ /*
+ * XXX This should never happen
+ */
+ printf("%s: ACL_OTHER missing\n", __func__);
+ return EPERM;
+ }
+
+ /*
+ * Checks against ACL_USER, ACL_GROUP_OBJ, and ACL_GROUP fields are
+ * masked by an ACL_MASK entry, if any. As such, first identify the
+ * ACL_MASK field, then iterate through identifying potential user
+ * matches, then group matches. If there is no ACL_MASK, assume that
+ * the mask allows all requests to succeed.
+ */
+ if (acl_mask != NULL) {
+ acl_mask_granted = 0;
+ if (acl_mask->ae_perm & ACL_EXECUTE)
+ acl_mask_granted |= VEXEC;
+ if (acl_mask->ae_perm & ACL_READ)
+ acl_mask_granted |= VREAD;
+ if (acl_mask->ae_perm & ACL_WRITE)
+ acl_mask_granted |= (VWRITE | VAPPEND);
+ } else
+ acl_mask_granted = VEXEC | VREAD | VWRITE | VAPPEND;
+
+ /*
+ * Check ACL_USER ACL entries. There will either be one or no
+ * matches; if there is one, we accept or rejected based on the
+ * match; otherwise, we continue on to groups.
+ */
+ for (i = 0; i < acl->acl_cnt; i++) {
+ struct acl_entry *ae = &acl->acl_entry[i];
+ switch (ae->ae_tag) {
+ case ACL_USER:
+ if (kauth_cred_geteuid(cred) != ae->ae_id)
+ break;
+ dac_granted = 0;
+ if (ae->ae_perm & ACL_EXECUTE)
+ dac_granted |= VEXEC;
+ if (ae->ae_perm & ACL_READ)
+ dac_granted |= VREAD;
+ if (ae->ae_perm & ACL_WRITE)
+ dac_granted |= (VWRITE | VAPPEND);
+ dac_granted &= acl_mask_granted;
+ goto out;
+ }
+ }
+
+ /*
+ * Group match is best-match, not first-match, so find a "best"
+ * match. Iterate across, testing each potential group match. Make
+ * sure we keep track of whether we found a match or not, so that we
+ * know if we should try again with any available privilege, or if we
+ * should move on to ACL_OTHER.
+ */
+ group_matched = 0;
+ for (i = 0; i < acl->acl_cnt; i++) {
+ struct acl_entry *ae = &acl->acl_entry[i];
+ switch (ae->ae_tag) {
+ case ACL_GROUP_OBJ:
+ error = groupmember(file_gid, cred);
+ if (error > 0)
+ return error;
+ if (error)
+ break;
+ dac_granted = 0;
+ if (ae->ae_perm & ACL_EXECUTE)
+ dac_granted |= VEXEC;
+ if (ae->ae_perm & ACL_READ)
+ dac_granted |= VREAD;
+ if (ae->ae_perm & ACL_WRITE)
+ dac_granted |= (VWRITE | VAPPEND);
+ dac_granted &= acl_mask_granted;
+
+ if ((accmode & dac_granted) == accmode)
+ return 0;
+
+ group_matched = 1;
+ break;
+
+ case ACL_GROUP:
+ error = groupmember(ae->ae_id, cred);
+ if (error > 0)
+ return error;
+ if (error)
+ break;
+ dac_granted = 0;
+ if (ae->ae_perm & ACL_EXECUTE)
+ dac_granted |= VEXEC;
+ if (ae->ae_perm & ACL_READ)
+ dac_granted |= VREAD;
+ if (ae->ae_perm & ACL_WRITE)
+ dac_granted |= (VWRITE | VAPPEND);
+ dac_granted &= acl_mask_granted;
+
+ if ((accmode & dac_granted) == accmode)
+ return 0;
+
+ group_matched = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (group_matched == 1) {
+ /*
+ * There was a match, but it did not grant rights via pure
+ * DAC. Try again, this time with privilege.
+ */
+ for (i = 0; i < acl->acl_cnt; i++) {
+ struct acl_entry *ae = &acl->acl_entry[i];
+ switch (ae->ae_tag) {
+ case ACL_GROUP_OBJ:
+ error = groupmember(file_gid, cred);
+ if (error > 0)
+ return error;
+ if (error)
+ break;
+ dac_granted = 0;
+ if (ae->ae_perm & ACL_EXECUTE)
+ dac_granted |= VEXEC;
+ if (ae->ae_perm & ACL_READ)
+ dac_granted |= VREAD;
+ if (ae->ae_perm & ACL_WRITE)
+ dac_granted |= (VWRITE | VAPPEND);
+ dac_granted &= acl_mask_granted;
+ goto out;
+
+ case ACL_GROUP:
+ error = groupmember(ae->ae_id, cred);
+ if (error > 0)
+ return error;
+ if (error)
+ break;
+ dac_granted = 0;
+ if (ae->ae_perm & ACL_EXECUTE)
+ dac_granted |= VEXEC;
+ if (ae->ae_perm & ACL_READ)
+ dac_granted |= VREAD;
+ if (ae->ae_perm & ACL_WRITE)
+ dac_granted |= (VWRITE | VAPPEND);
+ dac_granted &= acl_mask_granted;
+
+ goto out;
+ default:
+ break;
+ }
+ }
+ /*
+ * Even with privilege, group membership was not sufficient.
+ * Return failure.
+ */
+ dac_granted = 0;
+ goto out;
+ }
+
+ /*
+ * Fall back on ACL_OTHER. ACL_MASK is not applied to ACL_OTHER.
+ */
+ dac_granted = 0;
+ if (acl_other->ae_perm & ACL_EXECUTE)
+ dac_granted |= VEXEC;
+ if (acl_other->ae_perm & ACL_READ)
+ dac_granted |= VREAD;
+ if (acl_other->ae_perm & ACL_WRITE)
+ dac_granted |= (VWRITE | VAPPEND);
+
+out:
+ if ((accmode & dac_granted) == accmode)
+ return 0;
+ return (accmode & VADMIN) ? EPERM : EACCES;
+}
+
+static struct {
+ accmode_t accmode;
+ int mask;
+} accmode2mask[] = {
+ { VREAD, ACL_READ_DATA },
+ { VWRITE, ACL_WRITE_DATA },
+ { VAPPEND, ACL_APPEND_DATA },
+ { VEXEC, ACL_EXECUTE },
+ { VREAD_NAMED_ATTRS, ACL_READ_NAMED_ATTRS },
+ { VWRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS },
+ { VDELETE_CHILD, ACL_DELETE_CHILD },
+ { VREAD_ATTRIBUTES, ACL_READ_ATTRIBUTES },
+ { VWRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES },
+ { VDELETE, ACL_DELETE },
+ { VREAD_ACL, ACL_READ_ACL },
+ { VWRITE_ACL, ACL_WRITE_ACL },
+ { VWRITE_OWNER, ACL_WRITE_OWNER },
+ { VSYNCHRONIZE, ACL_SYNCHRONIZE },
+ { 0, 0 },
+};
+
+static int
+_access_mask_from_accmode(accmode_t accmode)
+{
+ int access_mask = 0, i;
+
+ for (i = 0; accmode2mask[i].accmode != 0; i++) {
+ if (accmode & accmode2mask[i].accmode)
+ access_mask |= accmode2mask[i].mask;
+ }
+
+ /*
+ * VAPPEND is just a modifier for VWRITE; if the caller asked
+ * for 'VAPPEND | VWRITE', we want to check for ACL_APPEND_DATA only.
+ */
+ if (access_mask & ACL_APPEND_DATA)
+ access_mask &= ~ACL_WRITE_DATA;
+
+ return (access_mask);
+}
+
+/*
+ * Return 0, iff access is allowed, 1 otherwise.
+ */
+static int
+_acl_denies(const struct acl *aclp, int access_mask, kauth_cred_t cred,
+ int file_uid, int file_gid, int *denied_explicitly)
+{
+ int i, error;
+ const struct acl_entry *ae;
+
+ if (denied_explicitly != NULL)
+ *denied_explicitly = 0;
+
+ KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES);
+
+ for (i = 0; i < aclp->acl_cnt; i++) {
+ ae = &(aclp->acl_entry[i]);
+
+ if (ae->ae_entry_type != ACL_ENTRY_TYPE_ALLOW &&
+ ae->ae_entry_type != ACL_ENTRY_TYPE_DENY)
+ continue;
+ if (ae->ae_flags & ACL_ENTRY_INHERIT_ONLY)
+ continue;
+ switch (ae->ae_tag) {
+ case ACL_USER_OBJ:
+ if (kauth_cred_geteuid(cred) != file_uid)
+ continue;
+ break;
+ case ACL_USER:
+ if (kauth_cred_geteuid(cred) != ae->ae_id)
+ continue;
+ break;
+ case ACL_GROUP_OBJ:
+ error = groupmember(file_gid, cred);
+ if (error > 0)
+ return error;
+ if (error != 0)
+ continue;
+ break;
+ case ACL_GROUP:
+ error = groupmember(ae->ae_id, cred);
+ if (error > 0)
+ return error;
+ if (error != 0)
+ continue;
+ break;
+ default:
+ KASSERT(ae->ae_tag == ACL_EVERYONE);
+ }
+
+ if (ae->ae_entry_type == ACL_ENTRY_TYPE_DENY) {
+ if (ae->ae_perm & access_mask) {
+ if (denied_explicitly != NULL)
+ *denied_explicitly = 1;
+ return (1);
+ }
+ }
+
+ access_mask &= ~(ae->ae_perm);
+ if (access_mask == 0)
+ return (0);
+ }
+
+ if (access_mask == 0)
+ return (0);
+
+ return (1);
+}
+
+int
+genfs_can_access_acl_nfs4(vnode_t *vp, kauth_cred_t cred, uid_t file_uid,
+ gid_t file_gid, mode_t file_mode, struct acl *aclp, accmode_t accmode)
+{
+ int denied, explicitly_denied, access_mask, is_directory,
+ must_be_owner = 0;
+ file_mode = 0;
+
+ KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND |
+ VEXPLICIT_DENY | VREAD_NAMED_ATTRS | VWRITE_NAMED_ATTRS |
+ VDELETE_CHILD | VREAD_ATTRIBUTES | VWRITE_ATTRIBUTES | VDELETE |
+ VREAD_ACL | VWRITE_ACL | VWRITE_OWNER | VSYNCHRONIZE)) == 0);
+ KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE));
+
+#ifdef ACL_DEBUG
+ char buf[128];
+ snprintb(buf, sizeof(buf), __VNODE_PERM_BITS, accmode);
+ printf("%s: %s uid=%d gid=%d\n", __func__, buf, file_uid, file_gid);
+#endif
+
+ if (accmode & VADMIN)
+ must_be_owner = 1;
+
+ /*
+ * Ignore VSYNCHRONIZE permission.
+ */
+ accmode &= ~VSYNCHRONIZE;
+
+ access_mask = _access_mask_from_accmode(accmode);
+
+ if (vp && vp->v_type == VDIR)
+ is_directory = 1;
+ else
+ is_directory = 0;
+
+ /*
+ * File owner is always allowed to read and write the ACL
+ * and basic attributes. This is to prevent a situation
+ * where user would change ACL in a way that prevents him
+ * from undoing the change.
+ */
+ if (kauth_cred_geteuid(cred) == file_uid)
+ access_mask &= ~(ACL_READ_ACL | ACL_WRITE_ACL |
+ ACL_READ_ATTRIBUTES | ACL_WRITE_ATTRIBUTES);
+
+ /*
+ * Ignore append permission for regular files; use write
+ * permission instead.
+ */
+ if (!is_directory && (access_mask & ACL_APPEND_DATA)) {
+ access_mask &= ~ACL_APPEND_DATA;
+ access_mask |= ACL_WRITE_DATA;
+ }
+
+ denied = _acl_denies(aclp, access_mask, cred, file_uid, file_gid,
+ &explicitly_denied);
+
+ if (must_be_owner) {
+ if (kauth_cred_geteuid(cred) != file_uid)
+ denied = EPERM;
+ }
+
+ /*
+ * For VEXEC, ensure that at least one execute bit is set for
+ * non-directories. We have to check the mode here to stay
+ * consistent with execve(2). See the test in
+ * exec_check_permissions().
+ */
+ __acl_nfs4_sync_mode_from_acl(&file_mode, aclp);
+ if (!denied && !is_directory && (accmode & VEXEC) &&
+ (file_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
+ denied = EACCES;
+
+ if (!denied)
+ return (0);
+
+ /*
+ * Access failed. Iff it was not denied explicitly and
+ * VEXPLICIT_DENY flag was specified, allow access.
+ */
+ if ((accmode & VEXPLICIT_DENY) && explicitly_denied == 0)
+ return (0);
+
+ accmode &= ~VEXPLICIT_DENY;
+
+ if (accmode & (VADMIN_PERMS | VDELETE_CHILD | VDELETE))
+ denied = EPERM;
+ else
+ denied = EACCES;
+
+ return (denied);
}
/*
@@ -724,29 +1191,32 @@ genfs_can_access(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid,
* - You must own the file, and
* - You must not set the "sticky" bit (meaningless, see chmod(2))
* - You must be a member of the group if you're trying to set the
- * SGIDf bit
+ * SGIDf bit
*
- * cred - credentials of the invoker
* vp - vnode of the file-system object
+ * cred - credentials of the invoker
* cur_uid, cur_gid - current uid/gid of the file-system object
* new_mode - new mode for the file-system object
*
* Returns 0 if the change is allowed, or an error value otherwise.
*/
int
-genfs_can_chmod(enum vtype type, kauth_cred_t cred, uid_t cur_uid,
+genfs_can_chmod(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid,
gid_t cur_gid, mode_t new_mode)
{
int error;
- /* The user must own the file. */
- if (kauth_cred_geteuid(cred) != cur_uid)
- return (EPERM);
+ /*
+ * To modify the permissions on a file, must possess VADMIN
+ * for that file.
+ */
+ if ((error = VOP_ACCESSX(vp, VWRITE_ACL, cred)) != 0)
+ return (error);
/*
* Unprivileged users can't set the sticky bit on files.
*/
- if ((type != VDIR) && (new_mode & S_ISTXT))
+ if ((vp->v_type != VDIR) && (new_mode & S_ISTXT))
return (EFTYPE);
/*
@@ -762,6 +1232,12 @@ genfs_can_chmod(enum vtype type, kauth_cred_t cred, uid_t cur_uid,
return (EPERM);
}
+ /*
+ * Deny setting setuid if we are not the file owner.
+ */
+ if ((new_mode & S_ISUID) && cur_uid != kauth_cred_geteuid(cred))
+ return (EPERM);
+
return (0);
}
@@ -773,6 +1249,7 @@ genfs_can_chmod(enum vtype type, kauth_cred_t cred, uid_t cur_uid,
* - You must not try to change ownership, and
* - You must be member of the new group
*
+ * vp - vnode
* cred - credentials of the invoker
* cur_uid, cur_gid - current uid/gid of the file-system object
* new_uid, new_gid - target uid/gid of the file-system object
@@ -780,12 +1257,19 @@ genfs_can_chmod(enum vtype type, kauth_cred_t cred, uid_t cur_uid,
* Returns 0 if the change is allowed, or an error value otherwise.
*/
int
-genfs_can_chown(kauth_cred_t cred, uid_t cur_uid,
+genfs_can_chown(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid,
gid_t cur_gid, uid_t new_uid, gid_t new_gid)
{
int error, ismember;
/*
+ * To modify the ownership of a file, must possess VADMIN for that
+ * file.
+ */
+ if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred)) != 0)
+ return (error);
+
+ /*
* You can only change ownership of a file if:
* You own the file and...
*/
@@ -822,10 +1306,23 @@ genfs_can_chown(kauth_cred_t cred, uid_t cur_uid,
}
int
-genfs_can_chtimes(vnode_t *vp, u_int vaflags, uid_t owner_uid,
- kauth_cred_t cred)
+genfs_can_chtimes(vnode_t *vp, kauth_cred_t cred, uid_t owner_uid,
+ u_int vaflags)
{
int error;
+ /*
+ * Grant permission if the caller is the owner of the file, or
+ * the super-user, or has ACL_WRITE_ATTRIBUTES permission on
+ * on the file. If the time pointer is null, then write
+ * permission on the file is also sufficient.
+ *
+ * From NFSv4.1, draft 21, 6.2.1.3.1, Discussion of Mask Attributes:
+ * A user having ACL_WRITE_DATA or ACL_WRITE_ATTRIBUTES
+ * will be allowed to set the times [..] to the current
+ * server time.
+ */
+ if ((error = VOP_ACCESSX(vp, VWRITE_ATTRIBUTES, cred)) != 0)
+ return (error);
/* Must be owner, or... */
if (kauth_cred_geteuid(cred) == owner_uid)
@@ -851,13 +1348,14 @@ genfs_can_chtimes(vnode_t *vp, u_int vaflags, uid_t owner_uid,
* - You must not change system flags, and
* - You must not change flags on character/block devices.
*
+ * vp - vnode
* cred - credentials of the invoker
* owner_uid - uid of the file-system object
* changing_sysflags - true if the invoker wants to change system flags
*/
int
-genfs_can_chflags(kauth_cred_t cred, enum vtype type, uid_t owner_uid,
- bool changing_sysflags)
+genfs_can_chflags(vnode_t *vp, kauth_cred_t cred,
+ uid_t owner_uid, bool changing_sysflags)
{
/* The user must own the file. */
@@ -873,7 +1371,7 @@ genfs_can_chflags(kauth_cred_t cred, enum vtype type, uid_t owner_uid,
* Unprivileged users cannot change the flags on devices, even if they
* own them.
*/
- if (type == VCHR || type == VBLK) {
+ if (vp->v_type == VCHR || vp->v_type == VBLK) {
return EPERM;
}
@@ -891,7 +1389,7 @@ genfs_can_chflags(kauth_cred_t cred, enum vtype type, uid_t owner_uid,
* directory or the file being deleted.
*/
int
-genfs_can_sticky(kauth_cred_t cred, uid_t dir_uid, uid_t file_uid)
+genfs_can_sticky(vnode_t *vp, kauth_cred_t cred, uid_t dir_uid, uid_t file_uid)
{
if (kauth_cred_geteuid(cred) != dir_uid &&
kauth_cred_geteuid(cred) != file_uid)
@@ -901,16 +1399,49 @@ genfs_can_sticky(kauth_cred_t cred, uid_t dir_uid, uid_t file_uid)
}
int
-genfs_can_extattr(kauth_cred_t cred, int access_mode, vnode_t *vp,
- const char *attr)
+genfs_can_extattr(vnode_t *vp, kauth_cred_t cred, int accmode,
+ int attrnamespace)
{
/*
- * This string comparison is bogus: see xattr_native in vfs_xattr.c;
- * it is going to go away soon.
+ * Kernel-invoked always succeeds.
*/
- if (strncasecmp(attr, "system.", 7) == 0)
- return kauth_authorize_system(cred, KAUTH_SYSTEM_FS_EXTATTR,
- 0, vp->v_mount, NULL, NULL);
+ if (cred == NOCRED)
+ return 0;
+
+ switch (attrnamespace) {
+ case EXTATTR_NAMESPACE_SYSTEM:
+ return kauth_authorize_system(cred, KAUTH_SYSTEM_FS_EXTATTR,
+ 0, vp->v_mount, NULL, NULL);
+ case EXTATTR_NAMESPACE_USER:
+ return VOP_ACCESS(vp, accmode, cred);
+ default:
+ return EPERM;
+ }
+}
+
+int
+genfs_access(void *v)
+{
+ struct vop_access_args *ap = v;
+
+ KASSERT((ap->a_accmode & ~(VEXEC | VWRITE | VREAD | VADMIN |
+ VAPPEND)) == 0);
+
+ return VOP_ACCESSX(ap->a_vp, ap->a_accmode, ap->a_cred);
+}
+
+int
+genfs_accessx(void *v)
+{
+ struct vop_accessx_args *ap = v;
+ int error;
+ accmode_t accmode = ap->a_accmode;
+ error = vfs_unixify_accmode(&accmode);
+ if (error != 0)
+ return error;
+
+ if (accmode == 0)
+ return 0;
- return VOP_ACCESS(vp, access_mode, cred);
+ return VOP_ACCESS(ap->a_vp, accmode, ap->a_cred);
}
diff --git a/sys/miscfs/genfs/layer_vnops.c b/sys/miscfs/genfs/layer_vnops.c
index e08cd2564ae..d47d6996aa6 100644
--- a/sys/miscfs/genfs/layer_vnops.c
+++ b/sys/miscfs/genfs/layer_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: layer_vnops.c,v 1.70 2020/04/13 19:23:19 ad Exp $ */
+/* $NetBSD: layer_vnops.c,v 1.71 2020/05/16 18:31:51 christos Exp $ */
/*
* Copyright (c) 1999 National Aeronautics & Space Administration
@@ -170,7 +170,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.70 2020/04/13 19:23:19 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.71 2020/05/16 18:31:51 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -466,19 +466,19 @@ layer_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
struct lwp *a_l;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
- mode_t mode = ap->a_mode;
+ accmode_t accmode = ap->a_accmode;
/*
* Disallow write attempts on read-only layers;
* unless the file is a socket, fifo, or a block or
* character device resident on the file system.
*/
- if (mode & VWRITE) {
+ if (accmode & VWRITE) {
switch (vp->v_type) {
case VDIR:
case VLNK:
diff --git a/sys/miscfs/kernfs/kernfs_vnops.c b/sys/miscfs/kernfs/kernfs_vnops.c
index 4cc5f72ebce..9dbb3f69643 100644
--- a/sys/miscfs/kernfs/kernfs_vnops.c
+++ b/sys/miscfs/kernfs/kernfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kernfs_vnops.c,v 1.164 2020/02/24 20:44:25 ad Exp $ */
+/* $NetBSD: kernfs_vnops.c,v 1.165 2020/05/16 18:31:51 christos Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.164 2020/02/24 20:44:25 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.165 2020/05/16 18:31:51 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -188,6 +188,7 @@ const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
{ &vop_open_desc, kernfs_open }, /* open */
{ &vop_close_desc, kernfs_close }, /* close */
{ &vop_access_desc, kernfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, kernfs_getattr }, /* getattr */
{ &vop_setattr_desc, kernfs_setattr }, /* setattr */
{ &vop_read_desc, kernfs_read }, /* read */
@@ -236,6 +237,7 @@ const struct vnodeopv_entry_desc kernfs_specop_entries[] = {
{ &vop_open_desc, spec_open }, /* open */
{ &vop_close_desc, spec_close }, /* close */
{ &vop_access_desc, kernfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, kernfs_getattr }, /* getattr */
{ &vop_setattr_desc, kernfs_setattr }, /* setattr */
{ &vop_read_desc, spec_read }, /* read */
@@ -640,7 +642,7 @@ kernfs_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vattr va;
@@ -650,9 +652,9 @@ kernfs_access(void *v)
return (error);
return kauth_authorize_vnode(ap->a_cred,
- KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode),
- ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode,
- va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
+ KAUTH_ACCESS_ACTION(ap->a_accmode, ap->a_vp->v_type, va.va_mode),
+ ap->a_vp, NULL, genfs_can_access(ap->a_vp, ap->a_cred,
+ va.va_uid, va.va_gid, va.va_mode, NULL, ap->a_accmode));
}
static int
diff --git a/sys/miscfs/nullfs/null_vnops.c b/sys/miscfs/nullfs/null_vnops.c
index a43ffea082c..efb93398001 100644
--- a/sys/miscfs/nullfs/null_vnops.c
+++ b/sys/miscfs/nullfs/null_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: null_vnops.c,v 1.42 2017/06/04 08:02:26 hannken Exp $ */
+/* $NetBSD: null_vnops.c,v 1.43 2020/05/16 18:31:51 christos Exp $ */
/*
* Copyright (c) 1999 National Aeronautics & Space Administration
@@ -80,7 +80,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: null_vnops.c,v 1.42 2017/06/04 08:02:26 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: null_vnops.c,v 1.43 2020/05/16 18:31:51 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -103,6 +103,7 @@ const struct vnodeopv_entry_desc null_vnodeop_entries[] = {
{ &vop_setattr_desc, layer_setattr },
{ &vop_getattr_desc, layer_getattr },
{ &vop_access_desc, layer_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_fsync_desc, layer_fsync },
{ &vop_inactive_desc, layer_inactive },
{ &vop_reclaim_desc, layer_reclaim },
diff --git a/sys/miscfs/overlay/overlay_vnops.c b/sys/miscfs/overlay/overlay_vnops.c
index ae44a27f624..6ea16aad815 100644
--- a/sys/miscfs/overlay/overlay_vnops.c
+++ b/sys/miscfs/overlay/overlay_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: overlay_vnops.c,v 1.24 2017/06/04 08:02:26 hannken Exp $ */
+/* $NetBSD: overlay_vnops.c,v 1.25 2020/05/16 18:31:51 christos Exp $ */
/*
* Copyright (c) 1999, 2000 National Aeronautics & Space Administration
@@ -67,7 +67,7 @@
*
* Ancestors:
* @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
- * $Id: overlay_vnops.c,v 1.24 2017/06/04 08:02:26 hannken Exp $
+ * $Id: overlay_vnops.c,v 1.25 2020/05/16 18:31:51 christos Exp $
* ...and...
* @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
*/
@@ -126,7 +126,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: overlay_vnops.c,v 1.24 2017/06/04 08:02:26 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: overlay_vnops.c,v 1.25 2020/05/16 18:31:51 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -151,6 +151,7 @@ const struct vnodeopv_entry_desc overlay_vnodeop_entries[] = {
{ &vop_setattr_desc, layer_setattr },
{ &vop_getattr_desc, layer_getattr },
{ &vop_access_desc, layer_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_fsync_desc, layer_fsync },
{ &vop_inactive_desc, layer_inactive },
{ &vop_reclaim_desc, layer_reclaim },
diff --git a/sys/miscfs/procfs/procfs_vnops.c b/sys/miscfs/procfs/procfs_vnops.c
index d36201903ed..834f14fb54b 100644
--- a/sys/miscfs/procfs/procfs_vnops.c
+++ b/sys/miscfs/procfs/procfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: procfs_vnops.c,v 1.212 2020/04/29 01:56:54 thorpej Exp $ */
+/* $NetBSD: procfs_vnops.c,v 1.213 2020/05/16 18:31:51 christos Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc.
@@ -105,7 +105,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.212 2020/04/29 01:56:54 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.213 2020/05/16 18:31:51 christos Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@@ -261,6 +261,7 @@ const struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
{ &vop_open_desc, procfs_open }, /* open */
{ &vop_close_desc, procfs_close }, /* close */
{ &vop_access_desc, procfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, procfs_getattr }, /* getattr */
{ &vop_setattr_desc, procfs_setattr }, /* setattr */
{ &vop_read_desc, procfs_read }, /* read */
@@ -969,7 +970,7 @@ procfs_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vattr va;
@@ -979,9 +980,9 @@ procfs_access(void *v)
return (error);
return kauth_authorize_vnode(ap->a_cred,
- KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode),
- ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode,
- va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
+ KAUTH_ACCESS_ACTION(ap->a_accmode, ap->a_vp->v_type, va.va_mode),
+ ap->a_vp, NULL, genfs_can_access(ap->a_vp, ap->a_cred,
+ va.va_uid, va.va_gid, va.va_mode, NULL, ap->a_accmode));
}
/*
diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c
index 57ab5a1ba2c..6c7a307c53c 100644
--- a/sys/miscfs/specfs/spec_vnops.c
+++ b/sys/miscfs/specfs/spec_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: spec_vnops.c,v 1.177 2020/04/13 20:02:27 jdolecek Exp $ */
+/* $NetBSD: spec_vnops.c,v 1.178 2020/05/16 18:31:51 christos Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.177 2020/04/13 20:02:27 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.178 2020/05/16 18:31:51 christos Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@@ -121,6 +121,7 @@ const struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
{ &vop_open_desc, spec_open }, /* open */
{ &vop_close_desc, spec_close }, /* close */
{ &vop_access_desc, spec_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, spec_getattr }, /* getattr */
{ &vop_setattr_desc, spec_setattr }, /* setattr */
{ &vop_read_desc, spec_read }, /* read */
diff --git a/sys/miscfs/umapfs/umap_vnops.c b/sys/miscfs/umapfs/umap_vnops.c
index fa68630a656..54c7cd53c42 100644
--- a/sys/miscfs/umapfs/umap_vnops.c
+++ b/sys/miscfs/umapfs/umap_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: umap_vnops.c,v 1.60 2017/06/04 08:02:26 hannken Exp $ */
+/* $NetBSD: umap_vnops.c,v 1.61 2020/05/16 18:31:51 christos Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umap_vnops.c,v 1.60 2017/06/04 08:02:26 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umap_vnops.c,v 1.61 2020/05/16 18:31:51 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -92,6 +92,7 @@ const struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
{ &vop_close_desc, layer_close },
{ &vop_setattr_desc, layer_setattr },
{ &vop_access_desc, layer_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_remove_desc, layer_remove },
{ &vop_revoke_desc, layer_revoke },
{ &vop_rmdir_desc, layer_rmdir },
diff --git a/sys/modules/compat_netbsd32/Makefile b/sys/modules/compat_netbsd32/Makefile
index 7f25c43d74c..1748803ac76 100644
--- a/sys/modules/compat_netbsd32/Makefile
+++ b/sys/modules/compat_netbsd32/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.34 2020/05/02 22:19:47 thorpej Exp $
+# $NetBSD: Makefile,v 1.35 2020/05/16 18:31:52 christos Exp $
.include "../Makefile.inc"
.include "../Makefile.assym"
@@ -29,6 +29,7 @@ CPPFLAGS+= -I${NETBSDSRCDIR}/sys/external/bsd/drm2/dist/uapi
.if ${NETBSD32_DRMKMS:Uno} == "yes"
SRCS+= netbsd32_drm.c
.endif
+SRCS+= netbsd32_acl.c
SRCS+= netbsd32_core.c netbsd32_event.c
SRCS+= netbsd32_exec_elf32.c netbsd32_execve.c
SRCS+= netbsd32_fd.c netbsd32_fs.c
diff --git a/sys/modules/ffs/Makefile b/sys/modules/ffs/Makefile
index cd7892c9714..2d5785e0376 100644
--- a/sys/modules/ffs/Makefile
+++ b/sys/modules/ffs/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.14 2020/04/18 19:18:33 christos Exp $
+# $NetBSD: Makefile,v 1.15 2020/05/16 18:31:52 christos Exp $
.include "../Makefile.inc"
@@ -6,7 +6,7 @@
KMOD= ffs
CPPFLAGS+= -DUFS_DIRHASH -DFFS_EI -DWAPBL -DAPPLE_UFS -DQUOTA -DQUOTA2
-CPPFLAGS+= -DUFS_EXTATTR
+CPPFLAGS+= -DUFS_EXTATTR -DUFS_ACL
CWARNFLAGS.clang= -Wno-conversion
diff --git a/sys/modules/ufs/Makefile b/sys/modules/ufs/Makefile
index aac917b8753..431fa85c258 100644
--- a/sys/modules/ufs/Makefile
+++ b/sys/modules/ufs/Makefile
@@ -1,16 +1,16 @@
-# $NetBSD: Makefile,v 1.3 2020/04/12 01:39:57 htodd Exp $
+# $NetBSD: Makefile,v 1.4 2020/05/16 18:31:52 christos Exp $
.include "../Makefile.inc"
KMOD= ufs
CPPFLAGS+= -DUFS_DIRHASH -DFFS_EI -DWAPBL -DAPPLE_UFS -DQUOTA -DQUOTA2
-CPPFLAGS+= -DUFS_EXTATTR
+CPPFLAGS+= -DUFS_EXTATTR -DUFS_ACL
CWARNFLAGS.clang= -Wno-conversion
.PATH: ${S}/ufs/ufs
-SRCS= ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \
+SRCS= ufs_acl.c ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \
ufs_lookup.c ufs_quota.c ufs_quota1.c ufs_quota2.c ufs_rename.c \
ufs_vfsops.c ufs_vnops.c quota1_subr.c quota2_subr.c
diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c
index f3d4bc11d8a..61987a8997b 100644
--- a/sys/nfs/nfs_vnops.c
+++ b/sys/nfs/nfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_vnops.c,v 1.314 2020/04/13 19:23:20 ad Exp $ */
+/* $NetBSD: nfs_vnops.c,v 1.315 2020/05/16 18:31:52 christos Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.314 2020/04/13 19:23:20 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.315 2020/05/16 18:31:52 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_nfs.h"
@@ -103,6 +103,7 @@ const struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
{ &vop_open_desc, nfs_open }, /* open */
{ &vop_close_desc, nfs_close }, /* close */
{ &vop_access_desc, nfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, nfs_getattr }, /* getattr */
{ &vop_setattr_desc, nfs_setattr }, /* setattr */
{ &vop_read_desc, nfs_read }, /* read */
@@ -156,6 +157,7 @@ const struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
{ &vop_open_desc, spec_open }, /* open */
{ &vop_close_desc, nfsspec_close }, /* close */
{ &vop_access_desc, nfsspec_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, nfs_getattr }, /* getattr */
{ &vop_setattr_desc, nfs_setattr }, /* setattr */
{ &vop_read_desc, nfsspec_read }, /* read */
@@ -206,6 +208,7 @@ const struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
{ &vop_open_desc, vn_fifo_bypass }, /* open */
{ &vop_close_desc, nfsfifo_close }, /* close */
{ &vop_access_desc, nfsspec_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, nfs_getattr }, /* getattr */
{ &vop_setattr_desc, nfs_setattr }, /* setattr */
{ &vop_read_desc, nfsfifo_read }, /* read */
@@ -316,7 +319,7 @@ nfs_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
@@ -344,9 +347,9 @@ nfs_access(void *v)
*/
if (cachevalid) {
if (!np->n_accerror) {
- if ((np->n_accmode & ap->a_mode) == ap->a_mode)
+ if ((np->n_accmode & ap->a_accmode) == ap->a_accmode)
return np->n_accerror;
- } else if ((np->n_accmode & ap->a_mode) == np->n_accmode)
+ } else if ((np->n_accmode & ap->a_accmode) == np->n_accmode)
return np->n_accerror;
}
@@ -364,20 +367,20 @@ nfs_access(void *v)
nfsm_reqhead(np, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
nfsm_fhtom(np, v3);
nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
- if (ap->a_mode & VREAD)
+ if (ap->a_accmode & VREAD)
mode = NFSV3ACCESS_READ;
else
mode = 0;
if (vp->v_type != VDIR) {
- if (ap->a_mode & VWRITE)
+ if (ap->a_accmode & VWRITE)
mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
- if (ap->a_mode & VEXEC)
+ if (ap->a_accmode & VEXEC)
mode |= NFSV3ACCESS_EXECUTE;
} else {
- if (ap->a_mode & VWRITE)
+ if (ap->a_accmode & VWRITE)
mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
NFSV3ACCESS_DELETE);
- if (ap->a_mode & VEXEC)
+ if (ap->a_accmode & VEXEC)
mode |= NFSV3ACCESS_LOOKUP;
}
*tl = txdr_unsigned(mode);
@@ -404,7 +407,7 @@ nfs_access(void *v)
* unless the file is a socket, fifo, or a block or character
* device resident on the filesystem.
*/
- if (!error && (ap->a_mode & VWRITE) &&
+ if (!error && (ap->a_accmode & VWRITE) &&
(vp->v_mount->mnt_flag & MNT_RDONLY)) {
switch (vp->v_type) {
case VREG:
@@ -425,13 +428,13 @@ nfs_access(void *v)
if (cachevalid && np->n_accstamp != -1 &&
error == np->n_accerror) {
if (!error)
- np->n_accmode |= ap->a_mode;
- else if ((np->n_accmode & ap->a_mode) == ap->a_mode)
- np->n_accmode = ap->a_mode;
+ np->n_accmode |= ap->a_accmode;
+ else if ((np->n_accmode & ap->a_accmode) == ap->a_accmode)
+ np->n_accmode = ap->a_accmode;
} else {
np->n_accstamp = time_uptime;
np->n_accuid = kauth_cred_geteuid(ap->a_cred);
- np->n_accmode = ap->a_mode;
+ np->n_accmode = ap->a_accmode;
np->n_accerror = error;
}
}
@@ -3346,7 +3349,7 @@ nfsspec_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
struct lwp *a_l;
} */ *ap = v;
@@ -3363,7 +3366,7 @@ nfsspec_access(void *v)
* unless the file is a socket, fifo, or a block or character
* device resident on the filesystem.
*/
- if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
+ if ((ap->a_accmode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
switch (vp->v_type) {
case VREG:
case VDIR:
@@ -3374,9 +3377,10 @@ nfsspec_access(void *v)
}
}
- return kauth_authorize_vnode(ap->a_cred, KAUTH_ACCESS_ACTION(ap->a_mode,
- va.va_type, va.va_mode), vp, NULL, genfs_can_access(va.va_type,
- va.va_mode, va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
+ return kauth_authorize_vnode(ap->a_cred, KAUTH_ACCESS_ACTION(
+ ap->a_accmode, va.va_type, va.va_mode), vp, NULL, genfs_can_access(
+ vp, ap->a_cred, va.va_uid, va.va_gid, va.va_mode, NULL,
+ ap->a_accmode));
}
/*
diff --git a/sys/rump/fs/lib/libffs/Makefile b/sys/rump/fs/lib/libffs/Makefile
index 857eba8bcbe..e1f1f2b1c41 100644
--- a/sys/rump/fs/lib/libffs/Makefile
+++ b/sys/rump/fs/lib/libffs/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.19 2020/04/25 15:42:15 bouyer Exp $
+# $NetBSD: Makefile,v 1.20 2020/05/16 18:31:52 christos Exp $
#
.PATH: ${.CURDIR}/../../../../ufs/ffs ${.CURDIR}/../../../../ufs/ufs
@@ -10,12 +10,12 @@ SRCS= ffs_alloc.c ffs_appleufs.c ffs_balloc.c ffs_bswap.c ffs_inode.c \
ffs_snapshot.c ffs_subr.c ffs_tables.c ffs_vfsops.c ffs_vnops.c \
ffs_wapbl.c ffs_quota2.c ffs_extattr.c
-SRCS+= ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \
- ufs_lookup.c ufs_rename.c ufs_vfsops.c ufs_vnops.c \
- ufs_quota.c ufs_quota2.c quota2_subr.c
+SRCS+= ufs_acl.c ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \
+ ufs_lookup.c ufs_rename.c ufs_vfsops.c ufs_vnops.c ufs_quota.c \
+ ufs_quota2.c quota2_subr.c
CPPFLAGS+= -DFFS_EI -DUFS_DIRHASH -DWAPBL -DAPPLE_UFS -DUFS_EXTATTR \
- -DQUOTA2
+ -DQUOTA2 -DUFS_ACL
.include <bsd.lib.mk>
.include <bsd.klinks.mk>
diff --git a/sys/rump/include/rump/rump_syscalls.h b/sys/rump/include/rump/rump_syscalls.h
index f2787c894ec..423d61c818e 100644
--- a/sys/rump/include/rump/rump_syscalls.h
+++ b/sys/rump/include/rump/rump_syscalls.h
@@ -1,4 +1,4 @@
-/* $NetBSD: rump_syscalls.h,v 1.118 2020/04/26 19:16:36 thorpej Exp $ */
+/* $NetBSD: rump_syscalls.h,v 1.119 2020/05/16 18:31:52 christos Exp $ */
/*
* System call protos in rump namespace.
@@ -224,6 +224,10 @@
#define RUMP_SYS_RENAME_EXTATTR_SET_LINK rump___sysimpl_extattr_set_link
#endif
+#ifndef RUMP_SYS_RENAME_LPATHCONF
+#define RUMP_SYS_RENAME_LPATHCONF rump___sysimpl_lpathconf
+#endif
+
#ifndef RUMP_SYS_RENAME_TIMER_CREATE
#define RUMP_SYS_RENAME_TIMER_CREATE rump___sysimpl_timer_create
#endif
@@ -1063,6 +1067,7 @@ int rump_sys_getvfsstat(struct statvfs *, size_t, int) __RENAME(RUMP_SYS_RENAME_
int rump_sys_statvfs1(const char *, struct statvfs *, int) __RENAME(RUMP_SYS_RENAME_STATVFS1);
int rump_sys_fstatvfs1(int, struct statvfs *, int) __RENAME(RUMP_SYS_RENAME_FSTATVFS1);
int rump_sys_fhstatvfs1(const void *, size_t, struct statvfs *, int) __RENAME(RUMP_SYS_RENAME_FHSTATVFS1);
+long rump_sys_lpathconf(const char *, int) __RENAME(RUMP_SYS_RENAME_LPATHCONF);
int rump_sys_pipe(int *);
#endif /* _RUMP_RUMP_SYSCALLS_H_ */
diff --git a/sys/rump/include/rump/rumpvnode_if.h b/sys/rump/include/rump/rumpvnode_if.h
index 45d0dfc3d43..4da38646bf7 100644
--- a/sys/rump/include/rump/rumpvnode_if.h
+++ b/sys/rump/include/rump/rumpvnode_if.h
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpvnode_if.h,v 1.33 2020/02/23 22:15:19 ad Exp $ */
+/* $NetBSD: rumpvnode_if.h,v 1.34 2020/05/16 18:31:52 christos Exp $ */
/*
* Warning: DO NOT EDIT! This file is automatically generated!
@@ -46,6 +46,9 @@ struct buf;
struct flock;
struct knote;
struct vm_page;
+struct acl;
+
+#include <sys/acl.h>
#ifndef _KERNEL
#include <stdbool.h>
@@ -59,7 +62,8 @@ int RUMP_VOP_MKNOD(struct vnode *, struct vnode **, struct componentname *,
struct vattr *);
int RUMP_VOP_OPEN(struct vnode *, int, struct kauth_cred *);
int RUMP_VOP_CLOSE(struct vnode *, int, struct kauth_cred *);
-int RUMP_VOP_ACCESS(struct vnode *, int, struct kauth_cred *);
+int RUMP_VOP_ACCESS(struct vnode *, accmode_t, struct kauth_cred *);
+int RUMP_VOP_ACCESSX(struct vnode *, accmode_t, struct kauth_cred *);
int RUMP_VOP_GETATTR(struct vnode *, struct vattr *, struct kauth_cred *);
int RUMP_VOP_SETATTR(struct vnode *, struct vattr *, struct kauth_cred *);
int RUMP_VOP_READ(struct vnode *, struct uio *, int, struct kauth_cred *);
@@ -101,6 +105,12 @@ int RUMP_VOP_WHITEOUT(struct vnode *, struct componentname *, int);
int RUMP_VOP_GETPAGES(struct vnode *, off_t, struct vm_page **, int *, int,
int, int, int);
int RUMP_VOP_PUTPAGES(struct vnode *, off_t, off_t, int);
+int RUMP_VOP_GETACL(struct vnode *, acl_type_t, struct acl *,
+ struct kauth_cred *);
+int RUMP_VOP_SETACL(struct vnode *, acl_type_t, struct acl *,
+ struct kauth_cred *);
+int RUMP_VOP_ACLCHECK(struct vnode *, acl_type_t, struct acl *,
+ struct kauth_cred *);
int RUMP_VOP_CLOSEEXTATTR(struct vnode *, int, struct kauth_cred *);
int RUMP_VOP_GETEXTATTR(struct vnode *, int, const char *, struct uio *,
size_t *, struct kauth_cred *);
diff --git a/sys/rump/librump/rumpkern/rump_syscalls.c b/sys/rump/librump/rumpkern/rump_syscalls.c
index 462f3fa615c..9679aeca114 100644
--- a/sys/rump/librump/rumpkern/rump_syscalls.c
+++ b/sys/rump/librump/rumpkern/rump_syscalls.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rump_syscalls.c,v 1.149 2020/04/26 19:16:36 thorpej Exp $ */
+/* $NetBSD: rump_syscalls.c,v 1.150 2020/05/16 18:31:52 christos Exp $ */
/*
* System call vector and marshalling for rump.
@@ -15,7 +15,7 @@
#ifdef __NetBSD__
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rump_syscalls.c,v 1.149 2020/04/26 19:16:36 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rump_syscalls.c,v 1.150 2020/05/16 18:31:52 christos Exp $");
#include <sys/fstypes.h>
#include <sys/proc.h>
@@ -6523,6 +6523,35 @@ __weak_alias(___fhstatvfs190,rump___sysimpl_fhstatvfs190);
__strong_alias(_sys___fhstatvfs190,rump___sysimpl_fhstatvfs190);
#endif /* RUMP_KERNEL_IS_LIBC */
+long rump___sysimpl_lpathconf(const char *, int);
+long
+rump___sysimpl_lpathconf(const char * path, int name)
+{
+ register_t retval[2];
+ int error = 0;
+ long rv = -1;
+ struct sys_lpathconf_args callarg;
+
+ memset(&callarg, 0, sizeof(callarg));
+ SPARG(&callarg, path) = path;
+ SPARG(&callarg, name) = name;
+
+ error = rsys_syscall(SYS_lpathconf, &callarg, sizeof(callarg), retval);
+ rsys_seterrno(error);
+ if (error == 0) {
+ if (sizeof(long) > sizeof(register_t))
+ rv = *(long *)retval;
+ else
+ rv = *retval;
+ }
+ return rv;
+}
+#ifdef RUMP_KERNEL_IS_LIBC
+__weak_alias(lpathconf,rump___sysimpl_lpathconf);
+__weak_alias(_lpathconf,rump___sysimpl_lpathconf);
+__strong_alias(_sys_lpathconf,rump___sysimpl_lpathconf);
+#endif /* RUMP_KERNEL_IS_LIBC */
+
int rump_sys_pipe(int *);
int
rump_sys_pipe(int *fd)
@@ -8445,57 +8474,45 @@ struct sysent rump_sysent[] = {
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
}, /* 486 = __fhstatvfs190 */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 487 = filler */
+}, /* 487 = __acl_get_link */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 488 = filler */
+}, /* 488 = __acl_set_link */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 489 = filler */
+}, /* 489 = __acl_delete_link */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 490 = filler */
+}, /* 490 = __acl_aclcheck_link */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 491 = filler */
+}, /* 491 = __acl_get_file */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 492 = filler */
+}, /* 492 = __acl_set_file */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 493 = filler */
+}, /* 493 = __acl_get_fd */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 494 = filler */
+}, /* 494 = __acl_set_fd */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 495 = filler */
+}, /* 495 = __acl_delete_file */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 496 = filler */
+}, /* 496 = __acl_delete_fd */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 497 = filler */
+}, /* 497 = __acl_aclcheck_file */
{
- .sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 498 = filler */
+}, /* 498 = __acl_aclcheck_fd */
{
- .sy_flags = SYCALL_NOSYS,
+ ns(struct sys_lpathconf_args),
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
- }, /* 499 = filler */
+ }, /* 499 = lpathconf */
{
.sy_flags = SYCALL_NOSYS,
.sy_call = (sy_call_t *)(void *)rumpns_enosys,
diff --git a/sys/rump/librump/rumpvfs/Makefile.rumpvfs b/sys/rump/librump/rumpvfs/Makefile.rumpvfs
index 2a873f12ffe..d0705436a3e 100644
--- a/sys/rump/librump/rumpvfs/Makefile.rumpvfs
+++ b/sys/rump/librump/rumpvfs/Makefile.rumpvfs
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.rumpvfs,v 1.49 2016/01/26 23:12:18 pooka Exp $
+# $NetBSD: Makefile.rumpvfs,v 1.50 2020/05/16 18:31:52 christos Exp $
#
.include "${RUMPTOP}/Makefile.rump"
@@ -31,10 +31,10 @@ SRCS+= rumpvfs_syscalls.c
SRCS+= kern_physio.c
# sys/kern vfs
-SRCS+= vfs_bio.c vfs_cache.c vfs_cwd.c vfs_dirhash.c vfs_getcwd.c \
- vfs_hooks.c vfs_init.c vfs_lockf.c vfs_lookup.c vfs_mount.c \
- vfs_subr.c vfs_syscalls.c vfs_trans.c vfs_vnode.c vfs_vnops.c \
- vfs_wapbl.c vfs_xattr.c
+SRCS+= vfs_acl.c vfs_bio.c vfs_cache.c vfs_cwd.c vfs_dirhash.c \
+ vfs_getcwd.c vfs_hooks.c vfs_init.c vfs_lockf.c vfs_lookup.c \
+ vfs_mount.c vfs_subr.c vfs_syscalls.c vfs_trans.c vfs_vnode.c \
+ vfs_vnops.c vfs_wapbl.c vfs_xattr.c
# sys/kern module support
SRCS+= kern_module_vfs.c subr_kobj_vfs.c
@@ -48,6 +48,9 @@ SRCS+= dead_vfsops.c dead_vnops.c
# sys/miscfs
SRCS+= genfs_io.c genfs_rename.c genfs_vfsops.c genfs_vnops.c spec_vnops.c
+# sys/kern acl
+SRCS+= subr_acl_nfs4.c subr_acl_posix1e.c
+
# sys/kern bufq
SRCS+= subr_bufq.c bufq_disksort.c bufq_fcfs.c bufq_priocscan.c \
bufq_readprio.c
diff --git a/sys/rump/librump/rumpvfs/rumpfs.c b/sys/rump/librump/rumpvfs/rumpfs.c
index 753eeb378b7..988edad851f 100644
--- a/sys/rump/librump/rumpvfs/rumpfs.c
+++ b/sys/rump/librump/rumpvfs/rumpfs.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpfs.c,v 1.161 2020/05/15 23:32:28 christos Exp $ */
+/* $NetBSD: rumpfs.c,v 1.162 2020/05/16 18:31:52 christos Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Antti Kantee. All Rights Reserved.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.161 2020/05/15 23:32:28 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.162 2020/05/16 18:31:52 christos Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@@ -101,6 +101,7 @@ const struct vnodeopv_entry_desc rump_vnodeop_entries[] = {
{ &vop_symlink_desc, rump_vop_symlink },
{ &vop_readlink_desc, rump_vop_readlink },
{ &vop_access_desc, rump_vop_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_readdir_desc, rump_vop_readdir },
{ &vop_read_desc, rump_vop_read },
{ &vop_write_desc, rump_vop_write },
@@ -815,13 +816,13 @@ rump_check_possible(struct vnode *vp, struct rumpfs_node *rnode,
static int
rump_check_permitted(struct vnode *vp, struct rumpfs_node *rnode,
- mode_t mode, kauth_cred_t cred)
+ accmode_t accmode, kauth_cred_t cred)
{
struct vattr *attr = &rnode->rn_va;
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
- vp->v_type, attr->va_mode), vp, NULL, genfs_can_access(vp->v_type,
- attr->va_mode, attr->va_uid, attr->va_gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, attr->va_mode), vp, NULL, genfs_can_access(vp, cred,
+ attr->va_uid, attr->va_gid, attr->va_mode, NULL, accmode));
}
int
@@ -837,11 +838,11 @@ rump_vop_access(void *v)
struct rumpfs_node *rn = vp->v_data;
int error;
- error = rump_check_possible(vp, rn, ap->a_mode);
+ error = rump_check_possible(vp, rn, ap->a_accmode);
if (error)
return error;
- error = rump_check_permitted(vp, rn, ap->a_mode, ap->a_cred);
+ error = rump_check_permitted(vp, rn, ap->a_accmode, ap->a_cred);
return error;
}
@@ -890,8 +891,8 @@ rump_vop_setattr(void *v)
CHANGED(va_mtime.tv_nsec, long) ||
CHANGED(va_birthtime.tv_nsec, long)) {
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
- NULL, genfs_can_chtimes(vp, vap->va_vaflags, attr->va_uid,
- cred));
+ NULL, genfs_can_chtimes(vp, cred, attr->va_uid,
+ vap->va_vaflags));
if (error)
return error;
}
@@ -919,8 +920,7 @@ rump_vop_setattr(void *v)
if (CHANGED(va_flags, u_long)) {
/* XXX Can we handle system flags here...? */
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp,
- NULL, genfs_can_chflags(cred, vp->v_type, attr->va_uid,
- false));
+ NULL, genfs_can_chflags(vp, cred, attr->va_uid, false));
if (error)
return error;
}
@@ -936,7 +936,7 @@ rump_vop_setattr(void *v)
(vap->va_gid != (gid_t)VNOVAL) ? vap->va_gid : attr->va_gid;
error = kauth_authorize_vnode(cred,
KAUTH_VNODE_CHANGE_OWNERSHIP, vp, NULL,
- genfs_can_chown(cred, attr->va_uid, attr->va_gid, uid,
+ genfs_can_chown(vp, cred, attr->va_uid, attr->va_gid, uid,
gid));
if (error)
return error;
@@ -947,7 +947,7 @@ rump_vop_setattr(void *v)
if (vap->va_mode != (mode_t)VNOVAL) {
mode_t mode = vap->va_mode;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY,
- vp, NULL, genfs_can_chmod(vp->v_type, cred, attr->va_uid,
+ vp, NULL, genfs_can_chmod(vp, cred, attr->va_uid,
attr->va_gid, mode));
if (error)
return error;
diff --git a/sys/rump/librump/rumpvfs/rumpvnode_if.c b/sys/rump/librump/rumpvfs/rumpvnode_if.c
index 1f47281f2bf..acc6562b780 100644
--- a/sys/rump/librump/rumpvfs/rumpvnode_if.c
+++ b/sys/rump/librump/rumpvfs/rumpvnode_if.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpvnode_if.c,v 1.33 2020/02/23 22:15:19 ad Exp $ */
+/* $NetBSD: rumpvnode_if.c,v 1.34 2020/05/16 18:31:53 christos Exp $ */
/*
* Warning: DO NOT EDIT! This file is automatically generated!
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rumpvnode_if.c,v 1.33 2020/02/23 22:15:19 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rumpvnode_if.c,v 1.34 2020/05/16 18:31:53 christos Exp $");
#include <sys/param.h>
#include <sys/mount.h>
@@ -137,13 +137,27 @@ RUMP_VOP_CLOSE(struct vnode *vp,
int
RUMP_VOP_ACCESS(struct vnode *vp,
- int mode,
+ accmode_t accmode,
+ struct kauth_cred *cred)
+{
+ int error;
+
+ rump_schedule();
+ error = VOP_ACCESS(vp, accmode, cred);
+ rump_unschedule();
+
+ return error;
+}
+
+int
+RUMP_VOP_ACCESSX(struct vnode *vp,
+ accmode_t accmode,
struct kauth_cred *cred)
{
int error;
rump_schedule();
- error = VOP_ACCESS(vp, mode, cred);
+ error = VOP_ACCESSX(vp, accmode, cred);
rump_unschedule();
return error;
@@ -667,6 +681,51 @@ RUMP_VOP_PUTPAGES(struct vnode *vp,
}
int
+RUMP_VOP_GETACL(struct vnode *vp,
+ acl_type_t type,
+ struct acl *aclp,
+ struct kauth_cred *cred)
+{
+ int error;
+
+ rump_schedule();
+ error = VOP_GETACL(vp, type, aclp, cred);
+ rump_unschedule();
+
+ return error;
+}
+
+int
+RUMP_VOP_SETACL(struct vnode *vp,
+ acl_type_t type,
+ struct acl *aclp,
+ struct kauth_cred *cred)
+{
+ int error;
+
+ rump_schedule();
+ error = VOP_SETACL(vp, type, aclp, cred);
+ rump_unschedule();
+
+ return error;
+}
+
+int
+RUMP_VOP_ACLCHECK(struct vnode *vp,
+ acl_type_t type,
+ struct acl *aclp,
+ struct kauth_cred *cred)
+{
+ int error;
+
+ rump_schedule();
+ error = VOP_ACLCHECK(vp, type, aclp, cred);
+ rump_unschedule();
+
+ return error;
+}
+
+int
RUMP_VOP_CLOSEEXTATTR(struct vnode *vp,
int commit,
struct kauth_cred *cred)
diff --git a/sys/rump/rump.sysmap b/sys/rump/rump.sysmap
index e85583d0ab9..cab36af41af 100644
--- a/sys/rump/rump.sysmap
+++ b/sys/rump/rump.sysmap
@@ -217,3 +217,4 @@
484 sys___statvfs190 __statvfs190 rump___sysimpl_statvfs190
485 sys___fstatvfs190 __fstatvfs190 rump___sysimpl_fstatvfs190
486 sys___fhstatvfs190 __fhstatvfs190 rump___sysimpl_fhstatvfs190
+499 sys_lpathconf lpathconf rump___sysimpl_lpathconf
diff --git a/sys/sys/Makefile b/sys/sys/Makefile
index af9e5bf3a94..993e1deb619 100644
--- a/sys/sys/Makefile
+++ b/sys/sys/Makefile
@@ -1,10 +1,10 @@
-# $NetBSD: Makefile,v 1.173 2020/04/26 18:53:33 thorpej Exp $
+# $NetBSD: Makefile,v 1.174 2020/05/16 18:31:53 christos Exp $
.include <bsd.own.mk>
INCSDIR= /usr/include/sys
-INCS= acct.h agpio.h aio.h ansi.h aout_mids.h ataio.h atomic.h \
+INCS= acct.h acl.h agpio.h aio.h ansi.h aout_mids.h ataio.h atomic.h \
audioio.h \
bitops.h bootblock.h bswap.h buf.h \
callback.h callout.h cdbr.h cdefs.h cdefs_aout.h \
diff --git a/sys/sys/acl.h b/sys/sys/acl.h
new file mode 100644
index 00000000000..9ff39653cd4
--- /dev/null
+++ b/sys/sys/acl.h
@@ -0,0 +1,440 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999-2001 Robert N. M. Watson
+ * Copyright (c) 2008 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/sys/sys/acl.h 326256 2017-11-27 15:01:59Z pfg $
+ */
+/*
+ * Developed by the TrustedBSD Project.
+ * Support for POSIX.1e and NFSv4 access control lists.
+ */
+
+#ifndef _SYS_ACL_H_
+#define _SYS_ACL_H_
+
+#include <sys/param.h>
+#include <sys/queue.h>
+
+/*
+ * POSIX.1e and NFSv4 ACL types and related constants.
+ */
+
+typedef uint32_t acl_tag_t;
+typedef uint32_t acl_perm_t;
+typedef uint16_t acl_entry_type_t;
+typedef uint16_t acl_flag_t;
+typedef int acl_type_t;
+typedef uint32_t *acl_permset_t;
+typedef uint16_t *acl_flagset_t;
+
+/*
+ * With 254 entries, "struct acl_t_struct" is exactly one 4kB page big.
+ * Note that with NFSv4 ACLs, the maximum number of ACL entries one
+ * may set on file or directory is about half of ACL_MAX_ENTRIES.
+ *
+ * If you increase this, you might also need to increase
+ * _ACL_T_ALIGNMENT_BITS in lib/libc/posix1e/acl_support.h.
+ *
+ * The maximum number of POSIX.1e ACLs is controlled
+ * by OLDACL_MAX_ENTRIES. Changing that one will break binary
+ * compatibility with pre-8.0 userland and change on-disk ACL layout.
+ */
+#define ACL_MAX_ENTRIES 254
+
+#if defined(_KERNEL) || defined(_ACL_PRIVATE) || defined(_MODULE)
+
+#define POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE EXTATTR_NAMESPACE_SYSTEM
+#define POSIX1E_ACL_ACCESS_EXTATTR_NAME "posix1e.acl_access"
+#define POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE EXTATTR_NAMESPACE_SYSTEM
+#define POSIX1E_ACL_DEFAULT_EXTATTR_NAME "posix1e.acl_default"
+#define NFS4_ACL_EXTATTR_NAMESPACE EXTATTR_NAMESPACE_SYSTEM
+#define NFS4_ACL_EXTATTR_NAME "nfs4.acl"
+#define OLDACL_MAX_ENTRIES 32
+
+/*
+ * "struct oldacl" is used in compatibility ACL syscalls and for on-disk
+ * storage of POSIX.1e ACLs.
+ */
+typedef int oldacl_tag_t;
+typedef mode_t oldacl_perm_t;
+
+struct oldacl_entry {
+ oldacl_tag_t ae_tag;
+ uid_t ae_id;
+ oldacl_perm_t ae_perm;
+};
+typedef struct oldacl_entry *oldacl_entry_t;
+
+struct oldacl {
+ int acl_cnt;
+ struct oldacl_entry acl_entry[OLDACL_MAX_ENTRIES];
+};
+
+/*
+ * Current "struct acl".
+ */
+struct acl_entry {
+ acl_tag_t ae_tag;
+ uid_t ae_id;
+ acl_perm_t ae_perm;
+ /* NFSv4 entry type, "allow" or "deny". Unused in POSIX.1e ACLs. */
+ acl_entry_type_t ae_entry_type;
+ /* NFSv4 ACL inheritance. Unused in POSIX.1e ACLs. */
+ acl_flag_t ae_flags;
+};
+typedef struct acl_entry *acl_entry_t;
+
+/*
+ * Internal ACL structure, used in libc, kernel APIs and for on-disk
+ * storage of NFSv4 ACLs. POSIX.1e ACLs use "struct oldacl" for on-disk
+ * storage.
+ */
+struct acl {
+ unsigned int acl_maxcnt;
+ unsigned int acl_cnt;
+ /* Will be required e.g. to implement NFSv4.1 ACL inheritance. */
+ int acl_spare[4];
+ struct acl_entry acl_entry[ACL_MAX_ENTRIES];
+};
+
+/*
+ * ACL structure internal to libc.
+ */
+struct acl_t_struct {
+ struct acl ats_acl;
+ unsigned int ats_cur_entry;
+ /*
+ * ats_brand is for libc internal bookkeeping only.
+ * Applications should use acl_get_brand_np(3).
+ * Kernel code should use the "type" argument passed
+ * to VOP_SETACL, VOP_GETACL or VOP_ACLCHECK calls;
+ * ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT mean POSIX.1e
+ * ACL, ACL_TYPE_NFS4 means NFSv4 ACL.
+ */
+ int ats_brand;
+};
+typedef struct acl_t_struct *acl_t;
+
+#else /* _KERNEL || _ACL_PRIVATE */
+
+typedef void *acl_entry_t;
+typedef void *acl_t;
+
+#endif /* !_KERNEL && !_ACL_PRIVATE */
+
+/*
+ * Possible valid values for ats_brand field.
+ */
+#define ACL_BRAND_UNKNOWN 0
+#define ACL_BRAND_POSIX 1
+#define ACL_BRAND_NFS4 2
+
+/*
+ * Possible valid values for ae_tag field. For explanation, see acl(9).
+ */
+#define ACL_UNDEFINED_TAG 0x00000000
+#define ACL_USER_OBJ 0x00000001
+#define ACL_USER 0x00000002
+#define ACL_GROUP_OBJ 0x00000004
+#define ACL_GROUP 0x00000008
+#define ACL_MASK 0x00000010
+#define ACL_OTHER 0x00000020
+#define ACL_OTHER_OBJ ACL_OTHER
+#define ACL_EVERYONE 0x00000040
+
+/*
+ * Possible valid values for ae_entry_type field, valid only for NFSv4 ACLs.
+ */
+#define ACL_ENTRY_TYPE_ALLOW 0x0100
+#define ACL_ENTRY_TYPE_DENY 0x0200
+#define ACL_ENTRY_TYPE_AUDIT 0x0400
+#define ACL_ENTRY_TYPE_ALARM 0x0800
+
+/*
+ * Possible valid values for acl_type_t arguments. First two
+ * are provided only for backwards binary compatibility.
+ */
+#define ACL_TYPE_ACCESS_OLD 0x00000000
+#define ACL_TYPE_DEFAULT_OLD 0x00000001
+#define ACL_TYPE_ACCESS 0x00000002
+#define ACL_TYPE_DEFAULT 0x00000003
+#define ACL_TYPE_NFS4 0x00000004
+
+/*
+ * Possible bits in ae_perm field for POSIX.1e ACLs. Note
+ * that ACL_EXECUTE may be used in both NFSv4 and POSIX.1e ACLs.
+ */
+#define ACL_EXECUTE 0x0001
+#define ACL_WRITE 0x0002
+#define ACL_READ 0x0004
+#define ACL_PERM_NONE 0x0000
+#define ACL_PERM_BITS (ACL_EXECUTE | ACL_WRITE | ACL_READ)
+#define ACL_POSIX1E_BITS (ACL_EXECUTE | ACL_WRITE | ACL_READ)
+
+/*
+ * Possible bits in ae_perm field for NFSv4 ACLs.
+ */
+#define ACL_READ_DATA 0x00000008
+#define ACL_LIST_DIRECTORY 0x00000008
+#define ACL_WRITE_DATA 0x00000010
+#define ACL_ADD_FILE 0x00000010
+#define ACL_APPEND_DATA 0x00000020
+#define ACL_ADD_SUBDIRECTORY 0x00000020
+#define ACL_READ_NAMED_ATTRS 0x00000040
+#define ACL_WRITE_NAMED_ATTRS 0x00000080
+/* ACL_EXECUTE is defined above. */
+#define ACL_DELETE_CHILD 0x00000100
+#define ACL_READ_ATTRIBUTES 0x00000200
+#define ACL_WRITE_ATTRIBUTES 0x00000400
+#define ACL_DELETE 0x00000800
+#define ACL_READ_ACL 0x00001000
+#define ACL_WRITE_ACL 0x00002000
+#define ACL_WRITE_OWNER 0x00004000
+#define ACL_SYNCHRONIZE 0x00008000
+
+#define ACL_FULL_SET (ACL_READ_DATA | ACL_WRITE_DATA | \
+ ACL_APPEND_DATA | ACL_READ_NAMED_ATTRS | ACL_WRITE_NAMED_ATTRS | \
+ ACL_EXECUTE | ACL_DELETE_CHILD | ACL_READ_ATTRIBUTES | \
+ ACL_WRITE_ATTRIBUTES | ACL_DELETE | ACL_READ_ACL | ACL_WRITE_ACL | \
+ ACL_WRITE_OWNER | ACL_SYNCHRONIZE)
+
+#define ACL_MODIFY_SET (ACL_FULL_SET & \
+ ~(ACL_WRITE_ACL | ACL_WRITE_OWNER))
+
+#define ACL_READ_SET (ACL_READ_DATA | ACL_READ_NAMED_ATTRS | \
+ ACL_READ_ATTRIBUTES | ACL_READ_ACL)
+
+#define ACL_WRITE_SET (ACL_WRITE_DATA | ACL_APPEND_DATA | \
+ ACL_WRITE_NAMED_ATTRS | ACL_WRITE_ATTRIBUTES)
+
+#define ACL_NFS4_PERM_BITS ACL_FULL_SET
+
+/*
+ * Possible entry_id values for acl_get_entry(3).
+ */
+#define ACL_FIRST_ENTRY 0
+#define ACL_NEXT_ENTRY 1
+
+/*
+ * Possible values in ae_flags field; valid only for NFSv4 ACLs.
+ */
+#define ACL_ENTRY_FILE_INHERIT 0x0001
+#define ACL_ENTRY_DIRECTORY_INHERIT 0x0002
+#define ACL_ENTRY_NO_PROPAGATE_INHERIT 0x0004
+#define ACL_ENTRY_INHERIT_ONLY 0x0008
+#define ACL_ENTRY_SUCCESSFUL_ACCESS 0x0010
+#define ACL_ENTRY_FAILED_ACCESS 0x0020
+#define ACL_ENTRY_INHERITED 0x0080
+
+#define ACL_FLAGS_BITS (ACL_ENTRY_FILE_INHERIT | \
+ ACL_ENTRY_DIRECTORY_INHERIT | ACL_ENTRY_NO_PROPAGATE_INHERIT | \
+ ACL_ENTRY_INHERIT_ONLY | ACL_ENTRY_SUCCESSFUL_ACCESS | \
+ ACL_ENTRY_FAILED_ACCESS | ACL_ENTRY_INHERITED)
+
+/*
+ * Undefined value in ae_id field. ae_id should be set to this value
+ * iff ae_tag is ACL_USER_OBJ, ACL_GROUP_OBJ, ACL_OTHER or ACL_EVERYONE.
+ */
+#define ACL_UNDEFINED_ID ((uid_t)-1)
+
+/*
+ * Possible values for _flags parameter in acl_to_text_np(3).
+ */
+#define ACL_TEXT_VERBOSE 0x01
+#define ACL_TEXT_NUMERIC_IDS 0x02
+#define ACL_TEXT_APPEND_ID 0x04
+
+/*
+ * POSIX.1e ACLs are capable of expressing the read, write, and execute bits
+ * of the POSIX mode field. We provide two masks: one that defines the bits
+ * the ACL will replace in the mode, and the other that defines the bits that
+ * must be preseved when an ACL is updating a mode.
+ */
+#define ACL_OVERRIDE_MASK (S_IRWXU | S_IRWXG | S_IRWXO)
+#define ACL_PRESERVE_MASK (~ACL_OVERRIDE_MASK)
+
+#ifdef _KERNEL
+
+/*
+ * Filesystem-independent code to move back and forth between POSIX mode and
+ * POSIX.1e ACL representations.
+ */
+acl_perm_t acl_posix1e_mode_to_perm(acl_tag_t tag, mode_t mode);
+struct acl_entry acl_posix1e_mode_to_entry(acl_tag_t tag, uid_t uid,
+ gid_t gid, mode_t mode);
+mode_t acl_posix1e_perms_to_mode(
+ struct acl_entry *acl_user_obj_entry,
+ struct acl_entry *acl_group_obj_entry,
+ struct acl_entry *acl_other_entry);
+mode_t acl_posix1e_acl_to_mode(struct acl *acl);
+mode_t acl_posix1e_newfilemode(mode_t cmode,
+ struct acl *dacl);
+struct acl *acl_alloc(int flags);
+void acl_free(struct acl *aclp);
+
+void acl_nfs4_sync_acl_from_mode(struct acl *aclp,
+ mode_t mode, int file_owner_id);
+void __acl_nfs4_sync_mode_from_acl(mode_t *mode,
+ const struct acl *aclp);
+int acl_nfs4_is_trivial(const struct acl *aclp,
+ int file_owner_id);
+void acl_nfs4_compute_inherited_acl(
+ const struct acl *parent_aclp,
+ struct acl *child_aclp, mode_t mode,
+ int file_owner_id, int is_directory);
+int acl_copy_oldacl_into_acl(const struct oldacl *source,
+ struct acl *dest);
+int acl_copy_acl_into_oldacl(const struct acl *source,
+ struct oldacl *dest);
+
+/*
+ * Filesystem-independent syntax check for a POSIX.1e ACL.
+ */
+int acl_posix1e_check(struct acl *acl);
+int acl_nfs4_check(const struct acl *aclp, int is_directory);
+
+/* for compat32 */
+#include <sys/namei.h>
+
+int kern___acl_aclcheck_path(struct lwp *, const char *, acl_type_t,
+ struct acl *, namei_simple_flags_t);
+int kern___acl_delete_path(struct lwp *, const char *, acl_type_t,
+ namei_simple_flags_t);
+int kern___acl_get_path(struct lwp *, const char *, acl_type_t,
+ struct acl *, namei_simple_flags_t);
+int kern___acl_set_path(struct lwp *, const char *, acl_type_t,
+ const struct acl *, namei_simple_flags_t);
+int vacl_set_acl(struct lwp *, struct vnode *, acl_type_t,
+ const struct acl *);
+int vacl_get_acl(struct lwp *, struct vnode *, acl_type_t, struct acl *);
+int vacl_aclcheck(struct lwp *, struct vnode *, acl_type_t,
+ const struct acl *);
+int vacl_delete(struct lwp *, struct vnode *, acl_type_t);
+
+#else /* !_KERNEL */
+
+#if defined(_ACL_PRIVATE)
+
+/*
+ * Syscall interface -- use the library calls instead as the syscalls have
+ * strict ACL entry ordering requirements.
+ */
+__BEGIN_DECLS
+int __acl_aclcheck_fd(int _filedes, acl_type_t _type, struct acl *_aclp);
+int __acl_aclcheck_file(const char *_path, acl_type_t _type,
+ struct acl *_aclp);
+int __acl_aclcheck_link(const char *_path, acl_type_t _type,
+ struct acl *_aclp);
+int __acl_delete_fd(int _filedes, acl_type_t _type);
+int __acl_delete_file(const char *_path_p, acl_type_t _type);
+int __acl_delete_link(const char *_path_p, acl_type_t _type);
+int __acl_get_fd(int _filedes, acl_type_t _type, struct acl *_aclp);
+int __acl_get_file(const char *_path, acl_type_t _type, struct acl *_aclp);
+int __acl_get_link(const char *_path, acl_type_t _type, struct acl *_aclp);
+int __acl_set_fd(int _filedes, acl_type_t _type, struct acl *_aclp);
+int __acl_set_file(const char *_path, acl_type_t _type, struct acl *_aclp);
+int __acl_set_link(const char *_path, acl_type_t _type, struct acl *_aclp);
+
+/*
+ * These routines from sys/kern/subr_acl_nfs4.c are used by both kernel
+ * and libc.
+ */
+void __acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *_aclp);
+void __acl_nfs4_trivial_from_mode_libc(struct acl *_aclp, int _file_owner_id,
+ int _canonical_six);
+__END_DECLS
+
+#endif /* _ACL_PRIVATE */
+
+/*
+ * Supported POSIX.1e ACL manipulation and assignment/retrieval API _np calls
+ * are local extensions that reflect an environment capable of opening file
+ * descriptors of directories, and allowing additional ACL type for different
+ * filesystems (i.e., AFS).
+ */
+__BEGIN_DECLS
+int acl_add_flag_np(acl_flagset_t _flagset_d, acl_flag_t _flag);
+int acl_add_perm(acl_permset_t _permset_d, acl_perm_t _perm);
+int acl_calc_mask(acl_t *_acl_p);
+int acl_clear_flags_np(acl_flagset_t _flagset_d);
+int acl_clear_perms(acl_permset_t _permset_d);
+int acl_copy_entry(acl_entry_t _dest_d, acl_entry_t _src_d);
+ssize_t acl_copy_ext(void *_buf_p, acl_t _acl, ssize_t _size);
+acl_t acl_copy_int(const void *_buf_p);
+int acl_create_entry(acl_t *_acl_p, acl_entry_t *_entry_p);
+int acl_create_entry_np(acl_t *_acl_p, acl_entry_t *_entry_p, int _index);
+int acl_delete_entry(acl_t _acl, acl_entry_t _entry_d);
+int acl_delete_entry_np(acl_t _acl, int _index);
+int acl_delete_fd_np(int _filedes, acl_type_t _type);
+int acl_delete_file_np(const char *_path_p, acl_type_t _type);
+int acl_delete_link_np(const char *_path_p, acl_type_t _type);
+int acl_delete_def_file(const char *_path_p);
+int acl_delete_def_link_np(const char *_path_p);
+int acl_delete_flag_np(acl_flagset_t _flagset_d, acl_flag_t _flag);
+int acl_delete_perm(acl_permset_t _permset_d, acl_perm_t _perm);
+acl_t acl_dup(acl_t _acl);
+int acl_free(void *_obj_p);
+acl_t acl_from_text(const char *_buf_p);
+int acl_get_brand_np(acl_t _acl, int *_brand_p);
+int acl_get_entry(acl_t _acl, int _entry_id, acl_entry_t *_entry_p);
+acl_t acl_get_fd(int _fd);
+acl_t acl_get_fd_np(int fd, acl_type_t _type);
+acl_t acl_get_file(const char *_path_p, acl_type_t _type);
+int acl_get_entry_type_np(acl_entry_t _entry_d, acl_entry_type_t *_entry_type_p);
+acl_t acl_get_link_np(const char *_path_p, acl_type_t _type);
+void *acl_get_qualifier(acl_entry_t _entry_d);
+int acl_get_flag_np(acl_flagset_t _flagset_d, acl_flag_t _flag);
+int acl_get_perm_np(acl_permset_t _permset_d, acl_perm_t _perm);
+int acl_get_flagset_np(acl_entry_t _entry_d, acl_flagset_t *_flagset_p);
+int acl_get_permset(acl_entry_t _entry_d, acl_permset_t *_permset_p);
+int acl_get_tag_type(acl_entry_t _entry_d, acl_tag_t *_tag_type_p);
+acl_t acl_init(int _count);
+int acl_set_fd(int _fd, acl_t _acl);
+int acl_set_fd_np(int _fd, acl_t _acl, acl_type_t _type);
+int acl_set_file(const char *_path_p, acl_type_t _type, acl_t _acl);
+int acl_set_entry_type_np(acl_entry_t _entry_d, acl_entry_type_t _entry_type);
+int acl_set_link_np(const char *_path_p, acl_type_t _type, acl_t _acl);
+int acl_set_flagset_np(acl_entry_t _entry_d, acl_flagset_t _flagset_d);
+int acl_set_permset(acl_entry_t _entry_d, acl_permset_t _permset_d);
+int acl_set_qualifier(acl_entry_t _entry_d, const void *_tag_qualifier_p);
+int acl_set_tag_type(acl_entry_t _entry_d, acl_tag_t _tag_type);
+ssize_t acl_size(acl_t _acl);
+char *acl_to_text(acl_t _acl, ssize_t *_len_p);
+char *acl_to_text_np(acl_t _acl, ssize_t *_len_p, int _flags);
+int acl_valid(acl_t _acl);
+int acl_valid_fd_np(int _fd, acl_type_t _type, acl_t _acl);
+int acl_valid_file_np(const char *_path_p, acl_type_t _type, acl_t _acl);
+int acl_valid_link_np(const char *_path_p, acl_type_t _type, acl_t _acl);
+int acl_is_trivial_np(const acl_t _acl, int *_trivialp);
+acl_t acl_strip_np(const acl_t _acl, int recalculate_mask);
+__END_DECLS
+
+#endif /* !_KERNEL */
+
+#endif /* !_SYS_ACL_H_ */
diff --git a/sys/sys/ansi.h b/sys/sys/ansi.h
index d480cfb6008..b457437e7f1 100644
--- a/sys/sys/ansi.h
+++ b/sys/sys/ansi.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ansi.h,v 1.14 2011/07/17 20:54:54 joerg Exp $ */
+/* $NetBSD: ansi.h,v 1.15 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc.
@@ -39,6 +39,7 @@ typedef __uint32_t __gid_t; /* group id */
typedef __uint32_t __in_addr_t; /* IP(v4) address */
typedef __uint16_t __in_port_t; /* "Internet" port number */
typedef __uint32_t __mode_t; /* file permissions */
+typedef __uint32_t __accmode_t; /* access permissions */
typedef __int64_t __off_t; /* file offset */
typedef __int32_t __pid_t; /* process id */
typedef __uint8_t __sa_family_t; /* socket address family */
diff --git a/sys/sys/extattr.h b/sys/sys/extattr.h
index 301a33c6098..18b3d387d6b 100644
--- a/sys/sys/extattr.h
+++ b/sys/sys/extattr.h
@@ -1,4 +1,4 @@
-/* $NetBSD: extattr.h,v 1.9 2012/03/13 18:41:02 elad Exp $ */
+/* $NetBSD: extattr.h,v 1.10 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 1999-2001 Robert N. M. Watson
@@ -60,7 +60,7 @@
#define EXTATTR_MAXNAMELEN KERNEL_NAME_MAX
struct lwp;
struct vnode;
-int extattr_check_cred(struct vnode *, const char *, kauth_cred_t, int);
+int extattr_check_cred(struct vnode *, int, kauth_cred_t, int);
#else
diff --git a/sys/sys/fstypes.h b/sys/sys/fstypes.h
index 1700dcd356d..178626cefad 100644
--- a/sys/sys/fstypes.h
+++ b/sys/sys/fstypes.h
@@ -1,4 +1,4 @@
-/* $NetBSD: fstypes.h,v 1.38 2020/04/04 20:49:31 ad Exp $ */
+/* $NetBSD: fstypes.h,v 1.39 2020/05/16 18:31:53 christos Exp $ */
/*
* Copyright (c) 1989, 1991, 1993
@@ -83,7 +83,6 @@ typedef struct fhandle fhandle_t;
* one of the __MNT_UNUSED flags.
*/
-#define __MNT_UNUSED1 0x00200000
#define MNT_RDONLY 0x00000001 /* read only filesystem */
#define MNT_SYNCHRONOUS 0x00000002 /* file system written synchronously */
@@ -95,6 +94,7 @@ typedef struct fhandle fhandle_t;
#define MNT_NOCOREDUMP 0x00008000 /* don't write core dumps to this FS */
#define MNT_RELATIME 0x00020000 /* only update access time if mod/ch */
#define MNT_IGNORE 0x00100000 /* don't show entry in df */
+#define MNT_ACLS 0x00200000 /* uses Access Control Lists */
#define MNT_DISCARD 0x00800000 /* use DISCARD/TRIM if supported */
#define MNT_EXTATTR 0x01000000 /* enable extended attributes */
#define MNT_LOG 0x02000000 /* Use logging */
@@ -103,10 +103,13 @@ typedef struct fhandle fhandle_t;
#define MNT_SYMPERM 0x20000000 /* recognize symlink permission */
#define MNT_NODEVMTIME 0x40000000 /* Never update mod times for devs */
#define MNT_SOFTDEP 0x80000000 /* Use soft dependencies */
+#define MNT_POSIX1EACLS 0x00000800 /* shared with EXKERB */
#define __MNT_BASIC_FLAGS \
{ MNT_ASYNC, 0, "asynchronous" }, \
{ MNT_AUTOMOUNTED, 0, "automounted" }, \
+ { MNT_ACLS, 0, "acls" }, \
+ { MNT_POSIX1EACLS, 0, "posix1eacls" }, \
{ MNT_DISCARD, 0, "discard" }, \
{ MNT_EXTATTR, 0, "extattr" }, \
{ MNT_IGNORE, 0, "hidden" }, \
@@ -127,7 +130,8 @@ typedef struct fhandle fhandle_t;
#define MNT_BASIC_FLAGS (MNT_ASYNC | MNT_AUTOMOUNTED | MNT_DISCARD | \
MNT_EXTATTR | MNT_LOG | MNT_NOATIME | MNT_NOCOREDUMP | MNT_NODEV | \
MNT_NODEVMTIME | MNT_NOEXEC | MNT_NOSUID | MNT_RDONLY | MNT_RELATIME | \
- MNT_SOFTDEP | MNT_SYMPERM | MNT_SYNCHRONOUS | MNT_UNION)
+ MNT_SOFTDEP | MNT_SYMPERM | MNT_SYNCHRONOUS | MNT_UNION | MNT_ACLS | \
+ MNT_POSIX1EACLS)
/*
* exported mount flags.
*/
@@ -170,6 +174,7 @@ typedef struct fhandle fhandle_t;
MNT_NOSUID | \
MNT_NODEV | \
MNT_UNION | \
+ MNT_ACLS | \
MNT_ASYNC | \
MNT_NOCOREDUMP | \
MNT_IGNORE | \
@@ -189,6 +194,7 @@ typedef struct fhandle fhandle_t;
MNT_QUOTA | \
MNT_ROOTFS | \
MNT_LOG | \
+ MNT_POSIX1EACLS | \
MNT_EXTATTR | \
MNT_AUTOMOUNTED)
@@ -245,7 +251,7 @@ typedef struct fhandle fhandle_t;
"\31MNT_EXTATTR" \
"\30MNT_DISCARD" \
"\27MNT_GETARGS" \
- "\26MNT_UNUSED" \
+ "\26MNT_ACL" \
"\25MNT_IGNORE" \
"\24MNT_FORCE" \
"\23MNT_RELOAD" \
@@ -255,7 +261,7 @@ typedef struct fhandle fhandle_t;
"\17MNT_ROOTFS" \
"\16MNT_QUOTA" \
"\15MNT_LOCAL" \
- "\14MNT_EXKERB" \
+ "\14MNT_EXKERB|MNT_POSIX1EACLS" \
"\13MNT_EXPORTANON" \
"\12MNT_DEFEXPORTED" \
"\11MNT_EXPORTED" \
diff --git a/sys/sys/kauth.h b/sys/sys/kauth.h
index 53cd6ed4298..aa4fea581b2 100644
--- a/sys/sys/kauth.h
+++ b/sys/sys/kauth.h
@@ -1,4 +1,4 @@
-/* $NetBSD: kauth.h,v 1.84 2020/04/29 05:54:37 riastradh Exp $ */
+/* $NetBSD: kauth.h,v 1.85 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org>
@@ -525,11 +525,11 @@ int kauth_cred_uucmp(kauth_cred_t, const struct uucred *);
void kauth_cred_toucred(kauth_cred_t, struct ki_ucred *);
void kauth_cred_topcred(kauth_cred_t, struct ki_pcred *);
-kauth_action_t kauth_mode_to_action(mode_t);
+kauth_action_t kauth_accmode_to_action(accmode_t);
kauth_action_t kauth_extattr_action(mode_t);
#define KAUTH_ACCESS_ACTION(access_mode, vn_vtype, file_mode) \
- (kauth_mode_to_action(access_mode) | \
+ (kauth_accmode_to_action(access_mode) | \
(FS_OBJECT_CAN_EXEC(vn_vtype, file_mode) ? KAUTH_VNODE_IS_EXEC : 0))
kauth_cred_t kauth_cred_get(void);
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
index 6dd5d65951e..81a2c6934b0 100644
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -1,4 +1,4 @@
-/* $NetBSD: namei.h,v 1.109 2020/05/12 23:18:03 ad Exp $ */
+/* $NetBSD: namei.h,v 1.110 2020/05/16 18:31:53 christos Exp $ */
/*
@@ -45,7 +45,7 @@
#include <sys/queue.h>
#include <sys/mutex.h>
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_MODULE)
#include <sys/kauth.h>
#include <sys/rwlock.h>
@@ -171,11 +171,12 @@ struct nameidata {
#define ISDOTDOT 0x0002000 /* current component name is .. */
#define MAKEENTRY 0x0004000 /* entry is to be added to name cache */
#define ISLASTCN 0x0008000 /* this is last component of pathname */
+#define WILLBEDIR 0x0010000 /* new files will be dirs; */
#define ISWHITEOUT 0x0020000 /* found whiteout */
#define DOWHITEOUT 0x0040000 /* do whiteouts */
#define REQUIREDIR 0x0080000 /* must be a directory */
#define CREATEDIR 0x0200000 /* trailing slashes are ok */
-#define PARAMASK 0x02ef800 /* mask of parameter descriptors */
+#define PARAMASK 0x02ff800 /* mask of parameter descriptors */
/*
* Initialization of a nameidata structure.
@@ -298,7 +299,7 @@ bool cache_lookup_raw(struct vnode *, const char *, size_t, uint32_t,
bool cache_lookup_linked(struct vnode *, const char *, size_t,
struct vnode **, krwlock_t **, kauth_cred_t);
int cache_revlookup(struct vnode *, struct vnode **, char **, char *,
- bool, int);
+ bool, accmode_t);
int cache_diraccess(struct vnode *, int);
void cache_enter(struct vnode *, struct vnode *,
const char *, size_t, uint32_t);
diff --git a/sys/sys/namei.src b/sys/sys/namei.src
index 82bec1ac3e4..5738df35499 100644
--- a/sys/sys/namei.src
+++ b/sys/sys/namei.src
@@ -1,4 +1,4 @@
-/* $NetBSD: namei.src,v 1.54 2020/05/12 23:17:41 ad Exp $ */
+/* $NetBSD: namei.src,v 1.55 2020/05/16 18:31:53 christos Exp $ */
/*
* Copyright (c) 1985, 1989, 1991, 1993
@@ -37,7 +37,7 @@
#include <sys/queue.h>
#include <sys/mutex.h>
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_MODULE)
#include <sys/kauth.h>
#include <sys/rwlock.h>
diff --git a/sys/sys/statvfs.h b/sys/sys/statvfs.h
index f73e4fa2f14..61efee292a5 100644
--- a/sys/sys/statvfs.h
+++ b/sys/sys/statvfs.h
@@ -1,4 +1,4 @@
-/* $NetBSD: statvfs.h,v 1.19 2019/09/22 22:59:40 christos Exp $ */
+/* $NetBSD: statvfs.h,v 1.20 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -113,6 +113,7 @@ struct statvfs {
#define ST_NODEV MNT_NODEV
#define ST_UNION MNT_UNION
#define ST_ASYNC MNT_ASYNC
+#define ST_ACLS MNT_ACLS
#define ST_NOCOREDUMP MNT_NOCOREDUMP
#define ST_RELATIME MNT_RELATIME
#define ST_IGNORE MNT_IGNORE
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
index 4fb8048d89e..7a2295a94a2 100644
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -1,4 +1,4 @@
-/* $NetBSD: syscall.h,v 1.313 2020/04/26 19:16:35 thorpej Exp $ */
+/* $NetBSD: syscall.h,v 1.314 2020/05/16 18:31:53 christos Exp $ */
/*
* System call numbers.
@@ -1350,6 +1350,45 @@
/* syscall: "__fhstatvfs190" ret: "int" args: "const void *" "size_t" "struct statvfs *" "int" */
#define SYS___fhstatvfs190 486
-#define SYS_MAXSYSCALL 487
+/* syscall: "__acl_get_link" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */
+#define SYS___acl_get_link 487
+
+/* syscall: "__acl_set_link" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */
+#define SYS___acl_set_link 488
+
+/* syscall: "__acl_delete_link" ret: "int" args: "const char *" "acl_type_t" */
+#define SYS___acl_delete_link 489
+
+/* syscall: "__acl_aclcheck_link" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */
+#define SYS___acl_aclcheck_link 490
+
+/* syscall: "__acl_get_file" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */
+#define SYS___acl_get_file 491
+
+/* syscall: "__acl_set_file" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */
+#define SYS___acl_set_file 492
+
+/* syscall: "__acl_get_fd" ret: "int" args: "int" "acl_type_t" "struct acl *" */
+#define SYS___acl_get_fd 493
+
+/* syscall: "__acl_set_fd" ret: "int" args: "int" "acl_type_t" "struct acl *" */
+#define SYS___acl_set_fd 494
+
+/* syscall: "__acl_delete_file" ret: "int" args: "const char *" "acl_type_t" */
+#define SYS___acl_delete_file 495
+
+/* syscall: "__acl_delete_fd" ret: "int" args: "int" "acl_type_t" */
+#define SYS___acl_delete_fd 496
+
+/* syscall: "__acl_aclcheck_file" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */
+#define SYS___acl_aclcheck_file 497
+
+/* syscall: "__acl_aclcheck_fd" ret: "int" args: "int" "acl_type_t" "struct acl *" */
+#define SYS___acl_aclcheck_fd 498
+
+/* syscall: "lpathconf" ret: "long" args: "const char *" "int" */
+#define SYS_lpathconf 499
+
+#define SYS_MAXSYSCALL 500
#define SYS_NSYSENT 512
#endif /* _SYS_SYSCALL_H_ */
diff --git a/sys/sys/syscallargs.h b/sys/sys/syscallargs.h
index c926680ad34..999b47f8804 100644
--- a/sys/sys/syscallargs.h
+++ b/sys/sys/syscallargs.h
@@ -1,4 +1,4 @@
-/* $NetBSD: syscallargs.h,v 1.297 2020/04/26 19:16:35 thorpej Exp $ */
+/* $NetBSD: syscallargs.h,v 1.298 2020/05/16 18:31:53 christos Exp $ */
/*
* System call argument lists.
@@ -14,6 +14,7 @@
#include <sys/idtype.h>
#include <sys/mount.h>
#include <sys/sched.h>
+#include <sys/acl.h>
#endif
#include <sys/socket.h>
@@ -3205,6 +3206,117 @@ struct sys___fhstatvfs190_args {
};
check_syscall_args(sys___fhstatvfs190)
+#ifndef RUMP_CLIENT
+struct sys___acl_get_link_args {
+ syscallarg(const char *) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(struct acl *) aclp;
+};
+check_syscall_args(sys___acl_get_link)
+#endif /* !RUMP_CLIENT */
+
+#ifndef RUMP_CLIENT
+struct sys___acl_set_link_args {
+ syscallarg(const char *) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(struct acl *) aclp;
+};
+check_syscall_args(sys___acl_set_link)
+#endif /* !RUMP_CLIENT */
+
+#ifndef RUMP_CLIENT
+struct sys___acl_delete_link_args {
+ syscallarg(const char *) path;
+ syscallarg(acl_type_t) type;
+};
+check_syscall_args(sys___acl_delete_link)
+#endif /* !RUMP_CLIENT */
+
+#ifndef RUMP_CLIENT
+struct sys___acl_aclcheck_link_args {
+ syscallarg(const char *) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(struct acl *) aclp;
+};
+check_syscall_args(sys___acl_aclcheck_link)
+#endif /* !RUMP_CLIENT */
+
+#ifndef RUMP_CLIENT
+struct sys___acl_get_file_args {
+ syscallarg(const char *) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(struct acl *) aclp;
+};
+check_syscall_args(sys___acl_get_file)
+#endif /* !RUMP_CLIENT */
+
+#ifndef RUMP_CLIENT
+struct sys___acl_set_file_args {
+ syscallarg(const char *) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(struct acl *) aclp;
+};
+check_syscall_args(sys___acl_set_file)
+#endif /* !RUMP_CLIENT */
+
+#ifndef RUMP_CLIENT
+struct sys___acl_get_fd_args {
+ syscallarg(int) filedes;
+ syscallarg(acl_type_t) type;
+ syscallarg(struct acl *) aclp;
+};
+check_syscall_args(sys___acl_get_fd)
+#endif /* !RUMP_CLIENT */
+
+#ifndef RUMP_CLIENT
+struct sys___acl_set_fd_args {
+ syscallarg(int) filedes;
+ syscallarg(acl_type_t) type;
+ syscallarg(struct acl *) aclp;
+};
+check_syscall_args(sys___acl_set_fd)
+#endif /* !RUMP_CLIENT */
+
+#ifndef RUMP_CLIENT
+struct sys___acl_delete_file_args {
+ syscallarg(const char *) path;
+ syscallarg(acl_type_t) type;
+};
+check_syscall_args(sys___acl_delete_file)
+#endif /* !RUMP_CLIENT */
+
+#ifndef RUMP_CLIENT
+struct sys___acl_delete_fd_args {
+ syscallarg(int) filedes;
+ syscallarg(acl_type_t) type;
+};
+check_syscall_args(sys___acl_delete_fd)
+#endif /* !RUMP_CLIENT */
+
+#ifndef RUMP_CLIENT
+struct sys___acl_aclcheck_file_args {
+ syscallarg(const char *) path;
+ syscallarg(acl_type_t) type;
+ syscallarg(struct acl *) aclp;
+};
+check_syscall_args(sys___acl_aclcheck_file)
+#endif /* !RUMP_CLIENT */
+
+#ifndef RUMP_CLIENT
+struct sys___acl_aclcheck_fd_args {
+ syscallarg(int) filedes;
+ syscallarg(acl_type_t) type;
+ syscallarg(struct acl *) aclp;
+};
+check_syscall_args(sys___acl_aclcheck_fd)
+#endif /* !RUMP_CLIENT */
+
+struct sys_lpathconf_args {
+ syscallarg(const char *) path;
+ syscallarg(int) name;
+};
+check_syscall_args(sys_lpathconf)
+
/*
* System call prototypes.
*/
@@ -4093,5 +4205,31 @@ int sys___fstatvfs190(struct lwp *, const struct sys___fstatvfs190_args *, regis
int sys___fhstatvfs190(struct lwp *, const struct sys___fhstatvfs190_args *, register_t *);
+int sys___acl_get_link(struct lwp *, const struct sys___acl_get_link_args *, register_t *);
+
+int sys___acl_set_link(struct lwp *, const struct sys___acl_set_link_args *, register_t *);
+
+int sys___acl_delete_link(struct lwp *, const struct sys___acl_delete_link_args *, register_t *);
+
+int sys___acl_aclcheck_link(struct lwp *, const struct sys___acl_aclcheck_link_args *, register_t *);
+
+int sys___acl_get_file(struct lwp *, const struct sys___acl_get_file_args *, register_t *);
+
+int sys___acl_set_file(struct lwp *, const struct sys___acl_set_file_args *, register_t *);
+
+int sys___acl_get_fd(struct lwp *, const struct sys___acl_get_fd_args *, register_t *);
+
+int sys___acl_set_fd(struct lwp *, const struct sys___acl_set_fd_args *, register_t *);
+
+int sys___acl_delete_file(struct lwp *, const struct sys___acl_delete_file_args *, register_t *);
+
+int sys___acl_delete_fd(struct lwp *, const struct sys___acl_delete_fd_args *, register_t *);
+
+int sys___acl_aclcheck_file(struct lwp *, const struct sys___acl_aclcheck_file_args *, register_t *);
+
+int sys___acl_aclcheck_fd(struct lwp *, const struct sys___acl_aclcheck_fd_args *, register_t *);
+
+int sys_lpathconf(struct lwp *, const struct sys_lpathconf_args *, register_t *);
+
#endif /* !RUMP_CLIENT */
#endif /* _SYS_SYSCALLARGS_H_ */
diff --git a/sys/sys/types.h b/sys/sys/types.h
index c4971fdd10f..f3e8216b2aa 100644
--- a/sys/sys/types.h
+++ b/sys/sys/types.h
@@ -1,4 +1,4 @@
-/* $NetBSD: types.h,v 1.104 2020/01/28 16:40:27 ad Exp $ */
+/* $NetBSD: types.h,v 1.105 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 1982, 1986, 1991, 1993, 1994
@@ -171,6 +171,11 @@ typedef __mode_t mode_t; /* permissions */
#define mode_t __mode_t
#endif
+#ifndef accmode_t
+typedef __accmode_t accmode_t; /* access permissions */
+#define accmode_t __accmode_t
+#endif
+
typedef uint32_t nlink_t; /* link count */
#ifndef off_t
diff --git a/sys/sys/unistd.h b/sys/sys/unistd.h
index 043a5cce7ee..b7ee7d3eee9 100644
--- a/sys/sys/unistd.h
+++ b/sys/sys/unistd.h
@@ -1,4 +1,4 @@
-/* $NetBSD: unistd.h,v 1.62 2019/10/16 20:43:18 maya Exp $ */
+/* $NetBSD: unistd.h,v 1.63 2020/05/16 18:31:53 christos Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -217,6 +217,11 @@
/* From OpenSolaris, used by SEEK_DATA/SEEK_HOLE. */
#define _PC_MIN_HOLE_SIZE 15
+#ifdef _NETBSD_SOURCE
+#define _PC_ACL_PATH_MAX 16
+#define _PC_ACL_NFS4 17
+#endif
+
/* configurable system variables; use as argument to sysconf(3) */
/*
* XXX The value of _SC_CLK_TCK is embedded in <time.h>.
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index ee69dcbaf02..560e7edaec3 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -1,4 +1,4 @@
-/* $NetBSD: vnode.h,v 1.295 2020/04/13 19:23:20 ad Exp $ */
+/* $NetBSD: vnode.h,v 1.296 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
@@ -66,6 +66,7 @@
#include <sys/rwlock.h>
#include <sys/mutex.h>
#include <sys/time.h>
+#include <sys/acl.h>
/* XXX: clean up includes later */
#include <uvm/uvm_param.h> /* XXX */
@@ -292,11 +293,72 @@ struct vattr {
#define IO_ADV_DECODE(ioflag) (((ioflag) & IO_ADV_MASK) >> IO_ADV_SHIFT)
/*
- * Modes.
+ * Flags for accmode_t.
*/
-#define VREAD 00004 /* read, write, execute permissions */
-#define VWRITE 00002
-#define VEXEC 00001
+#define VEXEC 000000000100 /* execute/search permission */
+#define VWRITE 000000000200 /* write permission */
+#define VREAD 000000000400 /* read permission */
+#define VADMIN 000000010000 /* being the file owner */
+#define VAPPEND 000000040000 /* permission to write/append */
+
+/*
+ * VEXPLICIT_DENY makes VOP_ACCESSX(9) return EPERM or EACCES only
+ * if permission was denied explicitly, by a "deny" rule in NFSv4 ACL,
+ * and 0 otherwise. This never happens with ordinary unix access rights
+ * or POSIX.1e ACLs. Obviously, VEXPLICIT_DENY must be OR-ed with
+ * some other V* constant.
+ */
+#define VEXPLICIT_DENY 000000100000
+#define VREAD_NAMED_ATTRS 000000200000 /* not used */
+#define VWRITE_NAMED_ATTRS 000000400000 /* not used */
+#define VDELETE_CHILD 000001000000
+#define VREAD_ATTRIBUTES 000002000000 /* permission to stat(2) */
+#define VWRITE_ATTRIBUTES 000004000000 /* change {m,c,a}time */
+#define VDELETE 000010000000
+#define VREAD_ACL 000020000000 /* read ACL and file mode */
+#define VWRITE_ACL 000040000000 /* change ACL and/or file mode */
+#define VWRITE_OWNER 000100000000 /* change file owner */
+#define VSYNCHRONIZE 000200000000 /* not used */
+#define VCREAT 000400000000 /* creating new file */
+#define VVERIFY 001000000000 /* verification required */
+
+#define __VNODE_PERM_BITS \
+ "\10" \
+ "\07VEXEC" \
+ "\10VWRITE" \
+ "\11VREAD" \
+ "\15VADMIN" \
+ "\17VAPPEND" \
+ "\20VEXPLICIT_DENY" \
+ "\21VREAD_NAMED_ATTRS" \
+ "\22VWRITE_NAMED_ATTRS" \
+ "\23VDELETE_CHILD" \
+ "\24VREAD_ATTRIBUTES" \
+ "\25VWRITE_ATTRIBUTES" \
+ "\26VDELETE" \
+ "\27VREAD_ACL" \
+ "\30VWRITE_ACL" \
+ "\31VWRITE_OWNER" \
+ "\32VSYNCHRONIZE" \
+ "\33VCREAT" \
+ "\34VVERIFY"
+
+/*
+ * Permissions that were traditionally granted only to the file owner.
+ */
+#define VADMIN_PERMS (VADMIN | VWRITE_ATTRIBUTES | VWRITE_ACL | \
+ VWRITE_OWNER)
+
+/*
+ * Permissions that were traditionally granted to everyone.
+ */
+#define VSTAT_PERMS (VREAD_ATTRIBUTES | VREAD_ACL)
+
+/*
+ * Permissions that allow to change the state of the file in any way.
+ */
+#define VMODIFY_PERMS (VWRITE | VAPPEND | VADMIN_PERMS | VDELETE_CHILD | \
+ VDELETE)
/*
* Token indicating no attribute value yet assigned.
@@ -580,6 +642,7 @@ int rawdev_mounted(struct vnode *, struct vnode **);
uint8_t vtype2dt(enum vtype);
/* see vfssubr(9) */
+int vfs_unixify_accmode(accmode_t *);
void vfs_getnewfsid(struct mount *);
void vfs_timestamp(struct timespec *);
#if defined(DDB) || defined(DEBUGPRINT)
diff --git a/sys/sys/vnode_if.h b/sys/sys/vnode_if.h
index d3ec84e88dc..64e9dacb9de 100644
--- a/sys/sys/vnode_if.h
+++ b/sys/sys/vnode_if.h
@@ -1,4 +1,4 @@
-/* $NetBSD: vnode_if.h,v 1.104 2020/02/23 22:15:18 ad Exp $ */
+/* $NetBSD: vnode_if.h,v 1.105 2020/05/16 18:31:53 christos Exp $ */
/*
* Warning: DO NOT EDIT! This file is automatically generated!
@@ -117,13 +117,23 @@ int VOP_CLOSE(struct vnode *, int, kauth_cred_t);
struct vop_access_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
};
extern const struct vnodeop_desc vop_access_desc;
-int VOP_ACCESS(struct vnode *, int, kauth_cred_t);
+int VOP_ACCESS(struct vnode *, accmode_t, kauth_cred_t);
+
+#define VOP_ACCESSX_DESCOFFSET 8
+struct vop_accessx_args {
+ const struct vnodeop_desc *a_desc;
+ struct vnode *a_vp;
+ accmode_t a_accmode;
+ kauth_cred_t a_cred;
+};
+extern const struct vnodeop_desc vop_accessx_desc;
+int VOP_ACCESSX(struct vnode *, accmode_t, kauth_cred_t);
-#define VOP_GETATTR_DESCOFFSET 8
+#define VOP_GETATTR_DESCOFFSET 9
struct vop_getattr_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -133,7 +143,7 @@ struct vop_getattr_args {
extern const struct vnodeop_desc vop_getattr_desc;
int VOP_GETATTR(struct vnode *, struct vattr *, kauth_cred_t);
-#define VOP_SETATTR_DESCOFFSET 9
+#define VOP_SETATTR_DESCOFFSET 10
struct vop_setattr_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -143,7 +153,7 @@ struct vop_setattr_args {
extern const struct vnodeop_desc vop_setattr_desc;
int VOP_SETATTR(struct vnode *, struct vattr *, kauth_cred_t);
-#define VOP_READ_DESCOFFSET 10
+#define VOP_READ_DESCOFFSET 11
struct vop_read_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -154,7 +164,7 @@ struct vop_read_args {
extern const struct vnodeop_desc vop_read_desc;
int VOP_READ(struct vnode *, struct uio *, int, kauth_cred_t);
-#define VOP_WRITE_DESCOFFSET 11
+#define VOP_WRITE_DESCOFFSET 12
struct vop_write_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -165,7 +175,7 @@ struct vop_write_args {
extern const struct vnodeop_desc vop_write_desc;
int VOP_WRITE(struct vnode *, struct uio *, int, kauth_cred_t);
-#define VOP_FALLOCATE_DESCOFFSET 12
+#define VOP_FALLOCATE_DESCOFFSET 13
struct vop_fallocate_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -175,7 +185,7 @@ struct vop_fallocate_args {
extern const struct vnodeop_desc vop_fallocate_desc;
int VOP_FALLOCATE(struct vnode *, off_t, off_t);
-#define VOP_FDISCARD_DESCOFFSET 13
+#define VOP_FDISCARD_DESCOFFSET 14
struct vop_fdiscard_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -185,7 +195,7 @@ struct vop_fdiscard_args {
extern const struct vnodeop_desc vop_fdiscard_desc;
int VOP_FDISCARD(struct vnode *, off_t, off_t);
-#define VOP_IOCTL_DESCOFFSET 14
+#define VOP_IOCTL_DESCOFFSET 15
struct vop_ioctl_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -197,7 +207,7 @@ struct vop_ioctl_args {
extern const struct vnodeop_desc vop_ioctl_desc;
int VOP_IOCTL(struct vnode *, u_long, void *, int, kauth_cred_t);
-#define VOP_FCNTL_DESCOFFSET 15
+#define VOP_FCNTL_DESCOFFSET 16
struct vop_fcntl_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -209,7 +219,7 @@ struct vop_fcntl_args {
extern const struct vnodeop_desc vop_fcntl_desc;
int VOP_FCNTL(struct vnode *, u_int, void *, int, kauth_cred_t);
-#define VOP_POLL_DESCOFFSET 16
+#define VOP_POLL_DESCOFFSET 17
struct vop_poll_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -218,7 +228,7 @@ struct vop_poll_args {
extern const struct vnodeop_desc vop_poll_desc;
int VOP_POLL(struct vnode *, int);
-#define VOP_KQFILTER_DESCOFFSET 17
+#define VOP_KQFILTER_DESCOFFSET 18
struct vop_kqfilter_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -227,7 +237,7 @@ struct vop_kqfilter_args {
extern const struct vnodeop_desc vop_kqfilter_desc;
int VOP_KQFILTER(struct vnode *, struct knote *);
-#define VOP_REVOKE_DESCOFFSET 18
+#define VOP_REVOKE_DESCOFFSET 19
struct vop_revoke_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -236,7 +246,7 @@ struct vop_revoke_args {
extern const struct vnodeop_desc vop_revoke_desc;
int VOP_REVOKE(struct vnode *, int);
-#define VOP_MMAP_DESCOFFSET 19
+#define VOP_MMAP_DESCOFFSET 20
struct vop_mmap_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -246,7 +256,7 @@ struct vop_mmap_args {
extern const struct vnodeop_desc vop_mmap_desc;
int VOP_MMAP(struct vnode *, vm_prot_t, kauth_cred_t);
-#define VOP_FSYNC_DESCOFFSET 20
+#define VOP_FSYNC_DESCOFFSET 21
struct vop_fsync_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -258,7 +268,7 @@ struct vop_fsync_args {
extern const struct vnodeop_desc vop_fsync_desc;
int VOP_FSYNC(struct vnode *, kauth_cred_t, int, off_t, off_t);
-#define VOP_SEEK_DESCOFFSET 21
+#define VOP_SEEK_DESCOFFSET 22
struct vop_seek_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -269,7 +279,7 @@ struct vop_seek_args {
extern const struct vnodeop_desc vop_seek_desc;
int VOP_SEEK(struct vnode *, off_t, off_t, kauth_cred_t);
-#define VOP_REMOVE_DESCOFFSET 22
+#define VOP_REMOVE_DESCOFFSET 23
struct vop_remove_v2_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_dvp;
@@ -279,7 +289,7 @@ struct vop_remove_v2_args {
extern const struct vnodeop_desc vop_remove_desc;
int VOP_REMOVE(struct vnode *, struct vnode *, struct componentname *);
-#define VOP_LINK_DESCOFFSET 23
+#define VOP_LINK_DESCOFFSET 24
struct vop_link_v2_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_dvp;
@@ -289,7 +299,7 @@ struct vop_link_v2_args {
extern const struct vnodeop_desc vop_link_desc;
int VOP_LINK(struct vnode *, struct vnode *, struct componentname *);
-#define VOP_RENAME_DESCOFFSET 24
+#define VOP_RENAME_DESCOFFSET 25
struct vop_rename_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_fdvp;
@@ -303,7 +313,7 @@ extern const struct vnodeop_desc vop_rename_desc;
int VOP_RENAME(struct vnode *, struct vnode *, struct componentname *,
struct vnode *, struct vnode *, struct componentname *);
-#define VOP_MKDIR_DESCOFFSET 25
+#define VOP_MKDIR_DESCOFFSET 26
struct vop_mkdir_v3_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_dvp;
@@ -315,7 +325,7 @@ extern const struct vnodeop_desc vop_mkdir_desc;
int VOP_MKDIR(struct vnode *, struct vnode **, struct componentname *,
struct vattr *);
-#define VOP_RMDIR_DESCOFFSET 26
+#define VOP_RMDIR_DESCOFFSET 27
struct vop_rmdir_v2_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_dvp;
@@ -325,7 +335,7 @@ struct vop_rmdir_v2_args {
extern const struct vnodeop_desc vop_rmdir_desc;
int VOP_RMDIR(struct vnode *, struct vnode *, struct componentname *);
-#define VOP_SYMLINK_DESCOFFSET 27
+#define VOP_SYMLINK_DESCOFFSET 28
struct vop_symlink_v3_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_dvp;
@@ -338,7 +348,7 @@ extern const struct vnodeop_desc vop_symlink_desc;
int VOP_SYMLINK(struct vnode *, struct vnode **, struct componentname *,
struct vattr *, char *);
-#define VOP_READDIR_DESCOFFSET 28
+#define VOP_READDIR_DESCOFFSET 29
struct vop_readdir_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -352,7 +362,7 @@ extern const struct vnodeop_desc vop_readdir_desc;
int VOP_READDIR(struct vnode *, struct uio *, kauth_cred_t, int *, off_t **,
int *);
-#define VOP_READLINK_DESCOFFSET 29
+#define VOP_READLINK_DESCOFFSET 30
struct vop_readlink_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -362,7 +372,7 @@ struct vop_readlink_args {
extern const struct vnodeop_desc vop_readlink_desc;
int VOP_READLINK(struct vnode *, struct uio *, kauth_cred_t);
-#define VOP_ABORTOP_DESCOFFSET 30
+#define VOP_ABORTOP_DESCOFFSET 31
struct vop_abortop_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_dvp;
@@ -371,7 +381,7 @@ struct vop_abortop_args {
extern const struct vnodeop_desc vop_abortop_desc;
int VOP_ABORTOP(struct vnode *, struct componentname *);
-#define VOP_INACTIVE_DESCOFFSET 31
+#define VOP_INACTIVE_DESCOFFSET 32
struct vop_inactive_v2_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -380,7 +390,7 @@ struct vop_inactive_v2_args {
extern const struct vnodeop_desc vop_inactive_desc;
int VOP_INACTIVE(struct vnode *, bool *);
-#define VOP_RECLAIM_DESCOFFSET 32
+#define VOP_RECLAIM_DESCOFFSET 33
struct vop_reclaim_v2_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -388,7 +398,7 @@ struct vop_reclaim_v2_args {
extern const struct vnodeop_desc vop_reclaim_desc;
int VOP_RECLAIM(struct vnode *);
-#define VOP_LOCK_DESCOFFSET 33
+#define VOP_LOCK_DESCOFFSET 34
struct vop_lock_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -397,7 +407,7 @@ struct vop_lock_args {
extern const struct vnodeop_desc vop_lock_desc;
int VOP_LOCK(struct vnode *, int);
-#define VOP_UNLOCK_DESCOFFSET 34
+#define VOP_UNLOCK_DESCOFFSET 35
struct vop_unlock_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -405,7 +415,7 @@ struct vop_unlock_args {
extern const struct vnodeop_desc vop_unlock_desc;
int VOP_UNLOCK(struct vnode *);
-#define VOP_BMAP_DESCOFFSET 35
+#define VOP_BMAP_DESCOFFSET 36
struct vop_bmap_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -417,7 +427,7 @@ struct vop_bmap_args {
extern const struct vnodeop_desc vop_bmap_desc;
int VOP_BMAP(struct vnode *, daddr_t, struct vnode **, daddr_t *, int *);
-#define VOP_STRATEGY_DESCOFFSET 36
+#define VOP_STRATEGY_DESCOFFSET 37
struct vop_strategy_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -426,7 +436,7 @@ struct vop_strategy_args {
extern const struct vnodeop_desc vop_strategy_desc;
int VOP_STRATEGY(struct vnode *, struct buf *);
-#define VOP_PRINT_DESCOFFSET 37
+#define VOP_PRINT_DESCOFFSET 38
struct vop_print_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -434,7 +444,7 @@ struct vop_print_args {
extern const struct vnodeop_desc vop_print_desc;
int VOP_PRINT(struct vnode *);
-#define VOP_ISLOCKED_DESCOFFSET 38
+#define VOP_ISLOCKED_DESCOFFSET 39
struct vop_islocked_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -442,7 +452,7 @@ struct vop_islocked_args {
extern const struct vnodeop_desc vop_islocked_desc;
int VOP_ISLOCKED(struct vnode *);
-#define VOP_PATHCONF_DESCOFFSET 39
+#define VOP_PATHCONF_DESCOFFSET 40
struct vop_pathconf_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -452,7 +462,7 @@ struct vop_pathconf_args {
extern const struct vnodeop_desc vop_pathconf_desc;
int VOP_PATHCONF(struct vnode *, int, register_t *);
-#define VOP_ADVLOCK_DESCOFFSET 40
+#define VOP_ADVLOCK_DESCOFFSET 41
struct vop_advlock_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -464,7 +474,7 @@ struct vop_advlock_args {
extern const struct vnodeop_desc vop_advlock_desc;
int VOP_ADVLOCK(struct vnode *, void *, int, struct flock *, int);
-#define VOP_WHITEOUT_DESCOFFSET 41
+#define VOP_WHITEOUT_DESCOFFSET 42
struct vop_whiteout_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_dvp;
@@ -474,7 +484,7 @@ struct vop_whiteout_args {
extern const struct vnodeop_desc vop_whiteout_desc;
int VOP_WHITEOUT(struct vnode *, struct componentname *, int);
-#define VOP_GETPAGES_DESCOFFSET 42
+#define VOP_GETPAGES_DESCOFFSET 43
struct vop_getpages_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -490,7 +500,7 @@ extern const struct vnodeop_desc vop_getpages_desc;
int VOP_GETPAGES(struct vnode *, voff_t, struct vm_page **, int *, int,
vm_prot_t, int, int);
-#define VOP_PUTPAGES_DESCOFFSET 43
+#define VOP_PUTPAGES_DESCOFFSET 44
struct vop_putpages_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -501,7 +511,40 @@ struct vop_putpages_args {
extern const struct vnodeop_desc vop_putpages_desc;
int VOP_PUTPAGES(struct vnode *, voff_t, voff_t, int);
-#define VOP_CLOSEEXTATTR_DESCOFFSET 44
+#define VOP_GETACL_DESCOFFSET 45
+struct vop_getacl_args {
+ const struct vnodeop_desc *a_desc;
+ struct vnode *a_vp;
+ acl_type_t a_type;
+ struct acl *a_aclp;
+ kauth_cred_t a_cred;
+};
+extern const struct vnodeop_desc vop_getacl_desc;
+int VOP_GETACL(struct vnode *, acl_type_t, struct acl *, kauth_cred_t);
+
+#define VOP_SETACL_DESCOFFSET 46
+struct vop_setacl_args {
+ const struct vnodeop_desc *a_desc;
+ struct vnode *a_vp;
+ acl_type_t a_type;
+ struct acl *a_aclp;
+ kauth_cred_t a_cred;
+};
+extern const struct vnodeop_desc vop_setacl_desc;
+int VOP_SETACL(struct vnode *, acl_type_t, struct acl *, kauth_cred_t);
+
+#define VOP_ACLCHECK_DESCOFFSET 47
+struct vop_aclcheck_args {
+ const struct vnodeop_desc *a_desc;
+ struct vnode *a_vp;
+ acl_type_t a_type;
+ struct acl *a_aclp;
+ kauth_cred_t a_cred;
+};
+extern const struct vnodeop_desc vop_aclcheck_desc;
+int VOP_ACLCHECK(struct vnode *, acl_type_t, struct acl *, kauth_cred_t);
+
+#define VOP_CLOSEEXTATTR_DESCOFFSET 48
struct vop_closeextattr_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -511,7 +554,7 @@ struct vop_closeextattr_args {
extern const struct vnodeop_desc vop_closeextattr_desc;
int VOP_CLOSEEXTATTR(struct vnode *, int, kauth_cred_t);
-#define VOP_GETEXTATTR_DESCOFFSET 45
+#define VOP_GETEXTATTR_DESCOFFSET 49
struct vop_getextattr_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -525,7 +568,7 @@ extern const struct vnodeop_desc vop_getextattr_desc;
int VOP_GETEXTATTR(struct vnode *, int, const char *, struct uio *,
size_t *, kauth_cred_t);
-#define VOP_LISTEXTATTR_DESCOFFSET 46
+#define VOP_LISTEXTATTR_DESCOFFSET 50
struct vop_listextattr_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -539,7 +582,7 @@ extern const struct vnodeop_desc vop_listextattr_desc;
int VOP_LISTEXTATTR(struct vnode *, int, struct uio *, size_t *, int,
kauth_cred_t);
-#define VOP_OPENEXTATTR_DESCOFFSET 47
+#define VOP_OPENEXTATTR_DESCOFFSET 51
struct vop_openextattr_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -548,7 +591,7 @@ struct vop_openextattr_args {
extern const struct vnodeop_desc vop_openextattr_desc;
int VOP_OPENEXTATTR(struct vnode *, kauth_cred_t);
-#define VOP_DELETEEXTATTR_DESCOFFSET 48
+#define VOP_DELETEEXTATTR_DESCOFFSET 52
struct vop_deleteextattr_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -559,7 +602,7 @@ struct vop_deleteextattr_args {
extern const struct vnodeop_desc vop_deleteextattr_desc;
int VOP_DELETEEXTATTR(struct vnode *, int, const char *, kauth_cred_t);
-#define VOP_SETEXTATTR_DESCOFFSET 49
+#define VOP_SETEXTATTR_DESCOFFSET 53
struct vop_setextattr_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
@@ -572,6 +615,6 @@ extern const struct vnodeop_desc vop_setextattr_desc;
int VOP_SETEXTATTR(struct vnode *, int, const char *, struct uio *,
kauth_cred_t);
-#define VNODE_OPS_COUNT 50
+#define VNODE_OPS_COUNT 54
#endif /* !_SYS_VNODE_IF_H_ */
diff --git a/sys/ufs/chfs/chfs_subr.c b/sys/ufs/chfs/chfs_subr.c
index af2363b9ab8..c3e2915af53 100644
--- a/sys/ufs/chfs/chfs_subr.c
+++ b/sys/ufs/chfs/chfs_subr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: chfs_subr.c,v 1.12 2020/04/23 21:47:08 ad Exp $ */
+/* $NetBSD: chfs_subr.c,v 1.13 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 2010 Department of Software Engineering,
@@ -279,7 +279,7 @@ chfs_chflags(struct vnode *vp, int flags, kauth_cred_t cred)
}
error = kauth_authorize_vnode(cred, action, vp, NULL,
- genfs_can_chflags(cred, CHTTOVT(ip->ch_type), ip->uid, changing_sysflags));
+ genfs_can_chflags(vp, cred, ip->uid, changing_sysflags));
if (error)
return error;
diff --git a/sys/ufs/chfs/chfs_vnode.c b/sys/ufs/chfs/chfs_vnode.c
index 814a4679c38..57d66b11f96 100644
--- a/sys/ufs/chfs/chfs_vnode.c
+++ b/sys/ufs/chfs/chfs_vnode.c
@@ -1,4 +1,4 @@
-/* $NetBSD: chfs_vnode.c,v 1.18 2020/01/17 20:08:10 ad Exp $ */
+/* $NetBSD: chfs_vnode.c,v 1.19 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 2010 Department of Software Engineering,
@@ -251,9 +251,9 @@ chfs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp,
/* authorize setting SGID if needed */
if (ip->mode & ISGID) {
- error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY,
- vp, NULL, genfs_can_chmod(vp->v_type, cnp->cn_cred, ip->uid,
- ip->gid, mode));
+ error = kauth_authorize_vnode(cnp->cn_cred,
+ KAUTH_VNODE_WRITE_SECURITY, vp, NULL, genfs_can_chmod(vp,
+ cnp->cn_cred, ip->uid, ip->gid, mode));
if (error)
ip->mode &= ~ISGID;
}
diff --git a/sys/ufs/chfs/chfs_vnops.c b/sys/ufs/chfs/chfs_vnops.c
index 6c9f3b87926..4edc3a9eae8 100644
--- a/sys/ufs/chfs/chfs_vnops.c
+++ b/sys/ufs/chfs/chfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: chfs_vnops.c,v 1.38 2020/04/23 21:47:08 ad Exp $ */
+/* $NetBSD: chfs_vnops.c,v 1.39 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 2010 Department of Software Engineering,
@@ -371,13 +371,13 @@ int
chfs_access(void *v)
{
struct vnode *vp = ((struct vop_access_args *) v)->a_vp;
- int mode = ((struct vop_access_args *) v)->a_mode;
+ accmode_t accmode = ((struct vop_access_args *) v)->a_accmode;
kauth_cred_t cred = ((struct vop_access_args *) v)->a_cred;
dbg("access()\n");
struct chfs_inode *ip = VTOI(vp);
- if (mode & VWRITE) {
+ if (accmode & VWRITE) {
switch (vp->v_type) {
case VLNK:
case VDIR:
@@ -395,12 +395,12 @@ chfs_access(void *v)
}
}
- if (mode & VWRITE && ip->flags & IMMUTABLE)
+ if (accmode & VWRITE && ip->flags & IMMUTABLE)
return (EPERM);
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, vp->v_type,
- ip->mode & ALLPERMS), vp, NULL, genfs_can_access(vp->v_type,
- ip->mode & ALLPERMS, ip->uid, ip->gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, ip->mode & ALLPERMS), vp, NULL, genfs_can_access(vp,
+ cred, ip->uid, ip->gid, ip->mode & ALLPERMS, NULL, accmode));
}
/* --------------------------------------------------------------------- */
@@ -510,7 +510,8 @@ chfs_setattr(void *v)
/* set time */
if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
- NULL, genfs_can_chtimes(vp, vap->va_vaflags, ip->uid, cred));
+ NULL, genfs_can_chtimes(vp, cred, ip->uid,
+ vap->va_vaflags));
if (error)
return error;
if (vap->va_atime.tv_sec != VNOVAL)
@@ -539,7 +540,7 @@ chfs_chmod(struct vnode *vp, int mode, kauth_cred_t cred)
dbg("chmod\n");
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp,
- NULL, genfs_can_chmod(vp->v_type, cred, ip->uid, ip->gid, mode));
+ NULL, genfs_can_chmod(vp, cred, ip->uid, ip->gid, mode));
if (error)
return error;
ip->mode &= ~ALLPERMS;
@@ -566,7 +567,7 @@ chfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred)
gid = ip->gid;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp,
- NULL, genfs_can_chown(cred, ip->uid, ip->gid, uid, gid));
+ NULL, genfs_can_chown(vp, cred, ip->uid, ip->gid, uid, gid));
if (error)
return error;
@@ -1603,6 +1604,7 @@ const struct vnodeopv_entry_desc chfs_vnodeop_entries[] =
{ &vop_open_desc, chfs_open },
{ &vop_close_desc, chfs_close },
{ &vop_access_desc, chfs_access },
+ { &vop_accessx_desc, genfs_accessx },
{ &vop_getattr_desc, chfs_getattr },
{ &vop_setattr_desc, chfs_setattr },
{ &vop_read_desc, chfs_read },
@@ -1661,6 +1663,7 @@ const struct vnodeopv_entry_desc chfs_specop_entries[] =
{ &vop_open_desc, spec_open },
{ &vop_close_desc, ufsspec_close },
{ &vop_access_desc, chfs_access },
+ { &vop_accessx_desc, genfs_access },
{ &vop_getattr_desc, chfs_getattr },
{ &vop_setattr_desc, chfs_setattr },
{ &vop_read_desc, chfs_read },
@@ -1717,6 +1720,7 @@ const struct vnodeopv_entry_desc chfs_fifoop_entries[] =
{ &vop_open_desc, vn_fifo_bypass },
{ &vop_close_desc, ufsfifo_close },
{ &vop_access_desc, chfs_access },
+ { &vop_accessx_desc, genfs_access },
{ &vop_getattr_desc, chfs_getattr },
{ &vop_setattr_desc, chfs_setattr },
{ &vop_read_desc, ufsfifo_read },
diff --git a/sys/ufs/ext2fs/ext2fs_lookup.c b/sys/ufs/ext2fs/ext2fs_lookup.c
index 7effa369d96..b8130ca38fc 100644
--- a/sys/ufs/ext2fs/ext2fs_lookup.c
+++ b/sys/ufs/ext2fs/ext2fs_lookup.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_lookup.c,v 1.90 2020/04/04 20:49:31 ad Exp $ */
+/* $NetBSD: ext2fs_lookup.c,v 1.91 2020/05/16 18:31:53 christos Exp $ */
/*
* Modified for NetBSD 1.2E
@@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.90 2020/04/04 20:49:31 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.91 2020/05/16 18:31:53 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -661,7 +661,7 @@ found:
*/
if (dp->i_e2fs_mode & ISVTX) {
error = kauth_authorize_vnode(cred, KAUTH_VNODE_DELETE,
- tdp, vdp, genfs_can_sticky(cred, dp->i_uid,
+ tdp, vdp, genfs_can_sticky(vdp, cred, dp->i_uid,
VTOI(tdp)->i_uid));
if (error) {
vrele(tdp);
diff --git a/sys/ufs/ext2fs/ext2fs_vfsops.c b/sys/ufs/ext2fs/ext2fs_vfsops.c
index 7d01c5b0acf..8d2971ce2a8 100644
--- a/sys/ufs/ext2fs/ext2fs_vfsops.c
+++ b/sys/ufs/ext2fs/ext2fs_vfsops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_vfsops.c,v 1.218 2020/04/04 20:49:31 ad Exp $ */
+/* $NetBSD: ext2fs_vfsops.c,v 1.219 2020/05/16 18:31:53 christos Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1994
@@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.218 2020/04/04 20:49:31 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.219 2020/05/16 18:31:53 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
@@ -1148,8 +1148,8 @@ ext2fs_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp,
/* Authorize setting SGID if needed. */
if (ip->i_e2fs_mode & ISGID) {
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY,
- vp, NULL, genfs_can_chmod(vp->v_type, cred, ip->i_uid,
- ip->i_gid, mode));
+ vp, NULL, genfs_can_chmod(vp, cred, ip->i_uid, ip->i_gid,
+ mode));
if (error)
ip->i_e2fs_mode &= ~ISGID;
}
diff --git a/sys/ufs/ext2fs/ext2fs_vnops.c b/sys/ufs/ext2fs/ext2fs_vnops.c
index 0d81ba46aa6..9f2ea3de6ae 100644
--- a/sys/ufs/ext2fs/ext2fs_vnops.c
+++ b/sys/ufs/ext2fs/ext2fs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_vnops.c,v 1.131 2020/03/08 17:38:12 kamil Exp $ */
+/* $NetBSD: ext2fs_vnops.c,v 1.132 2020/05/16 18:31:53 christos Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.131 2020/03/08 17:38:12 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.132 2020/05/16 18:31:53 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -226,13 +226,14 @@ ext2fs_check_possible(struct vnode *vp, struct inode *ip, mode_t mode)
}
static int
-ext2fs_check_permitted(struct vnode *vp, struct inode *ip, mode_t mode,
+ext2fs_check_permitted(struct vnode *vp, struct inode *ip, accmode_t accmode,
kauth_cred_t cred)
{
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, vp->v_type,
- ip->i_e2fs_mode & ALLPERMS), vp, NULL, genfs_can_access(vp->v_type,
- ip->i_e2fs_mode & ALLPERMS, ip->i_uid, ip->i_gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, ip->i_e2fs_mode & ALLPERMS), vp, NULL,
+ genfs_can_access(vp, cred, ip->i_uid, ip->i_gid,
+ ip->i_e2fs_mode & ALLPERMS, NULL, accmode));
}
int
@@ -240,12 +241,12 @@ ext2fs_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
- mode_t mode = ap->a_mode;
+ accmode_t mode = ap->a_accmode;
int error;
error = ext2fs_check_possible(vp, ip, mode);
@@ -367,8 +368,7 @@ ext2fs_setattr(void *v)
#endif /* EXT2FS_SYSTEM_FLAGS */
error = kauth_authorize_vnode(cred, action, vp, NULL,
- genfs_can_chflags(cred, vp->v_type, ip->i_uid,
- changing_sysflags));
+ genfs_can_chflags(vp, cred, ip->i_uid, changing_sysflags));
if (error)
return error;
@@ -425,8 +425,8 @@ ext2fs_setattr(void *v)
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return EROFS;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
- NULL, genfs_can_chtimes(vp, vap->va_vaflags, ip->i_uid,
- cred));
+ NULL, genfs_can_chtimes(vp, cred, ip->i_uid,
+ vap->va_vaflags));
if (error)
return error;
if (vap->va_atime.tv_sec != VNOVAL)
@@ -468,8 +468,7 @@ ext2fs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct lwp *l)
int error;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp,
- NULL, genfs_can_chmod(vp->v_type, cred, ip->i_uid, ip->i_gid,
- mode));
+ NULL, genfs_can_chmod(vp, cred, ip->i_uid, ip->i_gid, mode));
if (error)
return error;
@@ -498,7 +497,7 @@ ext2fs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred,
gid = ip->i_gid;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp,
- NULL, genfs_can_chown(cred, ip->i_uid, ip->i_gid, uid, gid));
+ NULL, genfs_can_chown(vp, cred, ip->i_uid, ip->i_gid, uid, gid));
if (error)
return error;
@@ -1101,6 +1100,7 @@ const struct vnodeopv_entry_desc ext2fs_vnodeop_entries[] = {
{ &vop_open_desc, ext2fs_open }, /* open */
{ &vop_close_desc, ufs_close }, /* close */
{ &vop_access_desc, ext2fs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, ext2fs_getattr }, /* getattr */
{ &vop_setattr_desc, ext2fs_setattr }, /* setattr */
{ &vop_read_desc, ext2fs_read }, /* read */
@@ -1155,6 +1155,7 @@ const struct vnodeopv_entry_desc ext2fs_specop_entries[] = {
{ &vop_open_desc, spec_open }, /* open */
{ &vop_close_desc, ufsspec_close }, /* close */
{ &vop_access_desc, ext2fs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, ext2fs_getattr }, /* getattr */
{ &vop_setattr_desc, ext2fs_setattr }, /* setattr */
{ &vop_read_desc, ufsspec_read }, /* read */
@@ -1209,6 +1210,7 @@ const struct vnodeopv_entry_desc ext2fs_fifoop_entries[] = {
{ &vop_open_desc, vn_fifo_bypass }, /* open */
{ &vop_close_desc, ufsfifo_close }, /* close */
{ &vop_access_desc, ext2fs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, ext2fs_getattr }, /* getattr */
{ &vop_setattr_desc, ext2fs_setattr }, /* setattr */
{ &vop_read_desc, ufsfifo_read }, /* read */
diff --git a/sys/ufs/ext2fs/ext2fs_xattr.c b/sys/ufs/ext2fs/ext2fs_xattr.c
index 3053696ba08..9af26cdc954 100644
--- a/sys/ufs/ext2fs/ext2fs_xattr.c
+++ b/sys/ufs/ext2fs/ext2fs_xattr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_xattr.c,v 1.4 2016/08/23 06:40:54 christos Exp $ */
+/* $NetBSD: ext2fs_xattr.c,v 1.5 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_xattr.c,v 1.4 2016/08/23 06:40:54 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_xattr.c,v 1.5 2020/05/16 18:31:53 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -205,19 +205,13 @@ ext2fs_getextattr(void *v)
kauth_cred_t a_cred;
} */ *ap = v;
struct inode *ip = VTOI(ap->a_vp);
- char namebuf[EXT2FS_XATTR_NAME_LEN_MAX + 1];
int error;
const char *prefix, *name;
uint8_t name_index;
size_t name_match, valuesize = 0;
- if (ap->a_attrnamespace == EXTATTR_NAMESPACE_USER)
- prefix = xattr_prefix_index[EXT2FS_XATTR_PREFIX_USER];
- else
- prefix = xattr_prefix_index[EXT2FS_XATTR_PREFIX_SYSTEM];
- snprintf(namebuf, sizeof(namebuf), "%s%s", prefix, ap->a_name);
-
- error = extattr_check_cred(ap->a_vp, namebuf, ap->a_cred, VREAD);
+ error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, ap->a_cred,
+ VREAD);
if (error)
return error;
@@ -408,7 +402,6 @@ ext2fs_listextattr(void *v)
} */ *ap = v;
struct inode *ip = VTOI(ap->a_vp);
int error;
- const char *prefix;
size_t listsize = 0;
if (!EXT2F_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_EXTATTR)) {
@@ -416,15 +409,8 @@ ext2fs_listextattr(void *v)
goto out;
}
- /*
- * XXX: We can move this inside the loop and iterate on individual
- * attributes.
- */
- if (ap->a_attrnamespace == EXTATTR_NAMESPACE_USER)
- prefix = xattr_prefix_index[EXT2FS_XATTR_PREFIX_USER];
- else
- prefix = xattr_prefix_index[EXT2FS_XATTR_PREFIX_SYSTEM];
- error = extattr_check_cred(ap->a_vp, prefix, ap->a_cred, VREAD);
+ error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, ap->a_cred,
+ VREAD);
if (error)
return error;
diff --git a/sys/ufs/ffs/ffs_extattr.c b/sys/ufs/ffs/ffs_extattr.c
index 41b30ed7d95..9c4875e2f67 100644
--- a/sys/ufs/ffs/ffs_extattr.c
+++ b/sys/ufs/ffs/ffs_extattr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ffs_extattr.c,v 1.4 2020/05/02 22:11:16 christos Exp $ */
+/* $NetBSD: ffs_extattr.c,v 1.5 2020/05/16 18:31:53 christos Exp $ */
/*-
* SPDX-License-Identifier: (BSD-2-Clause-FreeBSD AND BSD-3-Clause)
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_extattr.c,v 1.4 2020/05/02 22:11:16 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_extattr.c,v 1.5 2020/05/16 18:31:53 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -134,34 +134,6 @@ typedef daddr_t ufs_lbn_t;
#define vfs_bio_set_flags(bp, ioflag) __nothing
/*
- * Credential check based on process requesting service, and per-attribute
- * permissions.
- */
-static int
-ffs_extattr_check_cred(struct vnode *vp, int attrnamespace, kauth_cred_t cred,
- accmode_t accmode)
-{
- /*
- * Kernel-invoked always succeeds.
- */
- if (cred == NOCRED)
- return 0;
-
- /*
- * Do not allow privileged processes in jail to directly manipulate
- * system attributes.
- */
- switch (attrnamespace) {
- case EXTATTR_NAMESPACE_SYSTEM:
- return kauth_authorize_system(cred, KAUTH_SYSTEM_FS_EXTATTR,
- 0, vp->v_mount, NULL, NULL);
- case EXTATTR_NAMESPACE_USER:
- return VOP_ACCESS(vp, accmode, cred);
- default:
- return EPERM;
- }
-}
-/*
* Extended attribute area reading.
*/
static int
@@ -683,7 +655,7 @@ ffs_getextattr(void *v)
if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
return (EOPNOTSUPP);
- error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
+ error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
ap->a_cred, VREAD);
if (error)
return (error);
@@ -757,7 +729,7 @@ ffs_setextattr(void *v)
if (ealen < 0 || ealen > lblktosize(fs, UFS_NXADDR))
return (EINVAL);
- error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
+ error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
ap->a_cred, VWRITE);
if (error) {
@@ -862,7 +834,7 @@ ffs_listextattr(void *v)
if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
return (EOPNOTSUPP);
- error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
+ error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
ap->a_cred, VREAD);
if (error)
return (error);
@@ -932,7 +904,7 @@ ffs_deleteextattr(void *v)
if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
- error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
+ error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
ap->a_cred, VWRITE);
if (error) {
/*
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 0e5ac7426bc..eace8edf602 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ffs_vfsops.c,v 1.368 2020/05/12 23:17:41 ad Exp $ */
+/* $NetBSD: ffs_vfsops.c,v 1.369 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.368 2020/05/12 23:17:41 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.369 2020/05/16 18:31:53 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -394,6 +394,52 @@ ffs_mountroot(void)
return (0);
}
+static void
+ffs_acls(struct mount *mp, int fs_flags)
+{
+ if ((fs_flags & FS_ACLS) != 0) {
+#ifdef UFS_ACL
+ if (mp->mnt_flag & MNT_POSIX1EACLS)
+ printf("WARNING: %s: ACLs flag on fs conflicts with "
+ "\"posix1eacls\" mount option; option ignored\n",
+ mp->mnt_stat.f_mntonname);
+ mp->mnt_flag &= ~MNT_ACLS;
+ mp->mnt_flag |= MNT_POSIX1EACLS;
+
+#else
+ printf("WARNING: %s: ACLs flag on fs but no ACLs support\n",
+ mp->mnt_stat.f_mntonname);
+#endif
+ }
+ if ((fs_flags & FS_POSIX1EACLS) != 0) {
+#ifdef UFS_ACL
+ if (mp->mnt_flag & MNT_ACLS)
+ printf("WARNING: %s: NFSv4 ACLs flag on fs conflicts "
+ "with \"acls\" mount option; option ignored\n",
+ mp->mnt_stat.f_mntonname);
+ mp->mnt_flag &= ~MNT_POSIX1EACLS;
+ mp->mnt_flag |= MNT_ACLS;
+#else
+ printf("WARNING: %s: POSIX.1e ACLs flag on fs but no "
+ "ACLs support\n", mp->mnt_stat.f_mntonname);
+#endif
+ }
+
+ if ((mp->mnt_flag & (MNT_ACLS | MNT_POSIX1EACLS))
+ == (MNT_ACLS | MNT_POSIX1EACLS))
+ {
+ printf("WARNING: %s: posix1eacl conflicts "
+ "with \"acls\" mount option; option ignored\n",
+ mp->mnt_stat.f_mntonname);
+ mp->mnt_flag &= ~MNT_POSIX1EACLS;
+ }
+
+ if (mp->mnt_flag & (MNT_ACLS | MNT_POSIX1EACLS))
+ mp->mnt_iflag &= ~(IMNT_SHRLOOKUP|IMNT_NCLOOKUP);
+ else
+ mp->mnt_iflag |= IMNT_SHRLOOKUP|IMNT_NCLOOKUP;
+}
+
/*
* VFS Operations.
*
@@ -612,6 +658,8 @@ ffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
DPRINTF("ffs_reload returned %d", error);
return error;
}
+ } else {
+ ffs_acls(mp, 0);
}
if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) {
@@ -854,6 +902,8 @@ ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l)
}
ffs_oldfscompat_read(fs, ump, sblockloc);
+ ffs_acls(mp, 0);
+
mutex_enter(&ump->um_lock);
ump->um_maxfilesize = fs->fs_maxfilesize;
if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
@@ -865,6 +915,7 @@ ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l)
return (EINVAL);
}
}
+
if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
fs->fs_pendingblocks = 0;
fs->fs_pendinginodes = 0;
@@ -1460,6 +1511,7 @@ ffs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l)
if (needswap)
ump->um_flags |= UFS_NEEDSWAP;
#endif
+ ffs_acls(mp, fs->fs_flags);
ump->um_mountp = mp;
ump->um_dev = dev;
ump->um_devvp = devvp;
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 2db930e4ba6..c2af559754b 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ffs_vnops.c,v 1.131 2020/04/18 19:18:34 christos Exp $ */
+/* $NetBSD: ffs_vnops.c,v 1.132 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.131 2020/04/18 19:18:34 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.132 2020/05/16 18:31:53 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -88,6 +88,7 @@ __KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.131 2020/04/18 19:18:34 christos Exp
#include <miscfs/genfs/genfs.h>
#include <miscfs/specfs/specdev.h>
+#include <ufs/ufs/acl.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ufs/ufs_extern.h>
@@ -109,7 +110,8 @@ const struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
{ &vop_mknod_desc, ufs_mknod }, /* mknod */
{ &vop_open_desc, ufs_open }, /* open */
{ &vop_close_desc, ufs_close }, /* close */
- { &vop_access_desc, ufs_access }, /* access */
+ { &vop_access_desc, genfs_access }, /* access */
+ { &vop_accessx_desc, ufs_accessx }, /* accessx */
{ &vop_getattr_desc, ufs_getattr }, /* getattr */
{ &vop_setattr_desc, ufs_setattr }, /* setattr */
{ &vop_read_desc, ffs_read }, /* read */
@@ -152,6 +154,9 @@ const struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
{ &vop_setextattr_desc, ffs_setextattr }, /* setextattr */
{ &vop_listextattr_desc, ffs_listextattr }, /* listextattr */
{ &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
+ { &vop_getacl_desc, ufs_getacl }, /* getacl */
+ { &vop_setacl_desc, ufs_setacl }, /* setacl */
+ { &vop_aclcheck_desc, ufs_aclcheck }, /* aclcheck */
{ NULL, NULL }
};
const struct vnodeopv_desc ffs_vnodeop_opv_desc =
@@ -165,7 +170,8 @@ const struct vnodeopv_entry_desc ffs_specop_entries[] = {
{ &vop_mknod_desc, spec_mknod }, /* mknod */
{ &vop_open_desc, spec_open }, /* open */
{ &vop_close_desc, ufsspec_close }, /* close */
- { &vop_access_desc, ufs_access }, /* access */
+ { &vop_access_desc, genfs_access }, /* access */
+ { &vop_accessx_desc, ufs_accessx }, /* accessx */
{ &vop_getattr_desc, ufs_getattr }, /* getattr */
{ &vop_setattr_desc, ufs_setattr }, /* setattr */
{ &vop_read_desc, ufsspec_read }, /* read */
@@ -208,6 +214,9 @@ const struct vnodeopv_entry_desc ffs_specop_entries[] = {
{ &vop_setextattr_desc, ffs_setextattr }, /* setextattr */
{ &vop_listextattr_desc, ffs_listextattr }, /* listextattr */
{ &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
+ { &vop_getacl_desc, ufs_getacl }, /* getacl */
+ { &vop_setacl_desc, ufs_setacl }, /* setacl */
+ { &vop_aclcheck_desc, ufs_aclcheck }, /* aclcheck */
{ NULL, NULL }
};
const struct vnodeopv_desc ffs_specop_opv_desc =
@@ -221,7 +230,8 @@ const struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
{ &vop_mknod_desc, vn_fifo_bypass }, /* mknod */
{ &vop_open_desc, vn_fifo_bypass }, /* open */
{ &vop_close_desc, ufsfifo_close }, /* close */
- { &vop_access_desc, ufs_access }, /* access */
+ { &vop_access_desc, genfs_access }, /* access */
+ { &vop_accessx_desc, ufs_accessx }, /* accessx */
{ &vop_getattr_desc, ufs_getattr }, /* getattr */
{ &vop_setattr_desc, ufs_setattr }, /* setattr */
{ &vop_read_desc, ufsfifo_read }, /* read */
@@ -263,6 +273,9 @@ const struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
{ &vop_setextattr_desc, ffs_setextattr }, /* setextattr */
{ &vop_listextattr_desc, ffs_listextattr }, /* listextattr */
{ &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
+ { &vop_getacl_desc, ufs_getacl }, /* getacl */
+ { &vop_setacl_desc, ufs_setacl }, /* setacl */
+ { &vop_aclcheck_desc, ufs_aclcheck }, /* aclcheck */
{ NULL, NULL }
};
const struct vnodeopv_desc ffs_fifoop_opv_desc =
diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h
index 00bb93c8706..796b2af09f0 100644
--- a/sys/ufs/ffs/fs.h
+++ b/sys/ufs/ffs/fs.h
@@ -1,4 +1,4 @@
-/* $NetBSD: fs.h,v 1.67 2020/04/18 19:18:34 christos Exp $ */
+/* $NetBSD: fs.h,v 1.68 2020/05/16 18:31:53 christos Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@@ -418,23 +418,31 @@ struct fs {
/*
* File system flags
+ *
+ * FS_POSIX1EACLS indicates that POSIX.1e ACLs are administratively enabled
+ * for the file system, so they should be loaded from extended attributes,
+ * observed for access control purposes, and be administered by object
+ * owners. FS_ACLS indicates that NFSv4 ACLs are administratively
+ * enabled. This flag is mutually exclusive with FS_POSIX1EACLS.
*/
#define FS_UNCLEAN 0x001 /* file system not clean at mount (unused) */
#define FS_DOSOFTDEP 0x002 /* file system using soft dependencies */
#define FS_NEEDSFSCK 0x004 /* needs sync fsck (FreeBSD compat, unused) */
#define FS_SUJ 0x008 /* file system using journaled softupdates */
-#define FS_ACLS 0x010 /* file system has ACLs enabled */
+#define FS_POSIX1EACLS 0x010 /* file system has POSIX.1e ACLs enabled */
#define FS_MULTILABEL 0x020 /* file system is MAC multi-label */
#define FS_GJOURNAL 0x40 /* gjournaled file system */
#define FS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */
#define FS_DOWAPBL 0x100 /* Write ahead physical block logging */
-/* FS_NFS4ACLS 0x100 file system has NFSv4 ACLs enabled (FBSD) */
+/* FS_NFS4ACLS 0x100 file system has NFSv4 ACLs enabled (FBSD) */
#define FS_DOQUOTA2 0x200 /* in-filesystem quotas */
/* FS_INDEXDIRS 0x200 kernel supports indexed directories (FBSD)*/
#define FS_TRIM 0x400 /* discard deleted blocks in storage layer */
+#define FS_ACLS 0x800 /* file system has NFSv4 ACLs enabled */
/* File system flags that are ok for NetBSD if set in fs_flags */
-#define FS_KNOWN_FLAGS (FS_DOSOFTDEP | FS_DOWAPBL | FS_DOQUOTA2)
+#define FS_KNOWN_FLAGS (FS_DOSOFTDEP | FS_DOWAPBL | FS_DOQUOTA2 | \
+ FS_POSIX1EACLS | FS_ACLS)
/*
* File system internal flags, also in fs_flags.
diff --git a/sys/ufs/files.ufs b/sys/ufs/files.ufs
index a6ca5a8c43f..d2110795fdf 100644
--- a/sys/ufs/files.ufs
+++ b/sys/ufs/files.ufs
@@ -1,4 +1,4 @@
-# $NetBSD: files.ufs,v 1.47 2020/04/18 19:18:33 christos Exp $
+# $NetBSD: files.ufs,v 1.48 2020/05/16 18:31:53 christos Exp $
deffs FFS
deffs EXT2FS
@@ -7,7 +7,7 @@ deffs LFS
deffs CHFS
defflag opt_ffs.h FFS_EI FFS_NO_SNAPSHOT APPLE_UFS
- UFS_DIRHASH UFS_EXTATTR
+ UFS_DIRHASH UFS_EXTATTR UFS_ACL
defflag opt_lfs.h LFS_EI LFS_KERNEL_RFW
LFS_DIRHASH LFS_EXTATTR
@@ -99,6 +99,7 @@ file ufs/mfs/mfs_vnops.c mfs
file ufs/mfs/mfs_miniroot.c
define ufs: vfs
+file ufs/ufs/ufs_acl.c ufs & (ffs | mfs | ext2fs | chfs)
file ufs/ufs/ufs_bmap.c ufs & (ffs | mfs | ext2fs | chfs)
file ufs/ufs/ufs_dirhash.c (ffs | mfs | ext2fs | chfs) & ufs_dirhash
file ufs/ufs/ufs_extattr.c (ffs | mfs) & ufs_extattr
diff --git a/sys/ufs/lfs/lfs_vnops.c b/sys/ufs/lfs/lfs_vnops.c
index dfdef8114c5..2412745a248 100644
--- a/sys/ufs/lfs/lfs_vnops.c
+++ b/sys/ufs/lfs/lfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_vnops.c,v 1.332 2020/04/13 19:23:20 ad Exp $ */
+/* $NetBSD: lfs_vnops.c,v 1.333 2020/05/16 18:31:53 christos Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -125,7 +125,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.332 2020/04/13 19:23:20 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.333 2020/05/16 18:31:53 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
@@ -192,6 +192,7 @@ const struct vnodeopv_entry_desc lfs_vnodeop_entries[] = {
{ &vop_open_desc, ulfs_open }, /* open */
{ &vop_close_desc, lfs_close }, /* close */
{ &vop_access_desc, ulfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, lfs_getattr }, /* getattr */
{ &vop_setattr_desc, lfs_setattr }, /* setattr */
{ &vop_read_desc, lfs_read }, /* read */
@@ -248,6 +249,7 @@ const struct vnodeopv_entry_desc lfs_specop_entries[] = {
{ &vop_open_desc, spec_open }, /* open */
{ &vop_close_desc, lfsspec_close }, /* close */
{ &vop_access_desc, ulfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, lfs_getattr }, /* getattr */
{ &vop_setattr_desc, lfs_setattr }, /* setattr */
{ &vop_read_desc, ulfsspec_read }, /* read */
@@ -304,6 +306,7 @@ const struct vnodeopv_entry_desc lfs_fifoop_entries[] = {
{ &vop_open_desc, vn_fifo_bypass }, /* open */
{ &vop_close_desc, lfsfifo_close }, /* close */
{ &vop_access_desc, ulfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, lfs_getattr }, /* getattr */
{ &vop_setattr_desc, lfs_setattr }, /* setattr */
{ &vop_read_desc, ulfsfifo_read }, /* read */
@@ -381,8 +384,9 @@ lfs_makeinode(struct vattr *vap, struct vnode *dvp,
/* Authorize setting SGID if needed. */
if (ip->i_mode & ISGID) {
- error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY,
- tvp, NULL, genfs_can_chmod(tvp->v_type, cnp->cn_cred, ip->i_uid,
+ error = kauth_authorize_vnode(cnp->cn_cred,
+ KAUTH_VNODE_WRITE_SECURITY,
+ tvp, NULL, genfs_can_chmod(tvp, cnp->cn_cred, ip->i_uid,
ip->i_gid, MAKEIMODE(vap->va_type, vap->va_mode)));
if (error) {
ip->i_mode &= ~ISGID;
diff --git a/sys/ufs/lfs/ulfs_extattr.c b/sys/ufs/lfs/ulfs_extattr.c
index 3ade8e0a42c..810cc6938e6 100644
--- a/sys/ufs/lfs/ulfs_extattr.c
+++ b/sys/ufs/lfs/ulfs_extattr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ulfs_extattr.c,v 1.15 2020/01/17 20:08:10 ad Exp $ */
+/* $NetBSD: ulfs_extattr.c,v 1.16 2020/05/16 18:31:53 christos Exp $ */
/* from NetBSD: ulfs_extattr.c,v 1.48 2016/11/09 05:08:35 dholland Exp */
/*-
@@ -49,7 +49,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ulfs_extattr.c,v 1.15 2020/01/17 20:08:10 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ulfs_extattr.c,v 1.16 2020/05/16 18:31:53 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_lfs.h"
@@ -108,58 +108,6 @@ static int ulfs_extattr_get_header(struct vnode *,
struct ulfs_extattr_header *, off_t *);
/*
- * Convert a FreeBSD extended attribute and namespace to a consistent string
- * representation.
- *
- * The returned value, if not NULL, is guaranteed to be an allocated object
- * of its size as returned by strlen() + 1 and must be freed by the caller.
- */
-static char *
-from_freebsd_extattr(int attrnamespace, const char *attrname)
-{
- const char *namespace;
- char *attr;
- size_t len;
-
- if (attrnamespace == EXTATTR_NAMESPACE_SYSTEM)
- namespace = "system";
- else if (attrnamespace == EXTATTR_NAMESPACE_USER)
- namespace = "user";
- else
- return NULL;
-
- /* <namespace>.<attrname>\0 */
- len = strlen(namespace) + 1 + strlen(attrname) + 1;
-
- attr = kmem_alloc(len, KM_SLEEP);
-
- snprintf(attr, len, "%s.%s", namespace, attrname);
-
- return attr;
-}
-
-/*
- * Internal wrapper around a conversion-check-free sequence.
- */
-static int
-internal_extattr_check_cred(vnode_t *vp, int attrnamespace, const char *name,
- kauth_cred_t cred, int access_mode)
-{
- char *attr;
- int error;
-
- attr = from_freebsd_extattr(attrnamespace, name);
- if (attr == NULL)
- return EINVAL;
-
- error = extattr_check_cred(vp, attr, cred, access_mode);
-
- kmem_free(attr, strlen(attr) + 1);
-
- return error;
-}
-
-/*
* Per-FS attribute lock protecting attribute operations.
* XXX Right now there is a lot of lock contention due to having a single
* lock per-FS; really, this should be far more fine-grained.
@@ -1141,8 +1089,7 @@ ulfs_extattr_get(struct vnode *vp, int attrnamespace, const char *name,
if (strlen(name) == 0)
return (EINVAL);
- error = internal_extattr_check_cred(vp, attrnamespace, name, cred,
- VREAD);
+ error = extattr_check_cred(vp, attrnamespace, cred, VREAD);
if (error)
return (error);
@@ -1260,8 +1207,7 @@ ulfs_extattr_list(struct vnode *vp, int attrnamespace,
* XXX: We can move this inside the loop and iterate on individual
* attributes.
*/
- error = internal_extattr_check_cred(vp, attrnamespace, "", cred,
- VREAD);
+ error = extattr_check_cred(vp, attrnamespace, cred, VREAD);
if (error)
return (error);
@@ -1431,8 +1377,7 @@ ulfs_extattr_set(struct vnode *vp, int attrnamespace, const char *name,
if (!ulfs_extattr_valid_attrname(attrnamespace, name))
return (EINVAL);
- error = internal_extattr_check_cred(vp, attrnamespace, name, cred,
- VWRITE);
+ error = extattr_check_cred(vp, attrnamespace, cred, VWRITE);
if (error)
return (error);
@@ -1550,8 +1495,7 @@ ulfs_extattr_rm(struct vnode *vp, int attrnamespace, const char *name,
if (!ulfs_extattr_valid_attrname(attrnamespace, name))
return (EINVAL);
- error = internal_extattr_check_cred(vp, attrnamespace, name, cred,
- VWRITE);
+ error = extattr_check_cred(vp, attrnamespace, cred, VWRITE);
if (error)
return (error);
diff --git a/sys/ufs/lfs/ulfs_lookup.c b/sys/ufs/lfs/ulfs_lookup.c
index 9584f25b6e5..abfe5c72937 100644
--- a/sys/ufs/lfs/ulfs_lookup.c
+++ b/sys/ufs/lfs/ulfs_lookup.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ulfs_lookup.c,v 1.43 2020/04/04 20:49:31 ad Exp $ */
+/* $NetBSD: ulfs_lookup.c,v 1.44 2020/05/16 18:31:53 christos Exp $ */
/* from NetBSD: ufs_lookup.c,v 1.135 2015/07/11 11:04:48 mlelstv */
/*
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ulfs_lookup.c,v 1.43 2020/04/04 20:49:31 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ulfs_lookup.c,v 1.44 2020/05/16 18:31:53 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_lfs.h"
@@ -574,7 +574,7 @@ found:
*/
if (dp->i_mode & ISVTX) {
error = kauth_authorize_vnode(cred, KAUTH_VNODE_DELETE,
- tdp, vdp, genfs_can_sticky(cred, dp->i_uid,
+ tdp, vdp, genfs_can_sticky(vdp, cred, dp->i_uid,
VTOI(tdp)->i_uid));
if (error) {
vrele(tdp);
diff --git a/sys/ufs/lfs/ulfs_vnops.c b/sys/ufs/lfs/ulfs_vnops.c
index 7f95e4a97d0..809e690466f 100644
--- a/sys/ufs/lfs/ulfs_vnops.c
+++ b/sys/ufs/lfs/ulfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ulfs_vnops.c,v 1.52 2017/10/28 00:37:13 pgoyette Exp $ */
+/* $NetBSD: ulfs_vnops.c,v 1.53 2020/05/16 18:31:53 christos Exp $ */
/* from NetBSD: ufs_vnops.c,v 1.232 2016/05/19 18:32:03 riastradh Exp */
/*-
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ulfs_vnops.c,v 1.52 2017/10/28 00:37:13 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ulfs_vnops.c,v 1.53 2020/05/16 18:31:53 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_lfs.h"
@@ -140,7 +140,7 @@ ulfs_open(void *v)
}
static int
-ulfs_check_possible(struct vnode *vp, struct inode *ip, mode_t mode,
+ulfs_check_possible(struct vnode *vp, struct inode *ip, accmode_t accmode,
kauth_cred_t cred)
{
#if defined(LFS_QUOTA) || defined(LFS_QUOTA2)
@@ -152,7 +152,7 @@ ulfs_check_possible(struct vnode *vp, struct inode *ip, mode_t mode,
* unless the file is a socket, fifo, or a block or
* character device resident on the file system.
*/
- if (mode & VWRITE) {
+ if (accmode & VWRITE) {
switch (vp->v_type) {
case VDIR:
case VLNK:
@@ -180,20 +180,21 @@ ulfs_check_possible(struct vnode *vp, struct inode *ip, mode_t mode,
if ((ip->i_flags & SF_SNAPSHOT))
return (EPERM);
/* If immutable bit set, nobody gets to write it. */
- if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE))
+ if ((accmode & VWRITE) && (ip->i_flags & IMMUTABLE))
return (EPERM);
return 0;
}
static int
-ulfs_check_permitted(struct vnode *vp, struct inode *ip, mode_t mode,
+ulfs_check_permitted(struct vnode *vp, struct inode *ip, accmode_t accmode,
kauth_cred_t cred)
{
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, vp->v_type,
- ip->i_mode & ALLPERMS), vp, NULL, genfs_can_access(vp->v_type,
- ip->i_mode & ALLPERMS, ip->i_uid, ip->i_gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, ip->i_mode & ALLPERMS), vp, NULL, genfs_can_access(
+ vp, cred, ip->i_uid, ip->i_gid, ip->i_mode & ALLPERMS,
+ NULL, accmode));
}
int
@@ -201,26 +202,26 @@ ulfs_access(void *v)
{
struct vop_access_args /* {
struct vnode *a_vp;
- int a_mode;
+ accmode_t a_accmode;
kauth_cred_t a_cred;
} */ *ap = v;
struct vnode *vp;
struct inode *ip;
- mode_t mode;
+ accmode_t accmode;
int error;
vp = ap->a_vp;
- mode = ap->a_mode;
+ accmode = ap->a_accmode;
KASSERT(VOP_ISLOCKED(vp));
ip = VTOI(vp);
- error = ulfs_check_possible(vp, ip, mode, ap->a_cred);
+ error = ulfs_check_possible(vp, ip, accmode, ap->a_cred);
if (error)
return error;
- error = ulfs_check_permitted(vp, ip, mode, ap->a_cred);
+ error = ulfs_check_permitted(vp, ip, accmode, ap->a_cred);
return error;
}
@@ -292,7 +293,7 @@ ulfs_setattr(void *v)
}
error = kauth_authorize_vnode(cred, action, vp, NULL,
- genfs_can_chflags(cred, vp->v_type, ip->i_uid,
+ genfs_can_chflags(vp, cred, ip->i_uid,
changing_sysflags));
if (error)
goto out;
@@ -371,7 +372,8 @@ ulfs_setattr(void *v)
goto out;
}
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
- NULL, genfs_can_chtimes(vp, vap->va_vaflags, ip->i_uid, cred));
+ NULL, genfs_can_chtimes(vp, cred, ip->i_uid,
+ vap->va_vaflags));
if (error)
goto out;
if (vap->va_atime.tv_sec != VNOVAL)
@@ -424,7 +426,7 @@ ulfs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct lwp *l)
ip = VTOI(vp);
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp,
- NULL, genfs_can_chmod(vp->v_type, cred, ip->i_uid, ip->i_gid, mode));
+ NULL, genfs_can_chmod(vp, cred, ip->i_uid, ip->i_gid, mode));
if (error)
return (error);
@@ -462,7 +464,7 @@ ulfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred,
gid = ip->i_gid;
error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp,
- NULL, genfs_can_chown(cred, ip->i_uid, ip->i_gid, uid, gid));
+ NULL, genfs_can_chown(vp, cred, ip->i_uid, ip->i_gid, uid, gid));
if (error)
return (error);
diff --git a/sys/ufs/mfs/mfs_vnops.c b/sys/ufs/mfs/mfs_vnops.c
index 42dd94953a0..d5f0e8862b5 100644
--- a/sys/ufs/mfs/mfs_vnops.c
+++ b/sys/ufs/mfs/mfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mfs_vnops.c,v 1.60 2020/04/13 19:23:20 ad Exp $ */
+/* $NetBSD: mfs_vnops.c,v 1.61 2020/05/16 18:31:54 christos Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mfs_vnops.c,v 1.60 2020/04/13 19:23:20 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mfs_vnops.c,v 1.61 2020/05/16 18:31:54 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -64,6 +64,7 @@ const struct vnodeopv_entry_desc mfs_vnodeop_entries[] = {
{ &vop_open_desc, mfs_open }, /* open */
{ &vop_close_desc, mfs_close }, /* close */
{ &vop_access_desc, mfs_access }, /* access */
+ { &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, mfs_getattr }, /* getattr */
{ &vop_setattr_desc, mfs_setattr }, /* setattr */
{ &vop_read_desc, mfs_read }, /* read */
diff --git a/sys/ufs/ufs/README.acls b/sys/ufs/ufs/README.acls
new file mode 100644
index 00000000000..feaf1a47ff6
--- /dev/null
+++ b/sys/ufs/ufs/README.acls
@@ -0,0 +1,79 @@
+$FreeBSD: head/sys/ufs/ufs/README.acls 105456 2002-10-19 16:09:16Z rwatson $
+
+ UFS Access Control Lists Copyright
+
+The UFS Access Control Lists implementation is copyright Robert Watson,
+and is made available under a Berkeley-style license.
+
+ About UFS Access Control Lists (ACLs)
+
+Access control lists allow the association of fine-grained discretionary
+access control information with files and directories, extending the
+base UNIX permission model in a (mostly) compatible way. This
+implementation largely follows the POSIX.1e model, and relies on the
+availability of extended attributes to store extended components of
+the ACL, while maintaining the base permission information in the inode.
+
+ Using UFS Access Control Lists (ACLs)
+
+Support for UFS access control lists may be enabled by adding:
+
+ options UFS_ACL
+
+to your kernel configuration. As ACLs rely on the availability of extended
+attributes, your file systems must have support for extended attributes.
+For UFS2, this is supported natively, so no further configuration is
+necessary. For UFS1, you must also enable the optional extended attributes
+support documented in README.extattr. A summary of the instructions
+and ACL-specific information follows.
+
+To enable support for ACLs on a file system, the 'acls' mount flag
+must be set for the file system. This may be set using the tunefs
+'-a' flag:
+
+ tunefs -a enable /dev/md0a
+
+Or by using the mount-time flag:
+
+ mount -o acls /dev/md0a /mnt
+
+The flag may also be set in /etc/fstab. Note that mounting a file
+system previously configured for ACLs without ACL-support will result
+in incorrect application of discretionary protections. Likewise,
+mounting an ACL-enabled file system without kernel support for ACLs
+will result in incorrect application of discretionary protections. If
+the kernel is not configured for ACL support, a warning will be
+printed by the kernel at mount-time. For reliability purposes, it
+is recommended that the superblock flag be used instead of the
+mount-time flag, as this will avoid re-mount isses with the root file
+system. For reliability and performance reasons, the use of ACLs on
+UFS1 is discouraged; UFS2 extended attributes provide a more reliable
+storage mechanism for ACLs.
+
+Currently, support for ACLs on UFS1 requires the use of UFS1 EAs, which may
+be enabled by adding:
+
+ options UFS_EXTATTR
+
+to your kernel configuration file and rebuilding. Because of filesystem
+mount atomicity requirements, it is also recommended that:
+
+ options UFS_EXTATTR_AUTOSTART
+
+be added to the kernel so as to support the atomic enabling of the
+required extended attributes with the filesystem mount operation. To
+enable ACLs, two extended attributes must be available in the
+EXTATTR_NAMESPACE_SYSTEM namespace: "posix1e.acl_access", which holds
+the access ACL, and "posix1e.acl_default" which holds the default ACL
+for directories. If you're using UFS1 Extended Attributes, the following
+commands may be used to create the necessary EA backing files for
+ACLs in the filesystem root of each filesystem. In these examples,
+the root filesystem is used; see README.extattr for more details.
+
+ mkdir -p /.attribute/system
+ cd /.attribute/system
+ extattrctl initattr -p / 388 posix1e.acl_access
+ extattrctl initattr -p / 388 posix1e.acl_default
+
+On the next mount of the root filesystem, the attributes will be
+automatically started, and ACLs will be enabled.
diff --git a/sys/ufs/ufs/acl.h b/sys/ufs/ufs/acl.h
new file mode 100644
index 00000000000..31045f40cc3
--- /dev/null
+++ b/sys/ufs/ufs/acl.h
@@ -0,0 +1,62 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999-2001 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/sys/ufs/ufs/acl.h 326272 2017-11-27 15:23:17Z pfg $
+ */
+/*
+ * Developed by the TrustedBSD Project.
+ * Support for POSIX.1e access control lists.
+ */
+
+#ifndef _UFS_UFS_ACL_H_
+#define _UFS_UFS_ACL_H_
+
+#ifdef _KERNEL
+
+struct inode;
+int ufs_getacl_nfs4_internal(struct vnode *vp, struct acl *aclp, struct lwp *l);
+int ufs_setacl_nfs4_internal(struct vnode *vp, struct acl *aclp, struct lwp *l, bool lock);
+int ufs_setacl_posix1e(struct vnode *vp, int type, struct acl *aclp,
+ kauth_cred_t cred, struct lwp *l);
+void ufs_sync_acl_from_inode(struct inode *ip, struct acl *acl);
+void ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip);
+
+#ifdef UFS_ACL
+int ufs_getacl(void *);
+int ufs_setacl(void *);
+int ufs_aclcheck(void *);
+#else
+#define ufs_getacl genfs_eopnotsupp
+#define ufs_setacl genfs_eopnotsupp
+#define ufs_aclcheck genfs_eopnotsupp
+#endif
+
+#endif /* !_KERNEL */
+
+#endif /* !_UFS_UFS_ACL_H_ */
diff --git a/sys/ufs/ufs/ufs_acl.c b/sys/ufs/ufs/ufs_acl.c
new file mode 100644
index 00000000000..b04ac416bde
--- /dev/null
+++ b/sys/ufs/ufs/ufs_acl.c
@@ -0,0 +1,698 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1999-2003 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Support for POSIX.1e access control lists: UFS-specific support functions.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: head/sys/ufs/ufs/ufs_acl.c 356669 2020-01-13 02:31:51Z mjg $");
+#endif
+__KERNEL_RCSID(0, "$NetBSD: ufs_acl.c,v 1.1 2020/05/16 18:31:54 christos Exp $");
+
+#if defined(_KERNEL_OPT)
+#include "opt_ffs.h"
+#include "opt_quota.h"
+#include "opt_wapbl.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/wapbl.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <sys/event.h>
+#include <sys/extattr.h>
+#include <sys/proc.h>
+
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
+#include <ufs/ufs/acl.h>
+#include <ufs/ufs/extattr.h>
+#include <ufs/ufs/dir.h>
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/ufs_extern.h>
+#include <ufs/ufs/ufs_wapbl.h>
+
+#include <ufs/ffs/fs.h>
+
+#ifdef UFS_ACL
+
+/*
+ * Synchronize an ACL and an inode by copying over appropriate inode fields
+ * to the passed ACL. Assumes an ACL that would satisfy acl_posix1e_check(),
+ * and may panic if not.
+ */
+void
+ufs_sync_acl_from_inode(struct inode *ip, struct acl *acl)
+{
+ struct acl_entry *acl_mask, *acl_group_obj;
+ int i;
+
+ /*
+ * Update ACL_USER_OBJ, ACL_OTHER, but simply identify ACL_MASK
+ * and ACL_GROUP_OBJ for use after we know whether ACL_MASK is
+ * present.
+ */
+ acl_mask = NULL;
+ acl_group_obj = NULL;
+ for (i = 0; i < acl->acl_cnt; i++) {
+ switch (acl->acl_entry[i].ae_tag) {
+ case ACL_USER_OBJ:
+ acl->acl_entry[i].ae_perm = acl_posix1e_mode_to_perm(
+ ACL_USER_OBJ, ip->i_mode);
+ acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID;
+ break;
+
+ case ACL_GROUP_OBJ:
+ acl_group_obj = &acl->acl_entry[i];
+ acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID;
+ break;
+
+ case ACL_OTHER:
+ acl->acl_entry[i].ae_perm = acl_posix1e_mode_to_perm(
+ ACL_OTHER, ip->i_mode);
+ acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID;
+ break;
+
+ case ACL_MASK:
+ acl_mask = &acl->acl_entry[i];
+ acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID;
+ break;
+
+ case ACL_USER:
+ case ACL_GROUP:
+ break;
+
+ default:
+ panic("ufs_sync_acl_from_inode(): bad ae_tag");
+ }
+ }
+
+ if (acl_group_obj == NULL)
+ panic("ufs_sync_acl_from_inode(): no ACL_GROUP_OBJ");
+
+ if (acl_mask == NULL) {
+ /*
+ * There is no ACL_MASK, so update ACL_GROUP_OBJ.
+ */
+ acl_group_obj->ae_perm = acl_posix1e_mode_to_perm(
+ ACL_GROUP_OBJ, ip->i_mode);
+ } else {
+ /*
+ * Update the ACL_MASK entry instead of ACL_GROUP_OBJ.
+ */
+ acl_mask->ae_perm = acl_posix1e_mode_to_perm(ACL_GROUP_OBJ,
+ ip->i_mode);
+ }
+}
+
+/*
+ * Calculate what the inode mode should look like based on an authoritative
+ * ACL for the inode. Replace only the fields in the inode that the ACL
+ * can represent.
+ */
+void
+ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip)
+{
+
+ ip->i_mode &= ACL_PRESERVE_MASK;
+ ip->i_mode |= acl_posix1e_acl_to_mode(acl);
+ DIP_ASSIGN(ip, mode, ip->i_mode);
+}
+
+/*
+ * Retrieve NFSv4 ACL, skipping access checks. Must be used in UFS code
+ * instead of VOP_GETACL() when we don't want to be restricted by the user
+ * not having ACL_READ_ACL permission, e.g. when calculating inherited ACL
+ * or in ufs_vnops.c:ufs_accessx().
+ */
+int
+ufs_getacl_nfs4_internal(struct vnode *vp, struct acl *aclp, struct lwp *l)
+{
+ int error;
+ size_t len;
+ struct inode *ip = VTOI(vp);
+
+ len = sizeof(*aclp);
+ bzero(aclp, len);
+
+ error = vn_extattr_get(vp, IO_NODELOCKED,
+ NFS4_ACL_EXTATTR_NAMESPACE, NFS4_ACL_EXTATTR_NAME, &len, aclp, l);
+ aclp->acl_maxcnt = ACL_MAX_ENTRIES;
+ if (error == ENOATTR) {
+ /*
+ * Legitimately no ACL set on object, purely
+ * emulate it through the inode.
+ */
+ acl_nfs4_sync_acl_from_mode(aclp, ip->i_mode, ip->i_uid);
+
+ return (0);
+ }
+
+ if (error)
+ return (error);
+
+ if (len != sizeof(*aclp)) {
+ /*
+ * A short (or long) read, meaning that for
+ * some reason the ACL is corrupted. Return
+ * EPERM since the object DAC protections
+ * are unsafe.
+ */
+ printf("%s: Loaded invalid ACL ("
+ "%zu bytes), inumber %ju on %s\n", __func__, len,
+ (uintmax_t)ip->i_number, ip->i_fs->fs_fsmnt);
+
+ return (EPERM);
+ }
+
+ error = acl_nfs4_check(aclp, vp->v_type == VDIR);
+ if (error) {
+ printf("%s: Loaded invalid ACL "
+ "(failed acl_nfs4_check), inumber %ju on %s\n", __func__,
+ (uintmax_t)ip->i_number, ip->i_fs->fs_fsmnt);
+
+ return (EPERM);
+ }
+
+ return (0);
+}
+
+static int
+ufs_getacl_nfs4(struct vop_getacl_args *ap, struct lwp *l)
+{
+ int error;
+
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
+ return (EINVAL);
+
+ error = VOP_ACCESSX(ap->a_vp, VREAD_ACL, ap->a_cred);
+ if (error)
+ return (error);
+
+ error = ufs_getacl_nfs4_internal(ap->a_vp, ap->a_aclp, l);
+
+ return (error);
+}
+
+/*
+ * Read POSIX.1e ACL from an EA. Return error if its not found
+ * or if any other error has occurred.
+ */
+static int
+ufs_get_oldacl(acl_type_t type, struct oldacl *old, struct vnode *vp,
+ struct lwp *l)
+{
+ int error;
+ size_t len;
+ struct inode *ip = VTOI(vp);
+
+ len = sizeof(*old);
+
+ switch (type) {
+ case ACL_TYPE_ACCESS:
+ error = vn_extattr_get(vp, IO_NODELOCKED,
+ POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE,
+ POSIX1E_ACL_ACCESS_EXTATTR_NAME, &len, old, l);
+ break;
+ case ACL_TYPE_DEFAULT:
+ if (vp->v_type != VDIR)
+ return (EINVAL);
+ error = vn_extattr_get(vp, IO_NODELOCKED,
+ POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE,
+ POSIX1E_ACL_DEFAULT_EXTATTR_NAME, &len, old, l);
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ if (error != 0)
+ return (error);
+
+ if (len != sizeof(*old)) {
+ /*
+ * A short (or long) read, meaning that for some reason
+ * the ACL is corrupted. Return EPERM since the object
+ * DAC protections are unsafe.
+ */
+ printf("%s: Loaded invalid ACL "
+ "(len = %zu), inumber %ju on %s\n", __func__, len,
+ (uintmax_t)ip->i_number, ip->i_fs->fs_fsmnt);
+ return (EPERM);
+ }
+
+ return (0);
+}
+
+/*
+ * Retrieve the ACL on a file.
+ *
+ * As part of the ACL is stored in the inode, and the rest in an EA,
+ * assemble both into a final ACL product. Right now this is not done
+ * very efficiently.
+ */
+static int
+ufs_getacl_posix1e(struct vop_getacl_args *ap, struct lwp *l)
+{
+ struct inode *ip = VTOI(ap->a_vp);
+ int error;
+ struct oldacl *old;
+
+ /*
+ * XXX: If ufs_getacl() should work on file systems not supporting
+ * ACLs, remove this check.
+ */
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_POSIX1EACLS) == 0)
+ return (EINVAL);
+
+ old = kmem_zalloc(sizeof(*old), KM_SLEEP);
+
+ /*
+ * Attempt to retrieve the ACL from the extended attributes.
+ */
+ error = ufs_get_oldacl(ap->a_type, old, ap->a_vp, l);
+ switch (error) {
+ /*
+ * XXX: If ufs_getacl() should work on filesystems
+ * without the EA configured, add case EOPNOTSUPP here.
+ */
+ case ENOATTR:
+ switch (ap->a_type) {
+ case ACL_TYPE_ACCESS:
+ /*
+ * Legitimately no ACL set on object, purely
+ * emulate it through the inode. These fields will
+ * be updated when the ACL is synchronized with
+ * the inode later.
+ */
+ old->acl_cnt = 3;
+ old->acl_entry[0].ae_tag = ACL_USER_OBJ;
+ old->acl_entry[0].ae_id = ACL_UNDEFINED_ID;
+ old->acl_entry[0].ae_perm = ACL_PERM_NONE;
+ old->acl_entry[1].ae_tag = ACL_GROUP_OBJ;
+ old->acl_entry[1].ae_id = ACL_UNDEFINED_ID;
+ old->acl_entry[1].ae_perm = ACL_PERM_NONE;
+ old->acl_entry[2].ae_tag = ACL_OTHER;
+ old->acl_entry[2].ae_id = ACL_UNDEFINED_ID;
+ old->acl_entry[2].ae_perm = ACL_PERM_NONE;
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ /*
+ * Unlike ACL_TYPE_ACCESS, there is no relationship
+ * between the inode contents and the ACL, and it is
+ * therefore possible for the request for the ACL
+ * to fail since the ACL is undefined. In this
+ * situation, return success and an empty ACL,
+ * as required by POSIX.1e.
+ */
+ old->acl_cnt = 0;
+ break;
+ }
+ /* FALLTHROUGH */
+ case 0:
+ error = acl_copy_oldacl_into_acl(old, ap->a_aclp);
+ if (error != 0)
+ break;
+
+ if (ap->a_type == ACL_TYPE_ACCESS)
+ ufs_sync_acl_from_inode(ip, ap->a_aclp);
+ default:
+ break;
+ }
+
+ kmem_free(old, sizeof(*old));
+ return (error);
+}
+
+int
+ufs_getacl(void *v)
+{
+ struct vop_getacl_args *ap = v;
+
+ if ((ap->a_vp->v_mount->mnt_flag & (MNT_POSIX1EACLS | MNT_ACLS)) == 0)
+ return (EOPNOTSUPP);
+
+ if (ap->a_type == ACL_TYPE_NFS4)
+ return (ufs_getacl_nfs4(ap, curlwp));
+
+ return (ufs_getacl_posix1e(ap, curlwp));
+}
+
+/*
+ * Set NFSv4 ACL without doing any access checking. This is required
+ * e.g. by the UFS code that implements ACL inheritance, or from
+ * ufs_vnops.c:ufs_chmod(), as some of the checks have to be skipped
+ * in that case, and others are redundant.
+ */
+int
+ufs_setacl_nfs4_internal(struct vnode *vp, struct acl *aclp,
+ struct lwp *l, bool lock)
+{
+ int error;
+ mode_t mode;
+ struct inode *ip = VTOI(vp);
+
+ KASSERT(acl_nfs4_check(aclp, vp->v_type == VDIR) == 0);
+
+ if (acl_nfs4_is_trivial(aclp, ip->i_uid)) {
+ error = vn_extattr_rm(vp, IO_NODELOCKED,
+ NFS4_ACL_EXTATTR_NAMESPACE, NFS4_ACL_EXTATTR_NAME, l);
+ /*
+ * An attempt to remove ACL from a file that didn't have
+ * any extended entries is not an error.
+ */
+ if (error == ENOATTR)
+ error = 0;
+
+ } else {
+ error = vn_extattr_set(vp, IO_NODELOCKED,
+ NFS4_ACL_EXTATTR_NAMESPACE, NFS4_ACL_EXTATTR_NAME,
+ sizeof(*aclp), aclp, l);
+ }
+
+ /*
+ * Map lack of attribute definition in UFS_EXTATTR into lack of
+ * support for ACLs on the filesystem.
+ */
+ if (error == ENOATTR)
+ return (EOPNOTSUPP);
+
+ if (error)
+ return (error);
+
+ mode = ip->i_mode;
+
+ __acl_nfs4_sync_mode_from_acl(&mode, aclp);
+
+ if (lock && (error = UFS_WAPBL_BEGIN(vp->v_mount)) != 0)
+ return error;
+
+ ip->i_mode &= ACL_PRESERVE_MASK;
+ ip->i_mode |= mode;
+ DIP_ASSIGN(ip, mode, ip->i_mode);
+ ip->i_flag |= IN_CHANGE;
+
+ KNOTE(&vp->v_klist, NOTE_REVOKE);
+
+ error = UFS_UPDATE(vp, NULL, NULL, 0);
+ if (lock)
+ UFS_WAPBL_END(vp->v_mount);
+
+ return (error);
+}
+
+static int
+ufs_setacl_nfs4(struct vop_setacl_args *ap, struct lwp *l)
+{
+ int error;
+ struct inode *ip = VTOI(ap->a_vp);
+
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
+ return (EINVAL);
+
+ if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+
+ if (ap->a_aclp == NULL)
+ return (EINVAL);
+
+ error = VOP_ACLCHECK(ap->a_vp, ap->a_type, ap->a_aclp, ap->a_cred);
+ if (error)
+ return (error);
+
+ /*
+ * Authorize the ACL operation.
+ */
+ if (ip->i_flags & (IMMUTABLE | APPEND))
+ return (EPERM);
+
+ /*
+ * Must hold VWRITE_ACL or have appropriate privilege.
+ */
+ if ((error = VOP_ACCESSX(ap->a_vp, VWRITE_ACL, l->l_cred)))
+ return (error);
+
+ /*
+ * With NFSv4 ACLs, chmod(2) may need to add additional entries.
+ * Make sure it has enough room for that - splitting every entry
+ * into two and appending "canonical six" entries at the end.
+ */
+ if (ap->a_aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2)
+ return (ENOSPC);
+
+ error = ufs_setacl_nfs4_internal(ap->a_vp, ap->a_aclp, l, true);
+
+ return (error);
+}
+
+/*
+ * Set the ACL on a file.
+ *
+ * As part of the ACL is stored in the inode, and the rest in an EA,
+ * this is necessarily non-atomic, and has complex authorization.
+ * As ufs_setacl() includes elements of ufs_chown() and ufs_chmod(),
+ * a fair number of different access checks may be required to go ahead
+ * with the operation at all.
+ */
+int
+ufs_setacl_posix1e(struct vnode *vp, int type, struct acl *aclp,
+ kauth_cred_t cred, struct lwp *l)
+{
+ struct inode *ip = VTOI(vp);
+ int error;
+ struct oldacl *old;
+
+ if ((vp->v_mount->mnt_flag & MNT_POSIX1EACLS) == 0)
+ return (EINVAL);
+
+ /*
+ * If this is a set operation rather than a delete operation,
+ * invoke VOP_ACLCHECK() on the passed ACL to determine if it is
+ * valid for the target. This will include a check on ap->a_type.
+ */
+ if (aclp != NULL) {
+ /*
+ * Set operation.
+ */
+ error = VOP_ACLCHECK(vp, type, aclp, cred);
+ if (error != 0)
+ return (error);
+ } else {
+ /*
+ * Delete operation.
+ * POSIX.1e allows only deletion of the default ACL on a
+ * directory (ACL_TYPE_DEFAULT).
+ */
+ if (type != ACL_TYPE_DEFAULT)
+ return (EINVAL);
+ if (vp->v_type != VDIR)
+ return (ENOTDIR);
+ }
+
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+
+ /*
+ * Authorize the ACL operation.
+ */
+ if (ip->i_flags & (IMMUTABLE | APPEND))
+ return (EPERM);
+
+ /*
+ * Must hold VADMIN (be file owner) or have appropriate privilege.
+ */
+ if ((error = VOP_ACCESS(vp, VADMIN, cred)))
+ return (error);
+
+ switch(type) {
+ case ACL_TYPE_ACCESS:
+ old = kmem_zalloc(sizeof(*old), KM_SLEEP);
+ error = acl_copy_acl_into_oldacl(aclp, old);
+ if (error == 0) {
+ error = vn_extattr_set(vp, IO_NODELOCKED,
+ POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE,
+ POSIX1E_ACL_ACCESS_EXTATTR_NAME, sizeof(*old),
+ old, l);
+ }
+ kmem_free(old, sizeof(*old));
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ if (aclp == NULL) {
+ error = vn_extattr_rm(vp, IO_NODELOCKED,
+ POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE,
+ POSIX1E_ACL_DEFAULT_EXTATTR_NAME, l);
+ /*
+ * Attempting to delete a non-present default ACL
+ * will return success for portability purposes.
+ * (TRIX)
+ *
+ * XXX: Note that since we can't distinguish
+ * "that EA is not supported" from "that EA is not
+ * defined", the success case here overlaps the
+ * the ENOATTR->EOPNOTSUPP case below.
+ */
+ if (error == ENOATTR)
+ error = 0;
+ } else {
+ old = kmem_zalloc(sizeof(*old), KM_SLEEP);
+ error = acl_copy_acl_into_oldacl(aclp, old);
+ if (error == 0) {
+ error = vn_extattr_set(vp, IO_NODELOCKED,
+ POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE,
+ POSIX1E_ACL_DEFAULT_EXTATTR_NAME,
+ sizeof(*old), (char *) old, l);
+ }
+ kmem_free(old, sizeof(*old));
+ }
+ break;
+
+ default:
+ error = EINVAL;
+ }
+ /*
+ * Map lack of attribute definition in UFS_EXTATTR into lack of
+ * support for ACLs on the filesystem.
+ */
+ if (error == ENOATTR)
+ return (EOPNOTSUPP);
+ if (error != 0)
+ return (error);
+
+ if (type == ACL_TYPE_ACCESS) {
+ /*
+ * Now that the EA is successfully updated, update the
+ * inode and mark it as changed.
+ */
+ if ((error = UFS_WAPBL_BEGIN(vp->v_mount)) != 0)
+ return error;
+
+ ufs_sync_inode_from_acl(aclp, ip);
+ ip->i_flag |= IN_CHANGE;
+ error = UFS_UPDATE(vp, NULL, NULL, 0);
+
+ UFS_WAPBL_END(vp->v_mount);
+ }
+
+ KNOTE(&vp->v_klist, NOTE_ATTRIB);
+ return (error);
+}
+
+int
+ufs_setacl(void *v)
+{
+ struct vop_setacl_args *ap = v;
+ if ((ap->a_vp->v_mount->mnt_flag & (MNT_POSIX1EACLS | MNT_ACLS)) == 0)
+ return (EOPNOTSUPP);
+
+ if (ap->a_type == ACL_TYPE_NFS4)
+ return ufs_setacl_nfs4(ap, curlwp);
+
+ return ufs_setacl_posix1e(ap->a_vp, ap->a_type, ap->a_aclp, ap->a_cred,
+ curlwp);
+}
+
+static int
+ufs_aclcheck_nfs4(struct vop_aclcheck_args *ap, struct lwp *l)
+{
+ int is_directory = 0;
+
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
+ return (EINVAL);
+
+ /*
+ * With NFSv4 ACLs, chmod(2) may need to add additional entries.
+ * Make sure it has enough room for that - splitting every entry
+ * into two and appending "canonical six" entries at the end.
+ */
+ if (ap->a_aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2)
+ return (ENOSPC);
+
+ if (ap->a_vp->v_type == VDIR)
+ is_directory = 1;
+
+ return (acl_nfs4_check(ap->a_aclp, is_directory));
+}
+
+static int
+ufs_aclcheck_posix1e(struct vop_aclcheck_args *ap, struct lwp *l)
+{
+
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_POSIX1EACLS) == 0)
+ return (EINVAL);
+
+ /*
+ * Verify we understand this type of ACL, and that it applies
+ * to this kind of object.
+ * Rely on the acl_posix1e_check() routine to verify the contents.
+ */
+ switch(ap->a_type) {
+ case ACL_TYPE_ACCESS:
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ if (ap->a_vp->v_type != VDIR)
+ return (EINVAL);
+ break;
+
+ default:
+ return (EINVAL);
+ }
+
+ if (ap->a_aclp->acl_cnt > OLDACL_MAX_ENTRIES)
+ return (EINVAL);
+
+ return (acl_posix1e_check(ap->a_aclp));
+}
+
+/*
+ * Check the validity of an ACL for a file.
+ */
+int
+ufs_aclcheck(void *v)
+{
+ struct vop_aclcheck_args *ap = v;
+
+ if ((ap->a_vp->v_mount->mnt_flag & (MNT_POSIX1EACLS | MNT_ACLS)) == 0)
+ return (EOPNOTSUPP);
+
+ if (ap->a_type == ACL_TYPE_NFS4)
+ return ufs_aclcheck_nfs4(ap, curlwp);
+
+ return ufs_aclcheck_posix1e(ap, curlwp);
+}
+
+#endif /* !UFS_ACL */
diff --git a/sys/ufs/ufs/ufs_extattr.c b/sys/ufs/ufs/ufs_extattr.c
index 42aa4630748..fa463bcb03a 100644
--- a/sys/ufs/ufs/ufs_extattr.c
+++ b/sys/ufs/ufs/ufs_extattr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_extattr.c,v 1.51 2020/01/17 20:08:10 ad Exp $ */
+/* $NetBSD: ufs_extattr.c,v 1.52 2020/05/16 18:31:54 christos Exp $ */
/*-
* Copyright (c) 1999-2002 Robert N. M. Watson
@@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_extattr.c,v 1.51 2020/01/17 20:08:10 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_extattr.c,v 1.52 2020/05/16 18:31:54 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_ffs.h"
@@ -107,57 +107,6 @@ static int ufs_extattr_get_header(struct vnode *,
struct ufs_extattr_list_entry *,
struct ufs_extattr_header *, off_t *);
-/*
- * Convert a FreeBSD extended attribute and namespace to a consistent string
- * representation.
- *
- * The returned value, if not NULL, is guaranteed to be an allocated object
- * of its size as returned by strlen() + 1 and must be freed by the caller.
- */
-static char *
-from_freebsd_extattr(int attrnamespace, const char *attrname)
-{
- const char *namespace;
- char *attr;
- size_t len;
-
- if (attrnamespace == EXTATTR_NAMESPACE_SYSTEM)
- namespace = "system";
- else if (attrnamespace == EXTATTR_NAMESPACE_USER)
- namespace = "user";
- else
- return NULL;
-
- /* <namespace>.<attrname>\0 */
- len = strlen(namespace) + 1 + strlen(attrname) + 1;
-
- attr = kmem_alloc(len, KM_SLEEP);
-
- snprintf(attr, len, "%s.%s", namespace, attrname);
-
- return attr;
-}
-
-/*
- * Internal wrapper around a conversion-check-free sequence.
- */
-static int
-internal_extattr_check_cred(vnode_t *vp, int attrnamespace, const char *name,
- kauth_cred_t cred, int access_mode)
-{
- char *attr;
- int error;
-
- attr = from_freebsd_extattr(attrnamespace, name);
- if (attr == NULL)
- return EINVAL;
-
- error = extattr_check_cred(vp, attr, cred, access_mode);
-
- kmem_free(attr, strlen(attr) + 1);
-
- return error;
-}
/*
* Per-FS attribute lock protecting attribute operations.
@@ -1130,8 +1079,7 @@ ufs_extattr_get(struct vnode *vp, int attrnamespace, const char *name,
if (strlen(name) == 0)
return EINVAL;
- error = internal_extattr_check_cred(vp, attrnamespace, name, cred,
- VREAD);
+ error = extattr_check_cred(vp, attrnamespace, cred, VREAD);
if (error)
return error;
@@ -1249,8 +1197,7 @@ ufs_extattr_list(struct vnode *vp, int attrnamespace,
* XXX: We can move this inside the loop and iterate on individual
* attributes.
*/
- error = internal_extattr_check_cred(vp, attrnamespace, "", cred,
- VREAD);
+ error = extattr_check_cred(vp, attrnamespace, cred, VREAD);
if (error)
return error;
@@ -1420,8 +1367,7 @@ ufs_extattr_set(struct vnode *vp, int attrnamespace, const char *name,
if (!ufs_extattr_valid_attrname(attrnamespace, name))
return EINVAL;
- error = internal_extattr_check_cred(vp, attrnamespace, name, cred,
- VWRITE);
+ error = extattr_check_cred(vp, attrnamespace, cred, VWRITE);
if (error)
return error;
@@ -1539,8 +1485,7 @@ ufs_extattr_rm(struct vnode *vp, int attrnamespace, const char *name,
if (!ufs_extattr_valid_attrname(attrnamespace, name))
return EINVAL;
- error = internal_extattr_check_cred(vp, attrnamespace, name, cred,
- VWRITE);
+ error = extattr_check_cred(vp, attrnamespace, cred, VWRITE);
if (error)
return error;
diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h
index df42f1d452c..12d3f02da98 100644
--- a/sys/ufs/ufs/ufs_extern.h
+++ b/sys/ufs/ufs/ufs_extern.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_extern.h,v 1.85 2020/04/18 19:18:34 christos Exp $ */
+/* $NetBSD: ufs_extern.h,v 1.86 2020/05/16 18:31:54 christos Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@@ -61,7 +61,7 @@ extern pool_cache_t ufs_direct_cache; /* memory pool for directs */
__BEGIN_DECLS
#define ufs_abortop genfs_abortop
-int ufs_access(void *);
+int ufs_accessx(void *);
int ufs_advlock(void *);
int ufs_bmap(void *);
int ufs_close(void *);
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index dfe08ad53fc..9c19a9f9f26 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_lookup.c,v 1.152 2020/04/04 20:49:31 ad Exp $ */
+/* $NetBSD: ufs_lookup.c,v 1.153 2020/05/16 18:31:54 christos Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c,v 1.152 2020/04/04 20:49:31 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c,v 1.153 2020/05/16 18:31:54 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_ffs.h"
@@ -211,6 +211,38 @@ ufs_can_delete(struct vnode *tdp, struct vnode *vdp, struct inode *ip,
kauth_cred_t cred)
{
int error;
+
+#ifdef UFS_ACL
+ /*
+ * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt
+ *
+ * 3.16.2.1. ACE4_DELETE vs. ACE4_DELETE_CHILD
+ */
+
+ /*
+ * XXX: Is this check required?
+ */
+ error = VOP_ACCESS(vdp, VEXEC, cred);
+ if (error)
+ goto out;
+
+#if 0
+ /* Moved to ufs_remove, ufs_rmdir because they hold the lock */
+ error = VOP_ACCESSX(tdp, VDELETE, cred);
+ if (error == 0)
+ return (0);
+#endif
+
+ error = VOP_ACCESSX(vdp, VDELETE_CHILD, cred);
+ if (error == 0)
+ return (0);
+
+ error = VOP_ACCESSX(vdp, VEXPLICIT_DENY | VDELETE_CHILD, cred);
+ if (error)
+ goto out;
+
+#endif /* !UFS_ACL */
+
/*
* Write access to directory required to delete files.
*/
@@ -228,7 +260,7 @@ ufs_can_delete(struct vnode *tdp, struct vnode *vdp, struct inode *ip,
* implements append-only directories.
*/
error = kauth_authorize_vnode(cred, KAUTH_VNODE_DELETE, tdp, vdp,
- genfs_can_sticky(cred, ip->i_uid, VTOI(tdp)->i_uid));
+ genfs_can_sticky(vdp, cred, ip->i_uid, VTOI(tdp)->i_uid));
if (error) {
error = EPERM; // Why override?
goto out;
@@ -590,7 +622,10 @@ notfound:
* Access for write is interpreted as allowing
* creation of files in the directory.
*/
- error = VOP_ACCESS(vdp, VWRITE, cred);
+ if (flags & WILLBEDIR)
+ error = VOP_ACCESSX(vdp, VWRITE | VAPPEND, cred);
+ else
+ error = VOP_ACCESS(vdp, VWRITE, cred);
if (error)
goto out;
error = slot_estimate(&slot, dirblksiz, nameiop,
@@ -675,7 +710,11 @@ found:
* regular file, or empty directory.
*/
if (nameiop == RENAME && (flags & ISLASTCN)) {
- if ((error = VOP_ACCESS(vdp, VWRITE, cred)) != 0)
+ if (flags & WILLBEDIR)
+ error = VOP_ACCESSX(vdp, VWRITE | VAPPEND, cred);
+ else
+ error = VOP_ACCESS(vdp, VWRITE, cred);
+ if (error)
goto out;
/*
* Careful about locking second inode.
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 34ac4e22cf6..0b0d8942eb3 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_vnops.c,v 1.253 2020/05/12 23:17:41 ad Exp $ */
+/* $NetBSD: ufs_vnops.c,v 1.254 2020/05/16 18:31:54 christos Exp $ */
/*-
* Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.253 2020/05/12 23:17:41 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.254 2020/05/16 18:31:54 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -95,6 +95,7 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.253 2020/05/12 23:17:41 ad Exp $");
#include <miscfs/fifofs/fifo.h>
#include <miscfs/genfs/genfs.h>
+#include <ufs/ufs/acl.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ufs/ufsmount.h>
@@ -256,7 +257,7 @@ ufs_close(void *v)
}
static int
-ufs_check_possible(struct vnode *vp, struct inode *ip, mode_t mode,
+ufs_check_possible(struct vnode *vp, struct inode *ip, accmode_t accmode,
kauth_cred_t cred)
{
#if defined(QUOTA) || defined(QUOTA2)
@@ -268,13 +269,13 @@ ufs_check_possible(struct vnode *vp, struct inode *ip, mode_t mode,
* unless the file is a socket, fifo, or a block or
* character device resident on the file system.
*/
- if (mode & VWRITE) {
+ if (accmode & VMODIFY_PERMS) {
switch (vp->v_type) {
case VDIR:
case VLNK:
case VREG:
if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
+ return EROFS;
#if defined(QUOTA) || defined(QUOTA2)
error = chkdq(ip, 0, cred, 0);
if (error != 0)
@@ -294,48 +295,94 @@ ufs_check_possible(struct vnode *vp, struct inode *ip, mode_t mode,
/* If it is a snapshot, nobody gets access to it. */
if ((ip->i_flags & SF_SNAPSHOT))
- return (EPERM);
- /* If immutable bit set, nobody gets to write it. */
- if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE))
- return (EPERM);
+ return EPERM;
+ /*
+ * If immutable bit set, nobody gets to write it. "& ~VADMIN_PERMS"
+ * permits the owner of the file to remove the IMMUTABLE flag.
+ */
+ if ((accmode & (VMODIFY_PERMS & ~VADMIN_PERMS)) &&
+ (ip->i_flags & IMMUTABLE))
+ return EPERM;
return 0;
}
static int
-ufs_check_permitted(struct vnode *vp, struct inode *ip, mode_t mode,
- kauth_cred_t cred)
+ufs_check_permitted(struct vnode *vp, struct inode *ip,
+ struct acl *acl, accmode_t accmode, kauth_cred_t cred,
+ int (*func)(struct vnode *, kauth_cred_t, uid_t, gid_t, mode_t,
+ struct acl *, accmode_t))
{
- return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, vp->v_type,
- ip->i_mode & ALLPERMS), vp, NULL, genfs_can_access(vp->v_type,
- ip->i_mode & ALLPERMS, ip->i_uid, ip->i_gid, mode, cred));
+ return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
+ vp->v_type, ip->i_mode & ALLPERMS), vp, NULL, (*func)(vp, cred,
+ ip->i_uid, ip->i_gid, ip->i_mode & ALLPERMS, acl, accmode));
}
int
-ufs_access(void *v)
+ufs_accessx(void *v)
{
- struct vop_access_args /* {
- struct vnode *a_vp;
- int a_mode;
- kauth_cred_t a_cred;
+ struct vop_accessx_args /* {
+ struct vnode *a_vp;
+ accmode_t a_accmode;
+ kauth_cred_t a_cred;
} */ *ap = v;
- struct vnode *vp;
- struct inode *ip;
- mode_t mode;
- int error;
-
- vp = ap->a_vp;
- ip = VTOI(vp);
- mode = ap->a_mode;
+ struct vnode *vp = ap->a_vp;
+ struct inode *ip = VTOI(vp);
+ accmode_t accmode = ap->a_accmode;
+ int error;
+#ifdef UFS_ACL
+ struct acl *acl;
+ acl_type_t type;
+#endif
- error = ufs_check_possible(vp, ip, mode, ap->a_cred);
+ error = ufs_check_possible(vp, ip, accmode, ap->a_cred);
if (error)
return error;
- error = ufs_check_permitted(vp, ip, mode, ap->a_cred);
+#ifdef UFS_ACL
+ if ((vp->v_mount->mnt_flag & (MNT_POSIX1EACLS | MNT_ACLS)) != 0) {
+ if (vp->v_mount->mnt_flag & MNT_ACLS)
+ type = ACL_TYPE_NFS4;
+ else
+ type = ACL_TYPE_ACCESS;
- return error;
+ acl = acl_alloc(KM_SLEEP);
+ if (type == ACL_TYPE_NFS4)
+ error = ufs_getacl_nfs4_internal(vp, acl, curlwp);
+ else
+ error = VOP_GETACL(vp, type, acl, ap->a_cred);
+ if (!error) {
+ if (type == ACL_TYPE_NFS4) {
+ error = ufs_check_permitted(vp,
+ ip, acl, accmode, ap->a_cred,
+ genfs_can_access_acl_nfs4);
+ } else {
+ error = vfs_unixify_accmode(&accmode);
+ if (error == 0)
+ error = ufs_check_permitted(vp,
+ ip, acl, accmode, ap->a_cred,
+ genfs_can_access_acl_posix1e);
+ }
+ acl_free(acl);
+ return error;
+ }
+ if (error != EOPNOTSUPP)
+ printf("%s: Error retrieving ACL: %d\n",
+ __func__, error);
+ /*
+ * XXX: Fall back until debugged. Should
+ * eventually possibly log an error, and return
+ * EPERM for safety.
+ */
+ acl_free(acl);
+ }
+#endif /* !UFS_ACL */
+ error = vfs_unixify_accmode(&accmode);
+ if (error)
+ return error;
+ return ufs_check_permitted(vp, ip,
+ NULL, accmode, ap->a_cred, genfs_can_access);
}
/* ARGSUSED */
@@ -486,8 +533,7 @@ ufs_setattr(void *v)
}
error = kauth_authorize_vnode(cred, action, vp, NULL,
- genfs_can_chflags(cred, vp->v_type, ip->i_uid,
- changing_sysflags));
+ genfs_can_chflags(vp, cred, ip->i_uid, changing_sysflags));
if (error)
goto out;
@@ -577,7 +623,8 @@ ufs_setattr(void *v)
goto out;
}
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
- NULL, genfs_can_chtimes(vp, vap->va_vaflags, ip->i_uid, cred));
+ NULL, genfs_can_chtimes(vp, cred, ip->i_uid,
+ vap->va_vaflags));
if (error)
goto out;
error = UFS_WAPBL_BEGIN(vp->v_mount);
@@ -625,6 +672,32 @@ out:
return (error);
}
+#ifdef UFS_ACL
+static int
+ufs_update_nfs4_acl_after_mode_change(struct vnode *vp, int mode,
+ int file_owner_id, kauth_cred_t cred, struct lwp *l)
+{
+ int error;
+ struct acl *aclp;
+
+ aclp = acl_alloc(KM_SLEEP);
+ error = ufs_getacl_nfs4_internal(vp, aclp, l);
+ /*
+ * We don't have to handle EOPNOTSUPP here, as the filesystem claims
+ * it supports ACLs.
+ */
+ if (error)
+ goto out;
+
+ acl_nfs4_sync_acl_from_mode(aclp, mode, file_owner_id);
+ error = ufs_setacl_nfs4_internal(vp, aclp, l, false);
+
+out:
+ acl_free(aclp);
+ return (error);
+}
+#endif /* UFS_ACL */
+
/*
* Change the mode on a file.
* Inode must be locked before calling.
@@ -639,11 +712,28 @@ ufs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct lwp *l)
ip = VTOI(vp);
+#ifdef UFS_ACL
+ /*
+ * To modify the permissions on a file, must possess VADMIN
+ * for that file.
+ */
+ if ((error = VOP_ACCESSX(vp, VWRITE_ACL, cred)) != 0)
+ return error;
+#endif
+
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp,
- NULL, genfs_can_chmod(vp->v_type, cred, ip->i_uid, ip->i_gid, mode));
+ NULL, genfs_can_chmod(vp, cred, ip->i_uid, ip->i_gid, mode));
if (error)
return (error);
+#ifdef UFS_ACL
+ if ((vp->v_mount->mnt_flag & MNT_ACLS) != 0) {
+ error = ufs_update_nfs4_acl_after_mode_change(vp, mode,
+ ip->i_uid, cred, l);
+ if (error)
+ return error;
+ }
+#endif
ip->i_mode &= ~ALLPERMS;
ip->i_mode |= (mode & ALLPERMS);
ip->i_flag |= IN_CHANGE;
@@ -676,8 +766,17 @@ ufs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred,
if (gid == (gid_t)VNOVAL)
gid = ip->i_gid;
+#ifdef UFS_ACL
+ /*
+ * To modify the ownership of a file, must possess VADMIN for that
+ * file.
+ */
+ if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred)) != 0)
+ return error;
+#endif
+
error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp,
- NULL, genfs_can_chown(cred, ip->i_uid, ip->i_gid, uid, gid));
+ NULL, genfs_can_chown(vp, cred, ip->i_uid, ip->i_gid, uid, gid));
if (error)
return (error);
@@ -734,6 +833,17 @@ ufs_remove(void *v)
mp = dvp->v_mount;
KASSERT(mp == vp->v_mount); /* XXX Not stable without lock. */
+#ifdef UFS_ACL
+#ifdef notyet
+ /* We don't do this because if the filesystem is mounted without ACLs
+ * this goes through vfs_unixify_accmode() and we get EPERM.
+ */
+ error = VOP_ACCESSX(vp, VDELETE, ap->a_cnp->cn_cred);
+ if (error)
+ goto err;
+#endif
+#endif
+
/* XXX should handle this material another way */
ulr = &VTOI(dvp)->i_crap;
UFS_CHECK_CRAPCOUNTER(VTOI(dvp));
@@ -751,6 +861,9 @@ ufs_remove(void *v)
}
VN_KNOTE(vp, NOTE_DELETE);
VN_KNOTE(dvp, NOTE_WRITE);
+#ifdef notyet
+err:
+#endif
if (dvp == vp)
vrele(vp);
else
@@ -906,6 +1019,193 @@ ufs_whiteout(void *v)
return (error);
}
+#ifdef UFS_ACL
+static int
+ufs_do_posix1e_acl_inheritance_dir(struct vnode *dvp, struct vnode *tvp,
+ mode_t dmode, kauth_cred_t cred, struct lwp *l)
+{
+ int error;
+ struct inode *ip = VTOI(tvp);
+ struct acl *dacl, *acl;
+
+ acl = acl_alloc(KM_SLEEP);
+ dacl = acl_alloc(KM_SLEEP);
+
+ /*
+ * Retrieve default ACL from parent, if any.
+ */
+ error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred);
+ switch (error) {
+ case 0:
+ /*
+ * Retrieved a default ACL, so merge mode and ACL if
+ * necessary. If the ACL is empty, fall through to
+ * the "not defined or available" case.
+ */
+ if (acl->acl_cnt != 0) {
+ dmode = acl_posix1e_newfilemode(dmode, acl);
+ ip->i_mode = dmode;
+ DIP_ASSIGN(ip, mode, dmode);
+ *dacl = *acl;
+ ufs_sync_acl_from_inode(ip, acl);
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case EOPNOTSUPP:
+ /*
+ * Just use the mode as-is.
+ */
+ ip->i_mode = dmode;
+ DIP_ASSIGN(ip, mode, dmode);
+ error = 0;
+ goto out;
+
+ default:
+ goto out;
+ }
+
+ /*
+ * XXX: If we abort now, will Soft Updates notify the extattr
+ * code that the EAs for the file need to be released?
+ */
+ UFS_WAPBL_END(tvp->v_mount);
+ error = ufs_setacl_posix1e(tvp, ACL_TYPE_ACCESS, acl, cred, l);
+ if (error == 0)
+ error = ufs_setacl_posix1e(tvp, ACL_TYPE_DEFAULT, dacl, cred,
+ l);
+ UFS_WAPBL_BEGIN(tvp->v_mount);
+ switch (error) {
+ case 0:
+ break;
+
+ case EOPNOTSUPP:
+ /*
+ * XXX: This should not happen, as EOPNOTSUPP above
+ * was supposed to free acl.
+ */
+ printf("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()\n");
+ /*
+ panic("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()");
+ */
+ break;
+
+ default:
+ goto out;
+ }
+
+out:
+ acl_free(acl);
+ acl_free(dacl);
+
+ return (error);
+}
+
+static int
+ufs_do_posix1e_acl_inheritance_file(struct vnode *dvp, struct vnode *tvp,
+ mode_t mode, kauth_cred_t cred, struct lwp *l)
+{
+ int error;
+ struct inode *ip = VTOI(tvp);
+ struct acl *acl;
+
+ acl = acl_alloc(KM_SLEEP);
+
+ /*
+ * Retrieve default ACL for parent, if any.
+ */
+ error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred);
+ switch (error) {
+ case 0:
+ /*
+ * Retrieved a default ACL, so merge mode and ACL if
+ * necessary.
+ */
+ if (acl->acl_cnt != 0) {
+ /*
+ * Two possible ways for default ACL to not
+ * be present. First, the EA can be
+ * undefined, or second, the default ACL can
+ * be blank. If it's blank, fall through to
+ * the it's not defined case.
+ */
+ mode = acl_posix1e_newfilemode(mode, acl);
+ ip->i_mode = mode;
+ DIP_ASSIGN(ip, mode, mode);
+ ufs_sync_acl_from_inode(ip, acl);
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case EOPNOTSUPP:
+ /*
+ * Just use the mode as-is.
+ */
+ ip->i_mode = mode;
+ DIP_ASSIGN(ip, mode, mode);
+ error = 0;
+ goto out;
+
+ default:
+ goto out;
+ }
+
+ UFS_WAPBL_END(tvp->v_mount);
+ /*
+ * XXX: If we abort now, will Soft Updates notify the extattr
+ * code that the EAs for the file need to be released?
+ */
+ error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cred);
+ UFS_WAPBL_BEGIN(tvp->v_mount);
+ switch (error) {
+ case 0:
+ break;
+
+ case EOPNOTSUPP:
+ /*
+ * XXX: This should not happen, as EOPNOTSUPP above was
+ * supposed to free acl.
+ */
+ printf("%s: VOP_GETACL() but no VOP_SETACL()\n", __func__);
+ /* panic("%s: VOP_GETACL() but no VOP_SETACL()", __func__); */
+ break;
+
+ default:
+ goto out;
+ }
+
+out:
+ acl_free(acl);
+
+ return (error);
+}
+
+static int
+ufs_do_nfs4_acl_inheritance(struct vnode *dvp, struct vnode *tvp,
+ mode_t child_mode, kauth_cred_t cred, struct lwp *l)
+{
+ int error;
+ struct acl *parent_aclp, *child_aclp;
+
+ parent_aclp = acl_alloc(KM_SLEEP);
+ child_aclp = acl_alloc(KM_SLEEP);
+
+ error = ufs_getacl_nfs4_internal(dvp, parent_aclp, l);
+ if (error)
+ goto out;
+ acl_nfs4_compute_inherited_acl(parent_aclp, child_aclp,
+ child_mode, VTOI(tvp)->i_uid, tvp->v_type == VDIR);
+ error = ufs_setacl_nfs4_internal(tvp, child_aclp, l, false);
+ if (error)
+ goto out;
+out:
+ acl_free(parent_aclp);
+ acl_free(child_aclp);
+
+ return (error);
+}
+#endif
+
int
ufs_mkdir(void *v)
{
@@ -979,6 +1279,23 @@ ufs_mkdir(void *v)
if ((error = UFS_UPDATE(dvp, NULL, NULL, UPDATE_DIROP)) != 0)
goto bad;
+#ifdef UFS_ACL
+ mode_t dmode = (vap->va_mode & 0777) | IFDIR;
+ struct lwp *l = curlwp;
+ if (dvp->v_mount->mnt_flag & MNT_POSIX1EACLS) {
+
+ error = ufs_do_posix1e_acl_inheritance_dir(dvp, tvp, dmode,
+ cnp->cn_cred, l);
+ if (error)
+ goto bad;
+ } else if (dvp->v_mount->mnt_flag & MNT_ACLS) {
+ error = ufs_do_nfs4_acl_inheritance(dvp, tvp, dmode,
+ cnp->cn_cred, l);
+ if (error)
+ goto bad;
+ }
+#endif /* !UFS_ACL */
+
/*
* Initialize directory with "." and ".." from static template.
*/
@@ -1071,6 +1388,17 @@ ufs_rmdir(void *v)
ip = VTOI(vp);
dp = VTOI(dvp);
+#ifdef UFS_ACL
+#ifdef notyet
+ /* We don't do this because if the filesystem is mounted without ACLs
+ * this goes through vfs_unixify_accmode() and we get EPERM.
+ */
+ error = VOP_ACCESSX(vp, VDELETE, cnp->cn_cred);
+ if (error)
+ goto err;
+#endif
+#endif
+
/* XXX should handle this material another way */
ulr = &dp->i_crap;
UFS_CHECK_CRAPCOUNTER(dp);
@@ -1079,11 +1407,8 @@ ufs_rmdir(void *v)
* No rmdir "." or of mounted directories please.
*/
if (dp == ip || vp->v_mountedhere != NULL) {
- if (dp == ip)
- vrele(vp);
- else
- vput(vp);
- return (EINVAL);
+ error = EINVAL;
+ goto err;
}
/*
@@ -1144,7 +1469,13 @@ ufs_rmdir(void *v)
out:
VN_KNOTE(vp, NOTE_DELETE);
vput(vp);
- return (error);
+ return error;
+ err:
+ if (dp == ip)
+ vrele(vp);
+ else
+ vput(vp);
+ return error;
}
/*
@@ -1766,6 +2097,30 @@ ufs_pathconf(void *v)
case _PC_NO_TRUNC:
*ap->a_retval = 1;
return (0);
+#ifdef UFS_ACL
+ case _PC_ACL_EXTENDED:
+ if (ap->a_vp->v_mount->mnt_flag & MNT_POSIX1EACLS)
+ *ap->a_retval = 1;
+ else
+ *ap->a_retval = 0;
+ return 0;
+ case _PC_ACL_NFS4:
+ if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS)
+ *ap->a_retval = 1;
+ else
+ *ap->a_retval = 0;
+ return 0;
+#endif
+ case _PC_ACL_PATH_MAX:
+#ifdef UFS_ACL
+ if (ap->a_vp->v_mount->mnt_flag & (MNT_POSIX1EACLS | MNT_ACLS))
+ *ap->a_retval = ACL_MAX_ENTRIES;
+ else
+ *ap->a_retval = 3;
+#else
+ *ap->a_retval = 3;
+#endif
+ return 0;
case _PC_SYNC_IO:
*ap->a_retval = 1;
return (0);
@@ -1890,8 +2245,9 @@ ufs_makeinode(struct vattr *vap, struct vnode *dvp,
/* Authorize setting SGID if needed. */
if (ip->i_mode & ISGID) {
- error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY,
- tvp, NULL, genfs_can_chmod(tvp->v_type, cnp->cn_cred, ip->i_uid,
+ error = kauth_authorize_vnode(cnp->cn_cred,
+ KAUTH_VNODE_WRITE_SECURITY,
+ tvp, NULL, genfs_can_chmod(tvp, cnp->cn_cred, ip->i_uid,
ip->i_gid, MAKEIMODE(vap->va_type, vap->va_mode)));
if (error) {
ip->i_mode &= ~ISGID;
@@ -1909,6 +2265,20 @@ ufs_makeinode(struct vattr *vap, struct vnode *dvp,
*/
if ((error = UFS_UPDATE(tvp, NULL, NULL, UPDATE_DIROP)) != 0)
goto bad;
+#ifdef UFS_ACL
+ struct lwp *l = curlwp;
+ if (dvp->v_mount->mnt_flag & MNT_POSIX1EACLS) {
+ error = ufs_do_posix1e_acl_inheritance_file(dvp, tvp,
+ ip->i_mode, cnp->cn_cred, l);
+ if (error)
+ goto bad;
+ } else if (dvp->v_mount->mnt_flag & MNT_ACLS) {
+ error = ufs_do_nfs4_acl_inheritance(dvp, tvp, ip->i_mode,
+ cnp->cn_cred, l);
+ if (error)
+ goto bad;
+ }
+#endif /* !UFS_ACL */
newdir = pool_cache_get(ufs_direct_cache, PR_WAITOK);
ufs_makedirentry(ip, cnp, newdir);
error = ufs_direnter(dvp, ulr, tvp, newdir, cnp, NULL);