Index: bin/Makefile =================================================================== RCS file: /cvsroot/src/bin/Makefile,v retrieving revision 1.22 diff -u -p -u -p -r1.22 Makefile --- bin/Makefile 31 Dec 2007 15:31:24 -0000 1.22 +++ bin/Makefile 25 Apr 2020 01:05:50 -0000 @@ -1,8 +1,8 @@ # $NetBSD: Makefile,v 1.22 2007/12/31 15:31:24 ad 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 Index: bin/cp/cp.c =================================================================== RCS file: /cvsroot/src/bin/cp/cp.c,v retrieving revision 1.59 diff -u -p -u -p -r1.59 cp.c --- bin/cp/cp.c 5 Mar 2016 19:48:55 -0000 1.59 +++ bin/cp/cp.c 25 Apr 2020 01:05:51 -0000 @@ -499,9 +499,23 @@ copy(char *argv[], enum op type, int fts * 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); } Index: bin/cp/extern.h =================================================================== RCS file: /cvsroot/src/bin/cp/extern.h,v retrieving revision 1.17 diff -u -p -u -p -r1.17 extern.h --- bin/cp/extern.h 4 Jan 2012 15:58:37 -0000 1.17 +++ bin/cp/extern.h 25 Apr 2020 01:05:51 -0000 @@ -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 Index: bin/cp/utils.c =================================================================== RCS file: /cvsroot/src/bin/cp/utils.c,v retrieving revision 1.47 diff -u -p -u -p -r1.47 utils.c --- bin/cp/utils.c 23 Sep 2019 18:01:09 -0000 1.47 +++ bin/cp/utils.c 25 Apr 2020 01:05:51 -0000 @@ -38,10 +38,12 @@ __RCSID("$NetBSD: utils.c,v 1.47 2019/09 #endif #endif /* not lint */ +#define _ACL_PRIVATE #include #include #include #include +#include #include #include @@ -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) { Index: bin/getfacl/Makefile =================================================================== RCS file: bin/getfacl/Makefile diff -N bin/getfacl/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/getfacl/Makefile 25 Apr 2020 01:05:51 -0000 @@ -0,0 +1,6 @@ +# $NetBSD$ +# $FreeBSD: head/bin/getfacl/Makefile 298107 2016-04-16 07:45:30Z gjb $ + +PROG= getfacl + +.include Index: bin/getfacl/getfacl.1 =================================================================== RCS file: bin/getfacl/getfacl.1 diff -N bin/getfacl/getfacl.1 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/getfacl/getfacl.1 25 Apr 2020 01:05:51 -0000 @@ -0,0 +1,138 @@ +.\" $NetBSD$ +.\"- +.\" 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 Index: bin/getfacl/getfacl.c =================================================================== RCS file: bin/getfacl/getfacl.c diff -N bin/getfacl/getfacl.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/getfacl/getfacl.c 25 Apr 2020 01:05:51 -0000 @@ -0,0 +1,348 @@ +/* $NetBSD$ */ + +/*- + * 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 +#if 0 +__FBSDID("$FreeBSD: head/bin/getfacl/getfacl.c 340014 2018-11-01 17:45:29Z markj $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} Index: bin/ls/ls.1 =================================================================== RCS file: /cvsroot/src/bin/ls/ls.1,v retrieving revision 1.80 diff -u -p -u -p -r1.80 ls.1 --- bin/ls/ls.1 3 Jul 2017 21:33:23 -0000 1.80 +++ bin/ls/ls.1 25 Apr 2020 01:05:51 -0000 @@ -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 Index: bin/ls/print.c =================================================================== RCS file: /cvsroot/src/bin/ls/print.c,v retrieving revision 1.55 diff -u -p -u -p -r1.55 print.c --- bin/ls/print.c 10 May 2014 09:39:18 -0000 1.55 +++ bin/ls/print.c 25 Apr 2020 01:05:51 -0000 @@ -43,6 +43,7 @@ __RCSID("$NetBSD: print.c,v 1.55 2014/05 #include #include +#include #include #include @@ -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 (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); +} Index: bin/setfacl/Makefile =================================================================== RCS file: bin/setfacl/Makefile diff -N bin/setfacl/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/setfacl/Makefile 25 Apr 2020 01:05:51 -0000 @@ -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 Index: bin/setfacl/file.c =================================================================== RCS file: bin/setfacl/file.c diff -N bin/setfacl/file.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/setfacl/file.c 25 Apr 2020 01:05:51 -0000 @@ -0,0 +1,82 @@ +/* $NetBSD$ */ + +/*- + * 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 +#if 0 +__FBSDID("$FreeBSD: head/bin/setfacl/file.c 333065 2018-04-27 15:25:24Z emaste $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include + +#include +#include +#include + +#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)); +} Index: bin/setfacl/mask.c =================================================================== RCS file: bin/setfacl/mask.c diff -N bin/setfacl/mask.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/setfacl/mask.c 25 Apr 2020 01:05:51 -0000 @@ -0,0 +1,120 @@ +/* $NetBSD$ */ + +/*- + * 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 +#if 0 +__FBSDID("$FreeBSD: head/bin/setfacl/mask.c 333065 2018-04-27 15:25:24Z emaste $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#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); +} Index: bin/setfacl/merge.c =================================================================== RCS file: bin/setfacl/merge.c diff -N bin/setfacl/merge.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/setfacl/merge.c 25 Apr 2020 01:05:51 -0000 @@ -0,0 +1,299 @@ +/* $NetBSD$ */ + +/*- + * 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 +#if 0 +__FBSDID("$FreeBSD: head/bin/setfacl/merge.c 333065 2018-04-27 15:25:24Z emaste $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include + +#include +#include + +#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); +} Index: bin/setfacl/remove.c =================================================================== RCS file: bin/setfacl/remove.c diff -N bin/setfacl/remove.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/setfacl/remove.c 25 Apr 2020 01:05:51 -0000 @@ -0,0 +1,179 @@ +/* $NetBSD$ */ + +/*- + * 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 +#if 0 +__FBSDID("$FreeBSD: head/bin/setfacl/remove.c 333065 2018-04-27 15:25:24Z emaste $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include + +#include +#include +#include + +#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; +} Index: bin/setfacl/setfacl.1 =================================================================== RCS file: bin/setfacl/setfacl.1 diff -N bin/setfacl/setfacl.1 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/setfacl/setfacl.1 25 Apr 2020 01:05:51 -0000 @@ -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 . Index: bin/setfacl/setfacl.c =================================================================== RCS file: bin/setfacl/setfacl.c diff -N bin/setfacl/setfacl.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/setfacl/setfacl.c 25 Apr 2020 01:05:51 -0000 @@ -0,0 +1,511 @@ +/* $NetBSD$ */ + +/*- + * 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 +#if 0 +__FBSDID("$FreeBSD: head/bin/setfacl/setfacl.c 339793 2018-10-26 21:17:06Z markj $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} Index: bin/setfacl/setfacl.h =================================================================== RCS file: bin/setfacl/setfacl.h diff -N bin/setfacl/setfacl.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/setfacl/setfacl.h 25 Apr 2020 01:05:51 -0000 @@ -0,0 +1,64 @@ +/* $NetBSD$ */ + +/*- + * 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 + +#include +#include +#include + +/* 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 */ Index: bin/setfacl/util.c =================================================================== RCS file: bin/setfacl/util.c diff -N bin/setfacl/util.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ bin/setfacl/util.c 25 Apr 2020 01:05:51 -0000 @@ -0,0 +1,85 @@ +/* $NetBSD$ */ + +/*- + * 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 +#if 0 +__FBSDID("$FreeBSD: head/bin/setfacl/util.c 332396 2018-04-10 23:29:57Z emaste $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include + +#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); +} Index: distrib/sets/lists/base/mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/base/mi,v retrieving revision 1.1240 diff -u -p -u -p -r1.1240 mi --- distrib/sets/lists/base/mi 14 Apr 2020 03:16:26 -0000 1.1240 +++ distrib/sets/lists/base/mi 25 Apr 2020 01:06:17 -0000 @@ -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 Index: distrib/sets/lists/base/shl.mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/base/shl.mi,v retrieving revision 1.884 diff -u -p -u -p -r1.884 shl.mi --- distrib/sets/lists/base/shl.mi 4 Apr 2020 19:26:51 -0000 1.884 +++ distrib/sets/lists/base/shl.mi 25 Apr 2020 01:06:17 -0000 @@ -21,7 +21,7 @@ ./lib/libblacklist.so.0.0 base-sys-shlib dynamicroot ./lib/libc.so base-sys-shlib dynamicroot ./lib/libc.so.12 base-sys-shlib dynamicroot -./lib/libc.so.12.215 base-sys-shlib dynamicroot +./lib/libc.so.12.216 base-sys-shlib dynamicroot ./lib/libcrypt.so base-sys-shlib dynamicroot ./lib/libcrypt.so.1 base-sys-shlib dynamicroot ./lib/libcrypt.so.1.0 base-sys-shlib dynamicroot @@ -249,7 +249,7 @@ ./usr/lib/libc++.so.1.0 base-sys-shlib compatfile,libcxx ./usr/lib/libc.so base-sys-shlib compatfile ./usr/lib/libc.so.12 base-sys-shlib compatfile -./usr/lib/libc.so.12.215 base-sys-shlib compatfile +./usr/lib/libc.so.12.216 base-sys-shlib compatfile ./usr/lib/libcbor.so base-sys-shlib compatfile ./usr/lib/libcbor.so.0 base-sys-shlib compatfile ./usr/lib/libcbor.so.0.5 base-sys-shlib compatfile Index: distrib/sets/lists/comp/mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/comp/mi,v retrieving revision 1.2321 diff -u -p -u -p -r1.2321 mi --- distrib/sets/lists/comp/mi 4 Apr 2020 19:26:51 -0000 1.2321 +++ distrib/sets/lists/comp/mi 25 Apr 2020 01:06:20 -0000 @@ -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 @@ -3492,10 +3493,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 @@ -5558,6 +5559,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 @@ -8868,6 +8921,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 @@ -13645,6 +13699,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 @@ -16896,6 +17002,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 @@ -21569,6 +21676,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 @@ -24914,6 +25073,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 @@ -26475,8 +26635,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 Index: distrib/sets/lists/debug/mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/debug/mi,v retrieving revision 1.306 diff -u -p -u -p -r1.306 mi --- distrib/sets/lists/debug/mi 11 Apr 2020 01:51:14 -0000 1.306 +++ distrib/sets/lists/debug/mi 25 Apr 2020 01:06:20 -0000 @@ -286,6 +286,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 @@ -302,6 +303,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 Index: distrib/sets/lists/debug/shl.mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/debug/shl.mi,v retrieving revision 1.245 diff -u -p -u -p -r1.245 shl.mi --- distrib/sets/lists/debug/shl.mi 4 Apr 2020 19:26:51 -0000 1.245 +++ distrib/sets/lists/debug/shl.mi 25 Apr 2020 01:06:20 -0000 @@ -3,7 +3,7 @@ ./usr/libdata/debug/lib base-sys-usr debug,dynamicroot,compatdir ./usr/libdata/debug/lib/libavl.so.0.0.debug comp-zfs-debug debug,dynamicroot,zfs ./usr/libdata/debug/lib/libblacklist.so.0.0.debug comp-sys-debug debug,dynamicroot -./usr/libdata/debug/lib/libc.so.12.215.debug comp-sys-debug debug,dynamicroot +./usr/libdata/debug/lib/libc.so.12.216.debug comp-sys-debug debug,dynamicroot ./usr/libdata/debug/lib/libcrypt.so.1.0.debug comp-sys-debug debug,dynamicroot ./usr/libdata/debug/lib/libcrypto.so.12.0.debug comp-sys-debug debug,dynamicroot,openssl=10 ./usr/libdata/debug/lib/libcrypto.so.14.0.debug comp-sys-debug debug,dynamicroot,openssl=11 @@ -82,7 +82,7 @@ ./usr/libdata/debug/usr/lib/libbsdmalloc.so.0.0.debug comp-sys-debug debug,compatfile ./usr/libdata/debug/usr/lib/libbz2.so.1.1.debug comp-sys-debug debug,compatfile ./usr/libdata/debug/usr/lib/libc++.so.1.0.debug comp-sys-debug debug,compatfile,libcxx -./usr/libdata/debug/usr/lib/libc.so.12.215.debug comp-sys-debug debug,compatfile +./usr/libdata/debug/usr/lib/libc.so.12.216.debug comp-sys-debug debug,compatfile ./usr/libdata/debug/usr/lib/libcbor.so.0.5.debug comp-sys-debug debug,compatfile ./usr/libdata/debug/usr/lib/libcom_err.so.8.0.debug comp-krb5-debug debug,compatfile,kerberos ./usr/libdata/debug/usr/lib/libcrypt.so.1.0.debug comp-sys-debug debug,compatfile Index: distrib/sets/lists/man/mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/man/mi,v retrieving revision 1.1687 diff -u -p -u -p -r1.1687 mi --- distrib/sets/lists/man/mi 12 Apr 2020 01:10:53 -0000 1.1687 +++ distrib/sets/lists/man/mi 25 Apr 2020 01:06:21 -0000 @@ -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 Index: external/bsd/libarchive/include/config_netbsd.h =================================================================== RCS file: /cvsroot/src/external/bsd/libarchive/include/config_netbsd.h,v retrieving revision 1.11 diff -u -p -u -p -r1.11 config_netbsd.h --- external/bsd/libarchive/include/config_netbsd.h 24 Oct 2019 18:17:14 -0000 1.11 +++ external/bsd/libarchive/include/config_netbsd.h 25 Apr 2020 01:06:57 -0000 @@ -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 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 header file. */ #define HAVE_STDARG_H 1 @@ -1013,7 +1013,7 @@ #define HAVE_SYMLINK 1 /* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_ACL_H */ +#define HAVE_SYS_ACL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_CDEFS_H 1 Index: external/bsd/libarchive/lib/libarchive/Makefile =================================================================== RCS file: /cvsroot/src/external/bsd/libarchive/lib/libarchive/Makefile,v retrieving revision 1.11 diff -u -p -u -p -r1.11 Makefile --- external/bsd/libarchive/lib/libarchive/Makefile 13 Oct 2019 07:28:06 -0000 1.11 +++ external/bsd/libarchive/lib/libarchive/Makefile 25 Apr 2020 01:06:57 -0000 @@ -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 \ Index: external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c =================================================================== RCS file: /cvsroot/src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c,v retrieving revision 1.11 diff -u -p -u -p -r1.11 zfs_ctldir.c --- external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c 17 Jan 2020 20:08:06 -0000 1.11 +++ external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c 25 Apr 2020 01:07:29 -0000 @@ -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); Index: external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c =================================================================== RCS file: /cvsroot/src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c,v retrieving revision 1.64 diff -u -p -u -p -r1.64 zfs_vnops.c --- external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c 14 Mar 2020 20:45:23 -0000 1.64 +++ external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c 25 Apr 2020 01:07:29 -0000 @@ -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; @@ -6307,6 +6307,7 @@ const struct vnodeopv_entry_desc zfs_vno { &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 }, @@ -6352,6 +6353,7 @@ const struct vnodeopv_entry_desc zfs_spe { &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 }, @@ -6399,6 +6401,7 @@ const struct vnodeopv_entry_desc zfs_fif { &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 }, Index: external/cddl/osnet/sys/kern/policy.c =================================================================== RCS file: /cvsroot/src/external/cddl/osnet/sys/kern/policy.c,v retrieving revision 1.7 diff -u -p -u -p -r1.7 policy.c --- external/cddl/osnet/sys/kern/policy.c 28 May 2018 21:05:09 -0000 1.7 +++ external/cddl/osnet/sys/kern/policy.c 25 Apr 2020 01:07:30 -0000 @@ -177,7 +177,7 @@ secpolicy_vnode_owner(vnode_t *vp, cred_ 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); Index: external/cddl/osnet/sys/sys/policy.h =================================================================== RCS file: /cvsroot/src/external/cddl/osnet/sys/sys/policy.h,v retrieving revision 1.8 diff -u -p -u -p -r1.8 policy.h --- external/cddl/osnet/sys/sys/policy.h 28 May 2018 21:05:10 -0000 1.8 +++ external/cddl/osnet/sys/sys/policy.h 25 Apr 2020 01:07:30 -0000 @@ -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); Index: include/mntopts.h =================================================================== RCS file: /cvsroot/src/include/mntopts.h,v retrieving revision 1.18 diff -u -p -u -p -r1.18 mntopts.h --- include/mntopts.h 9 Jan 2018 03:31:12 -0000 1.18 +++ include/mntopts.h 25 Apr 2020 01:08:37 -0000 @@ -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 } Index: include/unistd.h =================================================================== RCS file: /cvsroot/src/include/unistd.h,v retrieving revision 1.156 diff -u -p -u -p -r1.156 unistd.h --- include/unistd.h 31 Mar 2020 16:50:31 -0000 1.156 +++ include/unistd.h 25 Apr 2020 01:08:37 -0000 @@ -360,6 +360,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); Index: lib/libc/Makefile =================================================================== RCS file: /cvsroot/src/lib/libc/Makefile,v retrieving revision 1.172 diff -u -p -u -p -r1.172 Makefile --- lib/libc/Makefile 3 Aug 2018 14:01:21 -0000 1.172 +++ lib/libc/Makefile 25 Apr 2020 01:08:38 -0000 @@ -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" Index: lib/libc/shlib_version =================================================================== RCS file: /cvsroot/src/lib/libc/shlib_version,v retrieving revision 1.286 diff -u -p -u -p -r1.286 shlib_version --- lib/libc/shlib_version 8 Mar 2020 22:27:38 -0000 1.286 +++ lib/libc/shlib_version 25 Apr 2020 01:08:38 -0000 @@ -54,4 +54,4 @@ # - move statfs() to libcompat since we have statvfs() # - the syscall stubs for the (obsolete) lfs syscalls should be removed major=12 -minor=215 +minor=216 Index: lib/libc/posix1e/Makefile.inc =================================================================== RCS file: lib/libc/posix1e/Makefile.inc diff -N lib/libc/posix1e/Makefile.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/Makefile.inc 25 Apr 2020 01:08:39 -0000 @@ -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 Index: lib/libc/posix1e/acl.3 =================================================================== RCS file: lib/libc/posix1e/acl.3 diff -N lib/libc/posix1e/acl.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl.3 25 Apr 2020 01:08:39 -0000 @@ -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 Index: lib/libc/posix1e/acl_add_flag_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_add_flag_np.3 diff -N lib/libc/posix1e/acl_add_flag_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_add_flag_np.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_add_perm.3 =================================================================== RCS file: lib/libc/posix1e/acl_add_perm.3 diff -N lib/libc/posix1e/acl_add_perm.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_add_perm.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_branding.c =================================================================== RCS file: lib/libc/posix1e/acl_branding.c diff -N lib/libc/posix1e/acl_branding.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_branding.c 25 Apr 2020 01:08:39 -0000 @@ -0,0 +1,175 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2008, 2009 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. + */ + +#include +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_branding.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include + +#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); +} Index: lib/libc/posix1e/acl_calc_mask.3 =================================================================== RCS file: lib/libc/posix1e/acl_calc_mask.3 diff -N lib/libc/posix1e/acl_calc_mask.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_calc_mask.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_calc_mask.c =================================================================== RCS file: lib/libc/posix1e/acl_calc_mask.c diff -N lib/libc/posix1e/acl_calc_mask.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_calc_mask.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_calc_mask.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" + +#include +#include + +#include +#include + +#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); +} Index: lib/libc/posix1e/acl_clear_flags_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_clear_flags_np.3 diff -N lib/libc/posix1e/acl_clear_flags_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_clear_flags_np.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_clear_perms.3 =================================================================== RCS file: lib/libc/posix1e/acl_clear_perms.3 diff -N lib/libc/posix1e/acl_clear_perms.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_clear_perms.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_compat.c =================================================================== RCS file: lib/libc/posix1e/acl_compat.c diff -N lib/libc/posix1e/acl_compat.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_compat.c 25 Apr 2020 01:08:39 -0000 @@ -0,0 +1,69 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2008 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. + */ + +#include +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_compat.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include + +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); Index: lib/libc/posix1e/acl_copy.c =================================================================== RCS file: lib/libc/posix1e/acl_copy.c diff -N lib/libc/posix1e/acl_copy.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_copy.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_copy.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include + +#include +#include + +#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); +} Index: lib/libc/posix1e/acl_copy_entry.3 =================================================================== RCS file: lib/libc/posix1e/acl_copy_entry.3 diff -N lib/libc/posix1e/acl_copy_entry.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_copy_entry.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_create_entry.3 =================================================================== RCS file: lib/libc/posix1e/acl_create_entry.3 diff -N lib/libc/posix1e/acl_create_entry.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_create_entry.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_delete.3 =================================================================== RCS file: lib/libc/posix1e/acl_delete.3 diff -N lib/libc/posix1e/acl_delete.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_delete.3 25 Apr 2020 01:08:39 -0000 @@ -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 Index: lib/libc/posix1e/acl_delete.c =================================================================== RCS file: lib/libc/posix1e/acl_delete.c diff -N lib/libc/posix1e/acl_delete.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_delete.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_delete.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include +#include + +#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)); +} Index: lib/libc/posix1e/acl_delete_entry.3 =================================================================== RCS file: lib/libc/posix1e/acl_delete_entry.3 diff -N lib/libc/posix1e/acl_delete_entry.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_delete_entry.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_delete_entry.c =================================================================== RCS file: lib/libc/posix1e/acl_delete_entry.c diff -N lib/libc/posix1e/acl_delete_entry.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_delete_entry.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_delete_entry.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include +#include +#include +#include + +#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); +} Index: lib/libc/posix1e/acl_delete_flag_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_delete_flag_np.3 diff -N lib/libc/posix1e/acl_delete_flag_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_delete_flag_np.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_delete_perm.3 =================================================================== RCS file: lib/libc/posix1e/acl_delete_perm.3 diff -N lib/libc/posix1e/acl_delete_perm.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_delete_perm.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_dup.3 =================================================================== RCS file: lib/libc/posix1e/acl_dup.3 diff -N lib/libc/posix1e/acl_dup.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_dup.3 25 Apr 2020 01:08:39 -0000 @@ -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 Index: lib/libc/posix1e/acl_entry.c =================================================================== RCS file: lib/libc/posix1e/acl_entry.c diff -N lib/libc/posix1e/acl_entry.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_entry.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_entry.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include + +#include +#include + +/* + * 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); +} Index: lib/libc/posix1e/acl_flag.c =================================================================== RCS file: lib/libc/posix1e/acl_flag.c diff -N lib/libc/posix1e/acl_flag.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_flag.c 25 Apr 2020 01:08:39 -0000 @@ -0,0 +1,161 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2008, 2009 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. + */ + +#include +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_flag.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include + +#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); +} Index: lib/libc/posix1e/acl_free.3 =================================================================== RCS file: lib/libc/posix1e/acl_free.3 diff -N lib/libc/posix1e/acl_free.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_free.3 25 Apr 2020 01:08:39 -0000 @@ -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 Index: lib/libc/posix1e/acl_free.c =================================================================== RCS file: lib/libc/posix1e/acl_free.c diff -N lib/libc/posix1e/acl_free.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_free.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_free.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include +#include +#include + +/* + * 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); +} Index: lib/libc/posix1e/acl_from_text.3 =================================================================== RCS file: lib/libc/posix1e/acl_from_text.3 diff -N lib/libc/posix1e/acl_from_text.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_from_text.3 25 Apr 2020 01:08:39 -0000 @@ -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. Index: lib/libc/posix1e/acl_from_text.c =================================================================== RCS file: lib/libc/posix1e/acl_from_text.c diff -N lib/libc/posix1e/acl_from_text.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_from_text.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_from_text.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(¬comment, ","))) { + + /* 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); + } +} Index: lib/libc/posix1e/acl_from_text_nfs4.c =================================================================== RCS file: lib/libc/posix1e/acl_from_text_nfs4.c diff -N lib/libc/posix1e/acl_from_text_nfs4.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_from_text_nfs4.c 25 Apr 2020 01:08:39 -0000 @@ -0,0 +1,289 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2008, 2009 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. + */ + +#include +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_from_text_nfs4.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} Index: lib/libc/posix1e/acl_get.3 =================================================================== RCS file: lib/libc/posix1e/acl_get.3 diff -N lib/libc/posix1e/acl_get.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_get.3 25 Apr 2020 01:08:39 -0000 @@ -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 Index: lib/libc/posix1e/acl_get.c =================================================================== RCS file: lib/libc/posix1e/acl_get.c diff -N lib/libc/posix1e/acl_get.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_get.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_get.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include + +#include +#include +#include +#include +#include + +#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); +} Index: lib/libc/posix1e/acl_get_brand_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_get_brand_np.3 diff -N lib/libc/posix1e/acl_get_brand_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_get_brand_np.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_get_entry.3 =================================================================== RCS file: lib/libc/posix1e/acl_get_entry.3 diff -N lib/libc/posix1e/acl_get_entry.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_get_entry.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_get_entry_type_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_get_entry_type_np.3 diff -N lib/libc/posix1e/acl_get_entry_type_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_get_entry_type_np.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_get_flag_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_get_flag_np.3 diff -N lib/libc/posix1e/acl_get_flag_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_get_flag_np.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_get_flagset_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_get_flagset_np.3 diff -N lib/libc/posix1e/acl_get_flagset_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_get_flagset_np.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_get_perm_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_get_perm_np.3 diff -N lib/libc/posix1e/acl_get_perm_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_get_perm_np.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_get_permset.3 =================================================================== RCS file: lib/libc/posix1e/acl_get_permset.3 diff -N lib/libc/posix1e/acl_get_permset.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_get_permset.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_get_qualifier.3 =================================================================== RCS file: lib/libc/posix1e/acl_get_qualifier.3 diff -N lib/libc/posix1e/acl_get_qualifier.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_get_qualifier.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_get_tag_type.3 =================================================================== RCS file: lib/libc/posix1e/acl_get_tag_type.3 diff -N lib/libc/posix1e/acl_get_tag_type.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_get_tag_type.3 25 Apr 2020 01:08:39 -0000 @@ -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 . Index: lib/libc/posix1e/acl_id_to_name.c =================================================================== RCS file: lib/libc/posix1e/acl_id_to_name.c diff -N lib/libc/posix1e/acl_id_to_name.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_id_to_name.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_id_to_name.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); + } +} Index: lib/libc/posix1e/acl_init.3 =================================================================== RCS file: lib/libc/posix1e/acl_init.3 diff -N lib/libc/posix1e/acl_init.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_init.3 25 Apr 2020 01:08:39 -0000 @@ -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 Index: lib/libc/posix1e/acl_init.c =================================================================== RCS file: lib/libc/posix1e/acl_init.c diff -N lib/libc/posix1e/acl_init.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_init.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_init.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include +#include +#include +#include +#include + +#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); +} Index: lib/libc/posix1e/acl_is_trivial_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_is_trivial_np.3 diff -N lib/libc/posix1e/acl_is_trivial_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_is_trivial_np.3 25 Apr 2020 01:08:39 -0000 @@ -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 Index: lib/libc/posix1e/acl_perm.c =================================================================== RCS file: lib/libc/posix1e/acl_perm.c diff -N lib/libc/posix1e/acl_perm.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_perm.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_perm.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include + +#include +#include + +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); +} Index: lib/libc/posix1e/acl_set.3 =================================================================== RCS file: lib/libc/posix1e/acl_set.3 diff -N lib/libc/posix1e/acl_set.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_set.3 25 Apr 2020 01:08:39 -0000 @@ -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 Index: lib/libc/posix1e/acl_set.c =================================================================== RCS file: lib/libc/posix1e/acl_set.c diff -N lib/libc/posix1e/acl_set.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_set.c 25 Apr 2020 01:08:39 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_set.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include + +#include +#include +#include +#include + +#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); +} Index: lib/libc/posix1e/acl_set_entry_type_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_set_entry_type_np.3 diff -N lib/libc/posix1e/acl_set_entry_type_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_set_entry_type_np.3 25 Apr 2020 01:08:40 -0000 @@ -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 . Index: lib/libc/posix1e/acl_set_flagset_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_set_flagset_np.3 diff -N lib/libc/posix1e/acl_set_flagset_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_set_flagset_np.3 25 Apr 2020 01:08:40 -0000 @@ -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 . Index: lib/libc/posix1e/acl_set_permset.3 =================================================================== RCS file: lib/libc/posix1e/acl_set_permset.3 diff -N lib/libc/posix1e/acl_set_permset.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_set_permset.3 25 Apr 2020 01:08:40 -0000 @@ -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 . Index: lib/libc/posix1e/acl_set_qualifier.3 =================================================================== RCS file: lib/libc/posix1e/acl_set_qualifier.3 diff -N lib/libc/posix1e/acl_set_qualifier.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_set_qualifier.3 25 Apr 2020 01:08:40 -0000 @@ -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 . Index: lib/libc/posix1e/acl_set_tag_type.3 =================================================================== RCS file: lib/libc/posix1e/acl_set_tag_type.3 diff -N lib/libc/posix1e/acl_set_tag_type.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_set_tag_type.3 25 Apr 2020 01:08:40 -0000 @@ -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 . Index: lib/libc/posix1e/acl_strip.c =================================================================== RCS file: lib/libc/posix1e/acl_strip.c diff -N lib/libc/posix1e/acl_strip.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_strip.c 25 Apr 2020 01:08:40 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_strip.c 344294 2019-02-19 19:15:15Z sef $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include +#include +#include + +#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); + } +} Index: lib/libc/posix1e/acl_strip_np.3 =================================================================== RCS file: lib/libc/posix1e/acl_strip_np.3 diff -N lib/libc/posix1e/acl_strip_np.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_strip_np.3 25 Apr 2020 01:08:40 -0000 @@ -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 Index: lib/libc/posix1e/acl_support.c =================================================================== RCS file: lib/libc/posix1e/acl_support.c diff -N lib/libc/posix1e/acl_support.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_support.c 25 Apr 2020 01:08:40 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_support.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} Index: lib/libc/posix1e/acl_support.h =================================================================== RCS file: lib/libc/posix1e/acl_support.h diff -N lib/libc/posix1e/acl_support.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_support.h 25 Apr 2020 01:08:40 -0000 @@ -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 Index: lib/libc/posix1e/acl_support_nfs4.c =================================================================== RCS file: lib/libc/posix1e/acl_support_nfs4.c diff -N lib/libc/posix1e/acl_support_nfs4.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_support_nfs4.c 25 Apr 2020 01:08:40 -0000 @@ -0,0 +1,267 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2008, 2009 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. + */ + +#include +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_support_nfs4.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include +#include +#include +#include +#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); +} Index: lib/libc/posix1e/acl_to_text.3 =================================================================== RCS file: lib/libc/posix1e/acl_to_text.3 diff -N lib/libc/posix1e/acl_to_text.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_to_text.3 25 Apr 2020 01:08:40 -0000 @@ -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. Index: lib/libc/posix1e/acl_to_text.c =================================================================== RCS file: lib/libc/posix1e/acl_to_text.c diff -N lib/libc/posix1e/acl_to_text.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_to_text.c 25 Apr 2020 01:08:40 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_to_text.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include +#include +#include +#include +#include + +#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)); +} Index: lib/libc/posix1e/acl_to_text_nfs4.c =================================================================== RCS file: lib/libc/posix1e/acl_to_text_nfs4.c diff -N lib/libc/posix1e/acl_to_text_nfs4.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_to_text_nfs4.c 25 Apr 2020 01:08:40 -0000 @@ -0,0 +1,271 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2008, 2009 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. + */ + +#include +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_to_text_nfs4.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} Index: lib/libc/posix1e/acl_valid.3 =================================================================== RCS file: lib/libc/posix1e/acl_valid.3 diff -N lib/libc/posix1e/acl_valid.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_valid.3 25 Apr 2020 01:08:40 -0000 @@ -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 Index: lib/libc/posix1e/acl_valid.c =================================================================== RCS file: lib/libc/posix1e/acl_valid.c diff -N lib/libc/posix1e/acl_valid.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/acl_valid.c 25 Apr 2020 01:08:40 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_valid.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include "namespace.h" +#include +#include +#include +#include + +#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)); +} Index: lib/libc/posix1e/extattr.3 =================================================================== RCS file: lib/libc/posix1e/extattr.3 diff -N lib/libc/posix1e/extattr.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/extattr.3 25 Apr 2020 01:08:40 -0000 @@ -0,0 +1,100 @@ +.\" +.\" Copyright (c) 2001 Dima Dorfman +.\" 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. Index: lib/libc/posix1e/extattr.c =================================================================== RCS file: lib/libc/posix1e/extattr.c diff -N lib/libc/posix1e/extattr.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/extattr.c 25 Apr 2020 01:08:40 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/lib/libc/posix1e/extattr.c 326193 2017-11-25 17:12:48Z pfg $"); +#else +__RCSID("$NetBSD$"); +#endif + +#include +#include + +#include +#include +#include + +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); + } +} Index: lib/libc/posix1e/posix1e.3 =================================================================== RCS file: lib/libc/posix1e/posix1e.3 diff -N lib/libc/posix1e/posix1e.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/posix1e/posix1e.3 25 Apr 2020 01:08:40 -0000 @@ -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 Index: lib/libc/sys/Makefile.inc =================================================================== RCS file: /cvsroot/src/lib/libc/sys/Makefile.inc,v retrieving revision 1.242 diff -u -p -u -p -r1.242 Makefile.inc --- lib/libc/sys/Makefile.inc 22 Sep 2019 22:59:38 -0000 1.242 +++ lib/libc/sys/Makefile.inc 25 Apr 2020 01:08:40 -0000 @@ -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 \ Index: lib/libc/sys/makelintstub =================================================================== RCS file: /cvsroot/src/lib/libc/sys/makelintstub,v retrieving revision 1.26 diff -u -p -u -p -r1.26 makelintstub --- lib/libc/sys/makelintstub 3 Apr 2016 00:48:29 -0000 1.26 +++ lib/libc/sys/makelintstub 25 Apr 2020 01:08:40 -0000 @@ -60,6 +60,7 @@ header() */ #include + #include #include #include #include Index: sbin/mount_ffs/mount_ffs.c =================================================================== RCS file: /cvsroot/src/sbin/mount_ffs/mount_ffs.c,v retrieving revision 1.28 diff -u -p -u -p -r1.28 mount_ffs.c --- sbin/mount_ffs/mount_ffs.c 19 Oct 2012 17:09:07 -0000 1.28 +++ sbin/mount_ffs/mount_ffs.c 25 Apr 2020 01:08:44 -0000 @@ -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, Index: sbin/tunefs/tunefs.8 =================================================================== RCS file: /cvsroot/src/sbin/tunefs/tunefs.8,v retrieving revision 1.44 diff -u -p -u -p -r1.44 tunefs.8 --- sbin/tunefs/tunefs.8 9 Aug 2014 10:41:05 -0000 1.44 +++ sbin/tunefs/tunefs.8 25 Apr 2020 01:08:44 -0000 @@ -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 POSIX.1e 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 @@ -120,6 +124,8 @@ threshold. Note that if the value is raised above the current usage level, users will be unable to allocate files until enough files have been deleted to get under the higher threshold. +.It Fl n Cm enable | disable +Turn on/off the administrative NFSv4 ACL enable flag. .It Fl o Ar optimize_preference The file system can either try to minimize the time spent allocating blocks, or it can attempt to minimize the space Index: sbin/tunefs/tunefs.c =================================================================== RCS file: /cvsroot/src/sbin/tunefs/tunefs.c,v retrieving revision 1.51 diff -u -p -u -p -r1.51 tunefs.c --- sbin/tunefs/tunefs.c 9 Apr 2020 14:44:38 -0000 1.51 +++ sbin/tunefs/tunefs.c 25 Apr 2020 01:08:44 -0000 @@ -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'"); 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'"); 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"); Index: sys/arch/amd64/amd64/genassym.cf =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/genassym.cf,v retrieving revision 1.82 diff -u -p -u -p -r1.82 genassym.cf --- sys/arch/amd64/amd64/genassym.cf 17 Feb 2020 09:09:48 -0000 1.82 +++ sys/arch/amd64/amd64/genassym.cf 25 Apr 2020 01:08:47 -0000 @@ -82,6 +82,7 @@ include include include include +include include include Index: sys/arch/amd64/conf/GENERIC =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/conf/GENERIC,v retrieving revision 1.565 diff -u -p -u -p -r1.565 GENERIC --- sys/arch/amd64/conf/GENERIC 15 Apr 2020 17:16:22 -0000 1.565 +++ sys/arch/amd64/conf/GENERIC 25 Apr 2020 01:08:48 -0000 @@ -187,6 +187,7 @@ options WAPBL # File system journaling # 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 Index: sys/coda/coda_vnops.c =================================================================== RCS file: /cvsroot/src/sys/coda/coda_vnops.c,v retrieving revision 1.111 diff -u -p -u -p -r1.111 coda_vnops.c --- sys/coda/coda_vnops.c 13 Apr 2020 19:23:17 -0000 1.111 +++ sys/coda/coda_vnops.c 25 Apr 2020 01:09:01 -0000 @@ -106,6 +106,7 @@ const struct vnodeopv_entry_desc coda_vn { &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); } Index: sys/fs/adosfs/advnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/adosfs/advnops.c,v retrieving revision 1.53 diff -u -p -u -p -r1.53 advnops.c --- sys/fs/adosfs/advnops.c 23 Apr 2020 21:47:07 -0000 1.53 +++ sys/fs/adosfs/advnops.c 25 Apr 2020 01:09:09 -0000 @@ -101,6 +101,7 @@ const struct vnodeopv_entry_desc adosfs_ { &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 */ @@ -779,7 +780,7 @@ adosfs_check_permitted(struct vnode *vp, 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)); + file_mode, ap->uid, ap->gid, NULL, mode, cred)); } 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); Index: sys/fs/autofs/autofs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/autofs/autofs_vnops.c,v retrieving revision 1.5 diff -u -p -u -p -r1.5 autofs_vnops.c --- sys/fs/autofs/autofs_vnops.c 17 Jan 2020 20:08:07 -0000 1.5 +++ sys/fs/autofs/autofs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -591,6 +591,7 @@ static const struct vnodeopv_entry_desc { &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 }, Index: sys/fs/cd9660/cd9660_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/cd9660/cd9660_vnops.c,v retrieving revision 1.56 diff -u -p -u -p -r1.56 cd9660_vnops.c --- sys/fs/cd9660/cd9660_vnops.c 23 Apr 2020 21:47:07 -0000 1.56 +++ sys/fs/cd9660/cd9660_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -85,7 +85,7 @@ int iso_uiodir(struct isoreaddir *, stru 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, * 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, * 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)); + ip->inode.iso_uid, ip->inode.iso_gid, NULL, accmode, cred)); } 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_ { &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_ { &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_ { &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 */ Index: sys/fs/efs/efs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/efs/efs_vnops.c,v retrieving revision 1.39 diff -u -p -u -p -r1.39 efs_vnops.c --- sys/fs/efs/efs_vnops.c 23 Apr 2020 21:47:07 -0000 1.39 +++ sys/fs/efs/efs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -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, str * 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, + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, 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)); + eip->ei_mode, eip->ei_uid, eip->ei_gid, NULL, accmode, cred)); } 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_vno { &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_spe { &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_fif { &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 */ Index: sys/fs/filecorefs/filecore_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/filecorefs/filecore_vnops.c,v retrieving revision 1.45 diff -u -p -u -p -r1.45 filecore_vnops.c --- sys/fs/filecorefs/filecore_vnops.c 23 Apr 2020 21:47:07 -0000 1.45 +++ sys/fs/filecorefs/filecore_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -122,14 +122,14 @@ filecore_check_possible(struct vnode *vp */ 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)); + fcmp->fc_gid, NULL, accmode, cred)); } 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 filecor { &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 */ Index: sys/fs/hfs/hfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/hfs/hfs_vnops.c,v retrieving revision 1.35 diff -u -p -u -p -r1.35 hfs_vnops.c --- sys/fs/hfs/hfs_vnops.c 23 Apr 2020 21:47:07 -0000 1.35 +++ sys/fs/hfs/hfs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -162,6 +162,7 @@ const struct vnodeopv_entry_desc hfs_vno { &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_spe { &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_fif { &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 */ @@ -560,7 +563,7 @@ hfs_check_permitted(vnode_t *vp, struct 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)); + va->va_mode, va->va_uid, va->va_gid, NULL, mode, cred)); } 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; } Index: sys/fs/msdosfs/msdosfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/msdosfs/msdosfs_vnops.c,v retrieving revision 1.102 diff -u -p -u -p -r1.102 msdosfs_vnops.c --- sys/fs/msdosfs/msdosfs_vnops.c 23 Apr 2020 21:47:07 -0000 1.102 +++ sys/fs/msdosfs/msdosfs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -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, * 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, } 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 file_mode &= (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask); - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, vp->v_type, file_mode), vp, NULL, genfs_can_access(vp->v_type, - file_mode, pmp->pm_uid, pmp->pm_gid, mode, cred)); + file_mode, pmp->pm_uid, pmp->pm_gid, NULL, accmode, cred)); } 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; } @@ -1847,6 +1847,7 @@ const struct vnodeopv_entry_desc msdosfs { &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 */ Index: sys/fs/nilfs/nilfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/nilfs/nilfs_vnops.c,v retrieving revision 1.40 diff -u -p -u -p -r1.40 nilfs_vnops.c --- sys/fs/nilfs/nilfs_vnops.c 23 Apr 2020 21:47:07 -0000 1.40 +++ sys/fs/nilfs/nilfs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -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, s * 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,7 +1020,7 @@ nilfs_check_possible(struct vnode *vp, s /* 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; @@ -1034,7 +1034,7 @@ nilfs_check_permitted(struct vnode *vp, /* 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)); + vap->va_mode, vap->va_uid, vap->va_gid, NULL, mode, cred)); } 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_v { &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 */ Index: sys/fs/ntfs/ntfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/ntfs/ntfs_vnops.c,v retrieving revision 1.63 diff -u -p -u -p -r1.63 ntfs_vnops.c --- sys/fs/ntfs/ntfs_vnops.c 26 May 2017 14:34:20 -0000 1.63 +++ sys/fs/ntfs/ntfs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -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, st * 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,17 @@ ntfs_check_possible(struct vnode *vp, st } 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->v_type, + file_mode, ip->i_mp->ntm_uid, ip->i_mp->ntm_gid, NULL, accmode, + cred)); } int @@ -439,7 +440,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 +449,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 +815,7 @@ const struct vnodeopv_entry_desc ntfs_vn { &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 */ Index: sys/fs/ptyfs/ptyfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/ptyfs/ptyfs_vnops.c,v retrieving revision 1.58 diff -u -p -u -p -r1.58 ptyfs_vnops.c --- sys/fs/ptyfs/ptyfs_vnops.c 13 Apr 2020 19:23:18 -0000 1.58 +++ sys/fs/ptyfs/ptyfs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -172,6 +172,7 @@ const struct vnodeopv_entry_desc ptyfs_v { &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 */ @@ -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), + KAUTH_ACCESS_ACTION(ap->a_accmode, 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)); + va.va_gid, NULL, ap->a_accmode, ap->a_cred)); } /* Index: sys/fs/puffs/puffs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/puffs/puffs_vnops.c,v retrieving revision 1.215 diff -u -p -u -p -r1.215 puffs_vnops.c --- sys/fs/puffs/puffs_vnops.c 23 Apr 2020 21:47:07 -0000 1.215 +++ sys/fs/puffs/puffs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -111,6 +111,7 @@ const struct vnodeopv_entry_desc puffs_v { &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_s { &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_f { &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_m { &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)); Index: sys/fs/sysvbfs/sysvbfs.c =================================================================== RCS file: /cvsroot/src/sys/fs/sysvbfs/sysvbfs.c,v retrieving revision 1.17 diff -u -p -u -p -r1.17 sysvbfs.c --- sys/fs/sysvbfs/sysvbfs.c 28 May 2018 21:04:37 -0000 1.17 +++ sys/fs/sysvbfs/sysvbfs.c 25 Apr 2020 01:09:09 -0000 @@ -55,6 +55,7 @@ const struct vnodeopv_entry_desc sysvbfs { &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 */ Index: sys/fs/sysvbfs/sysvbfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/sysvbfs/sysvbfs_vnops.c,v retrieving revision 1.65 diff -u -p -u -p -r1.65 sysvbfs_vnops.c --- sys/fs/sysvbfs/sysvbfs_vnops.c 23 Apr 2020 21:47:08 -0000 1.65 +++ sys/fs/sysvbfs/sysvbfs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -255,7 +255,7 @@ sysvbfs_check_permitted(struct vnode *vp 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)); + attr->mode, attr->uid, attr->gid, NULL, mode, cred)); } 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; } Index: sys/fs/tmpfs/tmpfs_fifoops.c =================================================================== RCS file: /cvsroot/src/sys/fs/tmpfs/tmpfs_fifoops.c,v retrieving revision 1.11 diff -u -p -u -p -r1.11 tmpfs_fifoops.c --- sys/fs/tmpfs/tmpfs_fifoops.c 25 Jul 2014 08:20:52 -0000 1.11 +++ sys/fs/tmpfs/tmpfs_fifoops.c 25 Apr 2020 01:09:09 -0000 @@ -55,6 +55,7 @@ const struct vnodeopv_entry_desc tmpfs_f { &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 }, Index: sys/fs/tmpfs/tmpfs_specops.c =================================================================== RCS file: /cvsroot/src/sys/fs/tmpfs/tmpfs_specops.c,v retrieving revision 1.12 diff -u -p -u -p -r1.12 tmpfs_specops.c --- sys/fs/tmpfs/tmpfs_specops.c 25 Jul 2014 08:20:52 -0000 1.12 +++ sys/fs/tmpfs/tmpfs_specops.c 25 Apr 2020 01:09:09 -0000 @@ -58,6 +58,7 @@ const struct vnodeopv_entry_desc tmpfs_s { &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 }, Index: sys/fs/tmpfs/tmpfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/tmpfs/tmpfs_vnops.c,v retrieving revision 1.136 diff -u -p -u -p -r1.136 tmpfs_vnops.c --- sys/fs/tmpfs/tmpfs_vnops.c 23 Apr 2020 21:47:08 -0000 1.136 +++ sys/fs/tmpfs/tmpfs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -70,6 +70,7 @@ const struct vnodeopv_entry_desc tmpfs_v { &vop_open_desc, tmpfs_open }, { &vop_close_desc, tmpfs_close }, { &vop_access_desc, tmpfs_access }, + { &vop_accessx_desc, genfs_access }, { &vop_getattr_desc, tmpfs_getattr }, { &vop_setattr_desc, tmpfs_setattr }, { &vop_read_desc, tmpfs_read }, @@ -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, + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, 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)); + node->tn_mode, node->tn_uid, node->tn_gid, NULL, accmode, cred)); } int Index: sys/fs/udf/udf_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/udf/udf_vnops.c,v retrieving revision 1.112 diff -u -p -u -p -r1.112 udf_vnops.c --- sys/fs/udf/udf_vnops.c 23 Apr 2020 21:47:08 -0000 1.112 +++ sys/fs/udf/udf_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -1443,7 +1443,7 @@ udf_check_permitted(struct vnode *vp, st /* 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)); + vap->va_mode, vap->va_uid, vap->va_gid, NULL, mode, cred)); } 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_vno { &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 */ Index: sys/fs/union/union_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/union/union_vnops.c,v retrieving revision 1.72 diff -u -p -u -p -r1.72 union_vnops.c --- sys/fs/union/union_vnops.c 23 Feb 2020 15:46:41 -0000 1.72 +++ sys/fs/union/union_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -151,6 +151,7 @@ const struct vnodeopv_entry_desc union_v { &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: Index: sys/fs/unionfs/unionfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/unionfs/unionfs_vnops.c,v retrieving revision 1.13 diff -u -p -u -p -r1.13 unionfs_vnops.c --- sys/fs/unionfs/unionfs_vnops.c 23 Feb 2020 15:46:41 -0000 1.13 +++ sys/fs/unionfs/unionfs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -1821,6 +1821,7 @@ const struct vnodeopv_entry_desc unionfs { &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 */ Index: sys/fs/v7fs/v7fs_extern.c =================================================================== RCS file: /cvsroot/src/sys/fs/v7fs/v7fs_extern.c,v retrieving revision 1.6 diff -u -p -u -p -r1.6 v7fs_extern.c --- sys/fs/v7fs/v7fs_extern.c 28 May 2018 21:04:38 -0000 1.6 +++ sys/fs/v7fs/v7fs_extern.c 25 Apr 2020 01:09:09 -0000 @@ -61,6 +61,7 @@ const struct vnodeopv_entry_desc v7fs_vn { &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_sp { &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_fi { &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 */ Index: sys/fs/v7fs/v7fs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/v7fs/v7fs_vnops.c,v retrieving revision 1.29 diff -u -p -u -p -r1.29 v7fs_vnops.c --- sys/fs/v7fs/v7fs_vnops.c 23 Apr 2020 21:47:08 -0000 1.29 +++ sys/fs/v7fs/v7fs_vnops.c 25 Apr 2020 01:09:09 -0000 @@ -379,26 +379,26 @@ v7fs_check_permitted(struct vnode *vp, s 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)); + inode->mode, inode->uid, inode->gid, NULL, mode, cred)); } 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; } Index: sys/gdbscripts/kernhist =================================================================== RCS file: /cvsroot/src/sys/gdbscripts/kernhist,v retrieving revision 1.2 diff -u -p -u -p -r1.2 kernhist --- sys/gdbscripts/kernhist 12 May 2016 00:35:10 -0000 1.2 +++ sys/gdbscripts/kernhist 25 Apr 2020 01:09:09 -0000 @@ -15,8 +15,15 @@ define kernhist set $e = $hist->e[$lcv] set $fmt = $e.fmt + if ($e.v[2] != 0xffff8fbe5f7604a0l) + set $lcv = ($lcv + 1) % $histn + if ($lcv == $histf) + loop_break + end + loop_continue + end if ($fmt) - printf "%06lx.%06d ", $e.tv.tv_sec, $e.tv.tv_usec + printf "%ld ", $e.bt.sec printf "%s#%ld@%d: ", $e.fn, $e.call, $e.cpunum printf "%s: %lx %lx %lx %lx\n", $fmt, $e.v[0], $e.v[1], $e.v[2], $e.v[3] set $lcv = ($lcv + 1) % $histn Index: sys/kern/files.kern =================================================================== RCS file: /cvsroot/src/sys/kern/files.kern,v retrieving revision 1.45 diff -u -p -u -p -r1.45 files.kern --- sys/kern/files.kern 22 Apr 2020 09:18:42 -0000 1.45 +++ sys/kern/files.kern 25 Apr 2020 01:09:09 -0000 @@ -98,6 +98,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 @@ -193,6 +195,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 Index: sys/kern/init_sysent.c =================================================================== RCS file: /cvsroot/src/sys/kern/init_sysent.c,v retrieving revision 1.329 diff -u -p -u -p -r1.329 init_sysent.c --- sys/kern/init_sysent.c 22 Apr 2020 21:25:17 -0000 1.329 +++ sys/kern/init_sysent.c 25 Apr 2020 01:09:09 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: init_sysent.c,v 1.329 2020/04/22 21:25:17 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call switch table. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: init_sysent.c,v 1.329 2020/04/22 21:25:17 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #ifdef _KERNEL_OPT #include "opt_modular.h" @@ -23,6 +23,7 @@ __KERNEL_RCSID(0, "$NetBSD: init_sysent. #include #include #include +#include #ifdef COMPAT_43 #define compat_43(func) __CONCAT(compat_43_,func) @@ -2359,44 +2360,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 */ Index: sys/kern/kern_auth.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_auth.c,v retrieving revision 1.77 diff -u -p -u -p -r1.77 kern_auth.c --- sys/kern/kern_auth.c 3 Sep 2018 16:29:35 -0000 1.77 +++ sys/kern/kern_auth.c 25 Apr 2020 01:09:09 -0000 @@ -1090,18 +1090,19 @@ kauth_authorize_device_passthru(kauth_cr } 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 Index: sys/kern/subr_acl_nfs4.c =================================================================== RCS file: sys/kern/subr_acl_nfs4.c diff -N sys/kern/subr_acl_nfs4.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/kern/subr_acl_nfs4.c 25 Apr 2020 01:09:09 -0000 @@ -0,0 +1,614 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2008-2010 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. + */ + +/* + * 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 +#if 0 +__FBSDID("$FreeBSD: head/sys/kern/subr_acl_nfs4.c 341827 2018-12-11 19:32:16Z mjg $"); +#endif +__KERNEL_RCSID(0, "$NetBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void acl_nfs4_trivial_from_mode(struct acl *aclp, mode_t mode); + + +#else + +#include +#include +#include +#include +#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 Index: sys/kern/subr_acl_posix1e.c =================================================================== RCS file: sys/kern/subr_acl_posix1e.c diff -N sys/kern/subr_acl_posix1e.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/kern/subr_acl_posix1e.c 25 Apr 2020 01:09:09 -0000 @@ -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 +#if 0 +__FBSDID("$FreeBSD: head/sys/kern/subr_acl_posix1e.c 341827 2018-12-11 19:32:16Z mjg $"); +#endif +__KERNEL_RCSID(0, "$NetBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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); +} Index: sys/kern/sys_mqueue.c =================================================================== RCS file: /cvsroot/src/sys/kern/sys_mqueue.c,v retrieving revision 1.46 diff -u -p -u -p -r1.46 sys_mqueue.c --- sys/kern/sys_mqueue.c 16 Mar 2020 21:20:10 -0000 1.46 +++ sys/kern/sys_mqueue.c 25 Apr 2020 01:09:09 -0000 @@ -403,7 +403,7 @@ mqueue_access(mqueue_t *mq, int access, acc_mode |= VWRITE; } if (genfs_can_access(VNON, mq->mq_mode, mq->mq_euid, - mq->mq_egid, acc_mode, cred)) { + mq->mq_egid, NULL, acc_mode, cred)) { return EACCES; } return 0; Index: sys/kern/syscalls.c =================================================================== RCS file: /cvsroot/src/sys/kern/syscalls.c,v retrieving revision 1.317 diff -u -p -u -p -r1.317 syscalls.c --- sys/kern/syscalls.c 22 Apr 2020 21:25:17 -0000 1.317 +++ sys/kern/syscalls.c 25 Apr 2020 01:09:09 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: syscalls.c,v 1.317 2020/04/22 21:25:17 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call names. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: syscalls.c,v 1.317 2020/04/22 21:25:17 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #if defined(_KERNEL_OPT) #ifdef _KERNEL_OPT @@ -24,6 +24,7 @@ __KERNEL_RCSID(0, "$NetBSD: syscalls.c,v #include #include #include +#include #else /* _KERNEL_OPT */ #include #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 */ Index: sys/kern/syscalls.conf =================================================================== RCS file: /cvsroot/src/sys/kern/syscalls.conf,v retrieving revision 1.30 diff -u -p -u -p -r1.30 syscalls.conf --- sys/kern/syscalls.conf 22 Sep 2019 22:59:39 -0000 1.30 +++ sys/kern/syscalls.conf 25 Apr 2020 01:09:09 -0000 @@ -5,7 +5,7 @@ sysnumhdr="../sys/syscall.h" syssw="init_sysent.c" systrace="systrace_args.c" sysarghdr="../sys/syscallargs.h" -sysarghdrextra='#ifndef RUMP_CLIENT\n#include \n#include \n#include \n#endif\n\n#include \n\n' +sysarghdrextra='#ifndef RUMP_CLIENT\n#include \n#include \n#include \n#include \n#endif\n\n#include \n\n' sysautoload="syscalls_autoload.c" sysalign=1 rumpcalls="../rump/librump/rumpkern/rump_syscalls.c" Index: sys/kern/syscalls.master =================================================================== RCS file: /cvsroot/src/sys/kern/syscalls.master,v retrieving revision 1.302 diff -u -p -u -p -r1.302 syscalls.master --- sys/kern/syscalls.master 22 Apr 2020 21:22:21 -0000 1.302 +++ sys/kern/syscalls.master 25 Apr 2020 01:09:09 -0000 @@ -59,6 +59,7 @@ #include #include #include +#include %% @@ -1015,3 +1016,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); } Index: sys/kern/syscalls_autoload.c =================================================================== RCS file: /cvsroot/src/sys/kern/syscalls_autoload.c,v retrieving revision 1.34 diff -u -p -u -p -r1.34 syscalls_autoload.c --- sys/kern/syscalls_autoload.c 22 Apr 2020 21:25:17 -0000 1.34 +++ sys/kern/syscalls_autoload.c 25 Apr 2020 01:09:09 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: syscalls_autoload.c,v 1.34 2020/04/22 21:25:17 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call autoload table. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: syscalls_autoload.c,v 1.34 2020/04/22 21:25:17 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #ifdef _KERNEL_OPT #include "opt_modular.h" @@ -23,6 +23,7 @@ __KERNEL_RCSID(0, "$NetBSD: syscalls_aut #include #include #include +#include static struct sc_autoload netbsd_syscalls_autoload[] = { { SYS_compat_50_wait4, "compat_50" }, { SYS_compat_43_ocreat, "compat_43" }, Index: sys/kern/systrace_args.c =================================================================== RCS file: /cvsroot/src/sys/kern/systrace_args.c,v retrieving revision 1.36 diff -u -p -u -p -r1.36 systrace_args.c --- sys/kern/systrace_args.c 22 Apr 2020 21:25:17 -0000 1.36 +++ sys/kern/systrace_args.c 25 Apr 2020 01:09:10 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: systrace_args.c,v 1.36 2020/04/22 21:25:17 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call argument to DTrace register array converstion. @@ -3701,6 +3701,119 @@ systrace_args(register_t sysnum, const v *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; @@ -9979,6 +10092,202 @@ systrace_entry_setargdesc(int sysnum, in 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; }; @@ -12076,6 +12385,71 @@ systrace_return_setargdesc(int sysnum, i 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; }; Index: sys/kern/vfs_acl.c =================================================================== RCS file: sys/kern/vfs_acl.c diff -N sys/kern/vfs_acl.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/kern/vfs_acl.c 25 Apr 2020 01:09:10 -0000 @@ -0,0 +1,556 @@ +/*- + * 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_.c. + */ + +#include +#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.545 2020/04/04 20:49:30 ad Exp $"); + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +__CTASSERT(ACL_MAX_ENTRIES >= OLDACL_MAX_ENTRIES); + +static int kern___acl_aclcheck_path(struct lwp *l, const char *path, + acl_type_t type, struct acl *aclp, namei_simple_flags_t flags); +static int kern___acl_delete_path(struct lwp *l, const char *path, + acl_type_t type, namei_simple_flags_t flags); +static int kern___acl_get_path(struct lwp *l, const char *path, + acl_type_t type, struct acl *aclp, namei_simple_flags_t flags); +static int kern___acl_set_path(struct lwp *l, const char *path, + acl_type_t type, const struct acl *aclp, namei_simple_flags_t flags); +static int vacl_set_acl(struct lwp *l, struct vnode *vp, + acl_type_t type, const struct acl *aclp); +static int vacl_get_acl(struct lwp *l, struct vnode *vp, + acl_type_t type, struct acl *aclp); +static int vacl_aclcheck(struct lwp *l, struct vnode *vp, + acl_type_t type, const struct acl *aclp); + +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. + */ +static 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. + */ +static 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. + */ +static 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...? + */ +static 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); +} + +static 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); +} + +static 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); +} + +static 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); +} + +static 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)); +} Index: sys/kern/vfs_cache.c =================================================================== RCS file: /cvsroot/src/sys/kern/vfs_cache.c,v retrieving revision 1.141 diff -u -p -u -p -r1.141 vfs_cache.c --- sys/kern/vfs_cache.c 23 Apr 2020 22:58:36 -0000 1.141 +++ sys/kern/vfs_cache.c 25 Apr 2020 01:09:10 -0000 @@ -688,7 +688,7 @@ cache_lookup_linked(struct vnode *dvp, c 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)); + dvi->vi_nc_uid, dvi->vi_nc_gid, NULL, VEXEC, cred)); if (error != 0) { COUNT(ncs_denied); return false; @@ -769,7 +769,7 @@ cache_revlookup(struct vnode *vp, struct 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)); + NULL, perms, curlwp->l_cred)); if (error != 0) { rw_exit(&vi->vi_nc_listlock); COUNT(ncs_denied); Index: sys/kern/vfs_getcwd.c =================================================================== RCS file: /cvsroot/src/sys/kern/vfs_getcwd.c,v retrieving revision 1.59 diff -u -p -u -p -r1.59 vfs_getcwd.c --- sys/kern/vfs_getcwd.c 21 Apr 2020 21:42:47 -0000 1.59 +++ sys/kern/vfs_getcwd.c 25 Apr 2020 01:09:10 -0000 @@ -277,7 +277,7 @@ getcwd_common(struct vnode *lvp, struct 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 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 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 * 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 panic("getcwd: oops, went back too far"); } #endif - perms = VEXEC | VREAD; + accmode = VEXEC | VREAD; if (bp) *(--bp) = '/'; vrele(lvp); Index: sys/kern/vfs_init.c =================================================================== RCS file: /cvsroot/src/sys/kern/vfs_init.c,v retrieving revision 1.50 diff -u -p -u -p -r1.50 vfs_init.c --- sys/kern/vfs_init.c 21 Feb 2020 00:26:22 -0000 1.50 +++ sys/kern/vfs_init.c 25 Apr 2020 01:09:10 -0000 @@ -377,10 +377,10 @@ mount_listener_cb(kauth_cred_t cred, kau 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; } Index: sys/kern/vfs_subr.c =================================================================== RCS file: /cvsroot/src/sys/kern/vfs_subr.c,v retrieving revision 1.486 diff -u -p -u -p -r1.486 vfs_subr.c --- sys/kern/vfs_subr.c 21 Apr 2020 21:42:47 -0000 1.486 +++ sys/kern/vfs_subr.c 25 Apr 2020 01:09:10 -0000 @@ -1141,16 +1141,16 @@ vprint(const char *label, struct vnode * /* 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) + accmode_t accmode, kauth_cred_t cred) { #ifdef DIAGNOSTIC printf("vaccess: deprecated interface used.\n"); #endif /* DIAGNOSTIC */ - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(acc_mode, + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, type, file_mode), NULL /* This may panic. */, NULL, - genfs_can_access(type, file_mode, uid, gid, acc_mode, cred)); + genfs_can_access(type, file_mode, uid, gid, NULL, accmode, cred)); } /* @@ -1278,6 +1278,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) Index: sys/kern/vfs_syscalls.c =================================================================== RCS file: /cvsroot/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.547 diff -u -p -u -p -r1.547 vfs_syscalls.c --- sys/kern/vfs_syscalls.c 21 Apr 2020 21:42:47 -0000 1.547 +++ sys/kern/vfs_syscalls.c 25 Apr 2020 01:09:10 -0000 @@ -3232,34 +3232,55 @@ sys_fstatat(struct lwp *l, const struct 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 fromf 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, 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); Index: sys/kern/vfs_xattr.c =================================================================== RCS file: /cvsroot/src/sys/kern/vfs_xattr.c,v retrieving revision 1.34 diff -u -p -u -p -r1.34 vfs_xattr.c --- sys/kern/vfs_xattr.c 20 Apr 2020 00:34:58 -0000 1.34 +++ sys/kern/vfs_xattr.c 25 Apr 2020 01:09:10 -0000 @@ -96,7 +96,7 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_xattr.c, * 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, con return (0); return kauth_authorize_vnode(cred, kauth_extattr_action(access), vp, - NULL, genfs_can_extattr(cred, access, vp, attr)); + NULL, genfs_can_extattr(cred, access, vp, attrspace)); } /* Index: sys/kern/vnode_if.c =================================================================== RCS file: /cvsroot/src/sys/kern/vnode_if.c,v retrieving revision 1.110 diff -u -p -u -p -r1.110 vnode_if.c --- sys/kern/vnode_if.c 23 Feb 2020 22:15:19 -0000 1.110 +++ sys/kern/vnode_if.c 25 Apr 2020 01:09:10 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: vnode_if.c,v 1.110 2020/02/23 22:15:19 ad Exp $ */ +/* $NetBSD$ */ /* * Warning: DO NOT EDIT! This file is automatically generated! @@ -40,7 +40,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: vnode_if.c,v 1.110 2020/02/23 22:15:19 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #include #include @@ -349,7 +349,7 @@ const struct vnodeop_desc vop_access_des }; 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 &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 &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, Index: sys/kern/vnode_if.sh =================================================================== RCS file: /cvsroot/src/sys/kern/vnode_if.sh,v retrieving revision 1.69 diff -u -p -u -p -r1.69 vnode_if.sh --- sys/kern/vnode_if.sh 23 Feb 2020 22:14:04 -0000 1.69 +++ sys/kern/vnode_if.sh 25 Apr 2020 01:09:10 -0000 @@ -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 \n"); } printf("\n#ifndef _KERNEL\n#include \n#endif\n"); if (rump) Index: sys/kern/vnode_if.src =================================================================== RCS file: /cvsroot/src/sys/kern/vnode_if.src,v retrieving revision 1.78 diff -u -p -u -p -r1.78 vnode_if.src --- sys/kern/vnode_if.src 11 Oct 2019 08:04:52 -0000 1.78 +++ sys/kern/vnode_if.src 25 Apr 2020 01:09:10 -0000 @@ -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 { Index: sys/miscfs/fdesc/fdesc_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/fdesc/fdesc_vnops.c,v retrieving revision 1.132 diff -u -p -u -p -r1.132 fdesc_vnops.c --- sys/miscfs/fdesc/fdesc_vnops.c 1 Feb 2020 02:23:04 -0000 1.132 +++ sys/miscfs/fdesc/fdesc_vnops.c 25 Apr 2020 01:09:10 -0000 @@ -125,6 +125,7 @@ const struct vnodeopv_entry_desc fdesc_v { &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 */ Index: sys/miscfs/fifofs/fifo_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/fifofs/fifo_vnops.c,v retrieving revision 1.79 diff -u -p -u -p -r1.79 fifo_vnops.c --- sys/miscfs/fifofs/fifo_vnops.c 25 Oct 2017 08:12:39 -0000 1.79 +++ sys/miscfs/fifofs/fifo_vnops.c 25 Apr 2020 01:09:10 -0000 @@ -637,6 +637,7 @@ const struct vnodeopv_entry_desc fifo_vn { &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 */ Index: sys/miscfs/genfs/genfs.h =================================================================== RCS file: /cvsroot/src/sys/miscfs/genfs/genfs.h,v retrieving revision 1.33 diff -u -p -u -p -r1.33 genfs.h --- sys/miscfs/genfs/genfs.h 17 Feb 2017 08:31:25 -0000 1.33 +++ sys/miscfs/genfs/genfs.h 25 Apr 2020 01:09:10 -0000 @@ -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,18 @@ 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_access(enum vtype, mode_t, uid_t, gid_t, + struct acl *, accmode_t, kauth_cred_t); +int genfs_can_access_acl_posix1e(enum vtype, mode_t, uid_t, gid_t, + struct acl *, accmode_t, kauth_cred_t); +int genfs_can_access_acl_nfs4(enum vtype, mode_t, uid_t, gid_t, + struct acl *, accmode_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_extattr(kauth_cred_t, int, vnode_t *, int); /* * Rename is complicated. Sorry. Index: sys/miscfs/genfs/genfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/genfs/genfs_vnops.c,v retrieving revision 1.202 diff -u -p -u -p -r1.202 genfs_vnops.c --- sys/miscfs/genfs/genfs_vnops.c 23 Feb 2020 22:14:04 -0000 1.202 +++ sys/miscfs/genfs/genfs_vnops.c 25 Apr 2020 01:09:10 -0000 @@ -74,6 +74,7 @@ __KERNEL_RCSID(0, "$NetBSD: genfs_vnops. #include #include #include +#include #include #include @@ -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's type, "mode", uid and gid, requested access mode, credentials. + * 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(enum vtype type, mode_t file_mode, uid_t file_uid, + gid_t file_gid, struct acl *acl, accmode_t accmode, kauth_cred_t cred) { - 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; + dac_granted = 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); + /* 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(enum vtype type, mode_t file_mode, uid_t file_uid, + gid_t file_gid, struct acl *acl, accmode_t accmode, kauth_cred_t cred) +{ + 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(enum vtype type, mode_t file_mode, uid_t file_uid, + gid_t file_gid, struct acl *aclp, accmode_t accmode, kauth_cred_t cred) +{ + 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 (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); } /* @@ -739,10 +1206,6 @@ genfs_can_chmod(enum vtype type, kauth_c { int error; - /* The user must own the file. */ - if (kauth_cred_geteuid(cred) != cur_uid) - return (EPERM); - /* * Unprivileged users can't set the sticky bit on files. */ @@ -762,6 +1225,12 @@ genfs_can_chmod(enum vtype type, kauth_c 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); } @@ -901,12 +1370,53 @@ genfs_can_sticky(kauth_cred_t cred, uid_ } int -genfs_can_extattr(kauth_cred_t cred, int access_mode, vnode_t *vp, - const char *attr) +genfs_can_extattr(kauth_cred_t cred, int accmode, vnode_t *vp, + int attrnamespace) { - /* We can't allow privileged namespaces. */ - if (strncasecmp(attr, "system", 6) == 0) + /* + * 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; + } +} + +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); } Index: sys/miscfs/genfs/layer_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/genfs/layer_vnops.c,v retrieving revision 1.70 diff -u -p -u -p -r1.70 layer_vnops.c --- sys/miscfs/genfs/layer_vnops.c 13 Apr 2020 19:23:19 -0000 1.70 +++ sys/miscfs/genfs/layer_vnops.c 25 Apr 2020 01:09:10 -0000 @@ -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: Index: sys/miscfs/kernfs/kernfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/kernfs/kernfs_vnops.c,v retrieving revision 1.164 diff -u -p -u -p -r1.164 kernfs_vnops.c --- sys/miscfs/kernfs/kernfs_vnops.c 24 Feb 2020 20:44:25 -0000 1.164 +++ sys/miscfs/kernfs/kernfs_vnops.c 25 Apr 2020 01:09:10 -0000 @@ -188,6 +188,7 @@ const struct vnodeopv_entry_desc kernfs_ { &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_ { &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), + KAUTH_ACCESS_ACTION(ap->a_accmode, 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)); + va.va_uid, va.va_gid, NULL, ap->a_accmode, ap->a_cred)); } static int Index: sys/miscfs/nullfs/null_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/nullfs/null_vnops.c,v retrieving revision 1.42 diff -u -p -u -p -r1.42 null_vnops.c --- sys/miscfs/nullfs/null_vnops.c 4 Jun 2017 08:02:26 -0000 1.42 +++ sys/miscfs/nullfs/null_vnops.c 25 Apr 2020 01:09:10 -0000 @@ -103,6 +103,7 @@ const struct vnodeopv_entry_desc null_vn { &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 }, Index: sys/miscfs/overlay/overlay_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/overlay/overlay_vnops.c,v retrieving revision 1.24 diff -u -p -u -p -r1.24 overlay_vnops.c --- sys/miscfs/overlay/overlay_vnops.c 4 Jun 2017 08:02:26 -0000 1.24 +++ sys/miscfs/overlay/overlay_vnops.c 25 Apr 2020 01:09:10 -0000 @@ -151,6 +151,7 @@ const struct vnodeopv_entry_desc overlay { &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 }, Index: sys/miscfs/procfs/procfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/procfs/procfs_vnops.c,v retrieving revision 1.211 diff -u -p -u -p -r1.211 procfs_vnops.c --- sys/miscfs/procfs/procfs_vnops.c 21 Apr 2020 21:42:47 -0000 1.211 +++ sys/miscfs/procfs/procfs_vnops.c 25 Apr 2020 01:09:10 -0000 @@ -261,6 +261,7 @@ const struct vnodeopv_entry_desc procfs_ { &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 */ @@ -965,7 +966,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; @@ -975,9 +976,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), + KAUTH_ACCESS_ACTION(ap->a_accmode, 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)); + va.va_uid, va.va_gid, NULL, ap->a_accmode, ap->a_cred)); } /* Index: sys/miscfs/specfs/spec_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/specfs/spec_vnops.c,v retrieving revision 1.177 diff -u -p -u -p -r1.177 spec_vnops.c --- sys/miscfs/specfs/spec_vnops.c 13 Apr 2020 20:02:27 -0000 1.177 +++ sys/miscfs/specfs/spec_vnops.c 25 Apr 2020 01:09:10 -0000 @@ -121,6 +121,7 @@ const struct vnodeopv_entry_desc spec_vn { &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 */ Index: sys/miscfs/umapfs/umap_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/umapfs/umap_vnops.c,v retrieving revision 1.60 diff -u -p -u -p -r1.60 umap_vnops.c --- sys/miscfs/umapfs/umap_vnops.c 4 Jun 2017 08:02:26 -0000 1.60 +++ sys/miscfs/umapfs/umap_vnops.c 25 Apr 2020 01:09:10 -0000 @@ -92,6 +92,7 @@ const struct vnodeopv_entry_desc umap_vn { &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 }, Index: sys/modules/ffs/Makefile =================================================================== RCS file: /cvsroot/src/sys/modules/ffs/Makefile,v retrieving revision 1.14 diff -u -p -u -p -r1.14 Makefile --- sys/modules/ffs/Makefile 18 Apr 2020 19:18:33 -0000 1.14 +++ sys/modules/ffs/Makefile 25 Apr 2020 01:09:11 -0000 @@ -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 Index: sys/modules/ufs/Makefile =================================================================== RCS file: /cvsroot/src/sys/modules/ufs/Makefile,v retrieving revision 1.3 diff -u -p -u -p -r1.3 Makefile --- sys/modules/ufs/Makefile 12 Apr 2020 01:39:57 -0000 1.3 +++ sys/modules/ufs/Makefile 25 Apr 2020 01:09:14 -0000 @@ -5,7 +5,7 @@ KMOD= ufs CPPFLAGS+= -DUFS_DIRHASH -DFFS_EI -DWAPBL -DAPPLE_UFS -DQUOTA -DQUOTA2 -CPPFLAGS+= -DUFS_EXTATTR +CPPFLAGS+= -DUFS_EXTATTR -DUFS_ACL CWARNFLAGS.clang= -Wno-conversion Index: sys/nfs/nfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/nfs/nfs_vnops.c,v retrieving revision 1.314 diff -u -p -u -p -r1.314 nfs_vnops.c --- sys/nfs/nfs_vnops.c 13 Apr 2020 19:23:20 -0000 1.314 +++ sys/nfs/nfs_vnops.c 25 Apr 2020 01:09:14 -0000 @@ -103,6 +103,7 @@ const struct vnodeopv_entry_desc nfsv2_v { &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_nf { &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_nf { &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( + va.va_type, va.va_mode, va.va_uid, va.va_gid, NULL, + ap->a_accmode, ap->a_cred)); } /* Index: sys/rump/rump.sysmap =================================================================== RCS file: /cvsroot/src/sys/rump/rump.sysmap,v retrieving revision 1.6 diff -u -p -u -p -r1.6 rump.sysmap --- sys/rump/rump.sysmap 22 Sep 2019 23:03:20 -0000 1.6 +++ sys/rump/rump.sysmap 25 Apr 2020 01:09:14 -0000 @@ -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 Index: sys/rump/fs/lib/libffs/Makefile =================================================================== RCS file: /cvsroot/src/sys/rump/fs/lib/libffs/Makefile,v retrieving revision 1.18 diff -u -p -u -p -r1.18 Makefile --- sys/rump/fs/lib/libffs/Makefile 18 Apr 2020 19:18:33 -0000 1.18 +++ sys/rump/fs/lib/libffs/Makefile 25 Apr 2020 01:09:15 -0000 @@ -10,12 +10,12 @@ SRCS= ffs_alloc.c ffs_appleufs.c ffs_bal 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 .include Index: sys/rump/include/rump/rump_syscalls.h =================================================================== RCS file: /cvsroot/src/sys/rump/include/rump/rump_syscalls.h,v retrieving revision 1.115 diff -u -p -u -p -r1.115 rump_syscalls.h --- sys/rump/include/rump/rump_syscalls.h 22 Apr 2020 21:25:17 -0000 1.115 +++ sys/rump/include/rump/rump_syscalls.h 25 Apr 2020 01:09:15 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: rump_syscalls.h,v 1.115 2020/04/22 21:25:17 thorpej Exp $ */ +/* $NetBSD$ */ /* * 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 * 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_ */ Index: sys/rump/include/rump/rumpvnode_if.h =================================================================== RCS file: /cvsroot/src/sys/rump/include/rump/rumpvnode_if.h,v retrieving revision 1.33 diff -u -p -u -p -r1.33 rumpvnode_if.h --- sys/rump/include/rump/rumpvnode_if.h 23 Feb 2020 22:15:19 -0000 1.33 +++ sys/rump/include/rump/rumpvnode_if.h 25 Apr 2020 01:09:15 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpvnode_if.h,v 1.33 2020/02/23 22:15:19 ad Exp $ */ +/* $NetBSD$ */ /* * 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 #ifndef _KERNEL #include @@ -59,7 +62,8 @@ int RUMP_VOP_MKNOD(struct vnode *, struc 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 *, st 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 *); Index: sys/rump/librump/rumpkern/rump_syscalls.c =================================================================== RCS file: /cvsroot/src/sys/rump/librump/rumpkern/rump_syscalls.c,v retrieving revision 1.146 diff -u -p -u -p -r1.146 rump_syscalls.c --- sys/rump/librump/rumpkern/rump_syscalls.c 22 Apr 2020 21:25:17 -0000 1.146 +++ sys/rump/librump/rumpkern/rump_syscalls.c 25 Apr 2020 01:09:16 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: rump_syscalls.c,v 1.146 2020/04/22 21:25:17 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call vector and marshalling for rump. @@ -15,7 +15,7 @@ #ifdef __NetBSD__ #include -__KERNEL_RCSID(0, "$NetBSD: rump_syscalls.c,v 1.146 2020/04/22 21:25:17 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #include #include @@ -6523,6 +6523,35 @@ __weak_alias(___fhstatvfs190,rump___sysi __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) @@ -8448,57 +8477,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, Index: sys/rump/librump/rumpvfs/Makefile.rumpvfs =================================================================== RCS file: /cvsroot/src/sys/rump/librump/rumpvfs/Makefile.rumpvfs,v retrieving revision 1.49 diff -u -p -u -p -r1.49 Makefile.rumpvfs --- sys/rump/librump/rumpvfs/Makefile.rumpvfs 26 Jan 2016 23:12:18 -0000 1.49 +++ sys/rump/librump/rumpvfs/Makefile.rumpvfs 25 Apr 2020 01:09:16 -0000 @@ -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 Index: sys/rump/librump/rumpvfs/rumpfs.c =================================================================== RCS file: /cvsroot/src/sys/rump/librump/rumpvfs/rumpfs.c,v retrieving revision 1.157 diff -u -p -u -p -r1.157 rumpfs.c --- sys/rump/librump/rumpvfs/rumpfs.c 23 Apr 2020 21:47:08 -0000 1.157 +++ sys/rump/librump/rumpvfs/rumpfs.c 25 Apr 2020 01:09:16 -0000 @@ -111,6 +111,7 @@ const struct vnodeopv_entry_desc rump_vn { &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 }, @@ -831,7 +832,7 @@ rump_check_permitted(struct vnode *vp, s 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)); + attr->va_mode, attr->va_uid, attr->va_gid, NULL, mode, cred)); } int @@ -847,11 +848,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; } Index: sys/rump/librump/rumpvfs/rumpvnode_if.c =================================================================== RCS file: /cvsroot/src/sys/rump/librump/rumpvfs/rumpvnode_if.c,v retrieving revision 1.33 diff -u -p -u -p -r1.33 rumpvnode_if.c --- sys/rump/librump/rumpvfs/rumpvnode_if.c 23 Feb 2020 22:15:19 -0000 1.33 +++ sys/rump/librump/rumpvfs/rumpvnode_if.c 25 Apr 2020 01:09:16 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpvnode_if.c,v 1.33 2020/02/23 22:15:19 ad Exp $ */ +/* $NetBSD$ */ /* * Warning: DO NOT EDIT! This file is automatically generated! @@ -40,7 +40,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: rumpvnode_if.c,v 1.33 2020/02/23 22:15:19 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #include #include @@ -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) Index: sys/sys/Makefile =================================================================== RCS file: /cvsroot/src/sys/sys/Makefile,v retrieving revision 1.172 diff -u -p -u -p -r1.172 Makefile --- sys/sys/Makefile 22 Mar 2020 14:27:33 -0000 1.172 +++ sys/sys/Makefile 25 Apr 2020 01:09:16 -0000 @@ -4,7 +4,7 @@ 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 \ Index: sys/sys/acl.h =================================================================== RCS file: sys/sys/acl.h diff -N sys/sys/acl.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/sys/acl.h 25 Apr 2020 01:09:16 -0000 @@ -0,0 +1,422 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 1999-2001 Robert N. M. Watson + * Copyright (c) 2008 Edward Tomasz NapieraƂa + * 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 +#include + +/* + * 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) + +#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); + +#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_ */ Index: sys/sys/ansi.h =================================================================== RCS file: /cvsroot/src/sys/sys/ansi.h,v retrieving revision 1.14 diff -u -p -u -p -r1.14 ansi.h --- sys/sys/ansi.h 17 Jul 2011 20:54:54 -0000 1.14 +++ sys/sys/ansi.h 25 Apr 2020 01:09:16 -0000 @@ -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 */ Index: sys/sys/extattr.h =================================================================== RCS file: /cvsroot/src/sys/sys/extattr.h,v retrieving revision 1.9 diff -u -p -u -p -r1.9 extattr.h --- sys/sys/extattr.h 13 Mar 2012 18:41:02 -0000 1.9 +++ sys/sys/extattr.h 25 Apr 2020 01:09:16 -0000 @@ -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 Index: sys/sys/fstypes.h =================================================================== RCS file: /cvsroot/src/sys/sys/fstypes.h,v retrieving revision 1.38 diff -u -p -u -p -r1.38 fstypes.h --- sys/sys/fstypes.h 4 Apr 2020 20:49:31 -0000 1.38 +++ sys/sys/fstypes.h 25 Apr 2020 01:09:16 -0000 @@ -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" \ Index: sys/sys/kauth.h =================================================================== RCS file: /cvsroot/src/sys/sys/kauth.h,v retrieving revision 1.83 diff -u -p -u -p -r1.83 kauth.h --- sys/sys/kauth.h 14 Feb 2020 04:36:33 -0000 1.83 +++ sys/sys/kauth.h 25 Apr 2020 01:09:16 -0000 @@ -520,11 +520,11 @@ int kauth_cred_uucmp(kauth_cred_t, const 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); Index: sys/sys/namei.h =================================================================== RCS file: /cvsroot/src/sys/sys/namei.h,v retrieving revision 1.108 diff -u -p -u -p -r1.108 namei.h --- sys/sys/namei.h 4 Apr 2020 20:52:18 -0000 1.108 +++ sys/sys/namei.h 25 Apr 2020 01:09:16 -0000 @@ -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. Index: sys/sys/statvfs.h =================================================================== RCS file: /cvsroot/src/sys/sys/statvfs.h,v retrieving revision 1.19 diff -u -p -u -p -r1.19 statvfs.h --- sys/sys/statvfs.h 22 Sep 2019 22:59:40 -0000 1.19 +++ sys/sys/statvfs.h 25 Apr 2020 01:09:16 -0000 @@ -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 Index: sys/sys/syscall.h =================================================================== RCS file: /cvsroot/src/sys/sys/syscall.h,v retrieving revision 1.311 diff -u -p -u -p -r1.311 syscall.h --- sys/sys/syscall.h 22 Apr 2020 21:25:17 -0000 1.311 +++ sys/sys/syscall.h 25 Apr 2020 01:09:16 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: syscall.h,v 1.311 2020/04/22 21:25:17 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call numbers. @@ -1341,6 +1341,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_ */ Index: sys/sys/syscallargs.h =================================================================== RCS file: /cvsroot/src/sys/sys/syscallargs.h,v retrieving revision 1.295 diff -u -p -u -p -r1.295 syscallargs.h --- sys/sys/syscallargs.h 22 Apr 2020 21:25:17 -0000 1.295 +++ sys/sys/syscallargs.h 25 Apr 2020 01:09:16 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: syscallargs.h,v 1.295 2020/04/22 21:25:17 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call argument lists. @@ -14,6 +14,7 @@ #include #include #include +#include #endif #include @@ -3175,6 +3176,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. */ @@ -4057,5 +4169,31 @@ int sys___fstatvfs190(struct lwp *, cons 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_ */ Index: sys/sys/types.h =================================================================== RCS file: /cvsroot/src/sys/sys/types.h,v retrieving revision 1.104 diff -u -p -u -p -r1.104 types.h --- sys/sys/types.h 28 Jan 2020 16:40:27 -0000 1.104 +++ sys/sys/types.h 25 Apr 2020 01:09:16 -0000 @@ -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 Index: sys/sys/unistd.h =================================================================== RCS file: /cvsroot/src/sys/sys/unistd.h,v retrieving revision 1.62 diff -u -p -u -p -r1.62 unistd.h --- sys/sys/unistd.h 16 Oct 2019 20:43:18 -0000 1.62 +++ sys/sys/unistd.h 25 Apr 2020 01:09:16 -0000 @@ -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 . Index: sys/sys/vnode.h =================================================================== RCS file: /cvsroot/src/sys/sys/vnode.h,v retrieving revision 1.295 diff -u -p -u -p -r1.295 vnode.h --- sys/sys/vnode.h 13 Apr 2020 19:23:20 -0000 1.295 +++ sys/sys/vnode.h 25 Apr 2020 01:09:16 -0000 @@ -66,6 +66,7 @@ #include #include #include +#include /* XXX: clean up includes later */ #include /* 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 *, struc 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) Index: sys/sys/vnode_if.h =================================================================== RCS file: /cvsroot/src/sys/sys/vnode_if.h,v retrieving revision 1.104 diff -u -p -u -p -r1.104 vnode_if.h --- sys/sys/vnode_if.h 23 Feb 2020 22:15:18 -0000 1.104 +++ sys/sys/vnode_if.h 25 Apr 2020 01:09:16 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: vnode_if.h,v 1.104 2020/02/23 22:15:18 ad Exp $ */ +/* $NetBSD$ */ /* * Warning: DO NOT EDIT! This file is automatically generated! @@ -117,13 +117,23 @@ int VOP_CLOSE(struct vnode *, int, kauth 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_ren 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_mkd 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_sym 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_rea 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_get 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_get 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_lis 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_set 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_ */ Index: sys/ufs/files.ufs =================================================================== RCS file: /cvsroot/src/sys/ufs/files.ufs,v retrieving revision 1.47 diff -u -p -u -p -r1.47 files.ufs --- sys/ufs/files.ufs 18 Apr 2020 19:18:33 -0000 1.47 +++ sys/ufs/files.ufs 25 Apr 2020 01:09:16 -0000 @@ -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 Index: sys/ufs/chfs/chfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/ufs/chfs/chfs_vnops.c,v retrieving revision 1.38 diff -u -p -u -p -r1.38 chfs_vnops.c --- sys/ufs/chfs/chfs_vnops.c 23 Apr 2020 21:47:08 -0000 1.38 +++ sys/ufs/chfs/chfs_vnops.c 25 Apr 2020 01:09:17 -0000 @@ -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,13 @@ 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->v_type, ip->mode & ALLPERMS, ip->uid, ip->gid, NULL, accmode, + cred)); } /* --------------------------------------------------------------------- */ @@ -1603,6 +1604,7 @@ const struct vnodeopv_entry_desc chfs_vn { &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_sp { &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_fi { &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 }, Index: sys/ufs/ext2fs/ext2fs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_vnops.c,v retrieving revision 1.131 diff -u -p -u -p -r1.131 ext2fs_vnops.c --- sys/ufs/ext2fs/ext2fs_vnops.c 8 Mar 2020 17:38:12 -0000 1.131 +++ sys/ufs/ext2fs/ext2fs_vnops.c 25 Apr 2020 01:09:17 -0000 @@ -232,7 +232,8 @@ ext2fs_check_permitted(struct vnode *vp, 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)); + ip->i_e2fs_mode & ALLPERMS, ip->i_uid, ip->i_gid, NULL, mode, + cred)); } 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); @@ -1101,6 +1102,7 @@ const struct vnodeopv_entry_desc ext2fs_ { &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 +1157,7 @@ const struct vnodeopv_entry_desc ext2fs_ { &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 +1212,7 @@ const struct vnodeopv_entry_desc ext2fs_ { &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 */ Index: sys/ufs/ext2fs/ext2fs_xattr.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_xattr.c,v retrieving revision 1.4 diff -u -p -u -p -r1.4 ext2fs_xattr.c --- sys/ufs/ext2fs/ext2fs_xattr.c 23 Aug 2016 06:40:54 -0000 1.4 +++ sys/ufs/ext2fs/ext2fs_xattr.c 25 Apr 2020 01:09:17 -0000 @@ -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; Index: sys/ufs/ffs/ffs_extattr.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ffs/ffs_extattr.c,v retrieving revision 1.3 diff -u -p -u -p -r1.3 ffs_extattr.c --- sys/ufs/ffs/ffs_extattr.c 20 Apr 2020 18:10:10 -0000 1.3 +++ sys/ufs/ffs/ffs_extattr.c 25 Apr 2020 01:09:17 -0000 @@ -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 @@ -687,7 +659,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); @@ -761,7 +733,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) { @@ -866,7 +838,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); @@ -936,7 +908,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) { /* Index: sys/ufs/ffs/ffs_vfsops.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vfsops.c,v retrieving revision 1.367 diff -u -p -u -p -r1.367 ffs_vfsops.c --- sys/ufs/ffs/ffs_vfsops.c 4 Apr 2020 20:49:31 -0000 1.367 +++ sys/ufs/ffs/ffs_vfsops.c 25 Apr 2020 01:09:17 -0000 @@ -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; + else + mp->mnt_iflag |= IMNT_SHRLOOKUP; +} + /* * VFS Operations. * @@ -612,6 +658,8 @@ ffs_mount(struct mount *mp, const char * 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_ } 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_ 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 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; Index: sys/ufs/ffs/ffs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vnops.c,v retrieving revision 1.131 diff -u -p -u -p -r1.131 ffs_vnops.c --- sys/ufs/ffs/ffs_vnops.c 18 Apr 2020 19:18:34 -0000 1.131 +++ sys/ufs/ffs/ffs_vnops.c 25 Apr 2020 01:09:17 -0000 @@ -88,6 +88,7 @@ __KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c, #include #include +#include #include #include #include @@ -109,7 +110,8 @@ const struct vnodeopv_entry_desc ffs_vno { &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_vno { &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_spe { &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_spe { &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_fif { &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_fif { &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 = Index: sys/ufs/ffs/fs.h =================================================================== RCS file: /cvsroot/src/sys/ufs/ffs/fs.h,v retrieving revision 1.67 diff -u -p -u -p -r1.67 fs.h --- sys/ufs/ffs/fs.h 18 Apr 2020 19:18:34 -0000 1.67 +++ sys/ufs/ffs/fs.h 25 Apr 2020 01:09:17 -0000 @@ -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. Index: sys/ufs/lfs/lfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/ufs/lfs/lfs_vnops.c,v retrieving revision 1.332 diff -u -p -u -p -r1.332 lfs_vnops.c --- sys/ufs/lfs/lfs_vnops.c 13 Apr 2020 19:23:20 -0000 1.332 +++ sys/ufs/lfs/lfs_vnops.c 25 Apr 2020 01:09:17 -0000 @@ -192,6 +192,7 @@ const struct vnodeopv_entry_desc lfs_vno { &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_spe { &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_fif { &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 */ Index: sys/ufs/lfs/ulfs_extattr.c =================================================================== RCS file: /cvsroot/src/sys/ufs/lfs/ulfs_extattr.c,v retrieving revision 1.15 diff -u -p -u -p -r1.15 ulfs_extattr.c --- sys/ufs/lfs/ulfs_extattr.c 17 Jan 2020 20:08:10 -0000 1.15 +++ sys/ufs/lfs/ulfs_extattr.c 25 Apr 2020 01:09:17 -0000 @@ -108,58 +108,6 @@ static int ulfs_extattr_get_header(struc 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; - - /* .\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 a 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 * 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 a 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 at 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); Index: sys/ufs/lfs/ulfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/ufs/lfs/ulfs_vnops.c,v retrieving revision 1.52 diff -u -p -u -p -r1.52 ulfs_vnops.c --- sys/ufs/lfs/ulfs_vnops.c 28 Oct 2017 00:37:13 -0000 1.52 +++ sys/ufs/lfs/ulfs_vnops.c 25 Apr 2020 01:09:17 -0000 @@ -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, st * 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, st 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->v_type, ip->i_mode & ALLPERMS, ip->i_uid, ip->i_gid, NULL, + accmode, cred)); } 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; } Index: sys/ufs/mfs/mfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/ufs/mfs/mfs_vnops.c,v retrieving revision 1.60 diff -u -p -u -p -r1.60 mfs_vnops.c --- sys/ufs/mfs/mfs_vnops.c 13 Apr 2020 19:23:20 -0000 1.60 +++ sys/ufs/mfs/mfs_vnops.c 25 Apr 2020 01:09:17 -0000 @@ -64,6 +64,7 @@ const struct vnodeopv_entry_desc mfs_vno { &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 */ Index: sys/ufs/ufs/README.acls =================================================================== RCS file: sys/ufs/ufs/README.acls diff -N sys/ufs/ufs/README.acls --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/ufs/ufs/README.acls 25 Apr 2020 01:09:17 -0000 @@ -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. Index: sys/ufs/ufs/acl.h =================================================================== RCS file: sys/ufs/ufs/acl.h diff -N sys/ufs/ufs/acl.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/ufs/ufs/acl.h 25 Apr 2020 01:09:17 -0000 @@ -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_ */ Index: sys/ufs/ufs/ufs_acl.c =================================================================== RCS file: sys/ufs/ufs/ufs_acl.c diff -N sys/ufs/ufs/ufs_acl.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/ufs/ufs/ufs_acl.c 25 Apr 2020 01:09:17 -0000 @@ -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 +#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_wapbl.c,v 1.25 2019/12/22 19:47:35 ad Exp $"); + +#if defined(_KERNEL_OPT) +#include "opt_ffs.h" +#include "opt_quota.h" +#include "opt_wapbl.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 */ Index: sys/ufs/ufs/ufs_extattr.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ufs/ufs_extattr.c,v retrieving revision 1.51 diff -u -p -u -p -r1.51 ufs_extattr.c --- sys/ufs/ufs/ufs_extattr.c 17 Jan 2020 20:08:10 -0000 1.51 +++ sys/ufs/ufs/ufs_extattr.c 25 Apr 2020 01:09:17 -0000 @@ -107,57 +107,6 @@ static int ufs_extattr_get_header(struct 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; - - /* .\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 at 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 a * 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 at 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 att 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; Index: sys/ufs/ufs/ufs_extern.h =================================================================== RCS file: /cvsroot/src/sys/ufs/ufs/ufs_extern.h,v retrieving revision 1.85 diff -u -p -u -p -r1.85 ufs_extern.h --- sys/ufs/ufs/ufs_extern.h 18 Apr 2020 19:18:34 -0000 1.85 +++ sys/ufs/ufs/ufs_extern.h 25 Apr 2020 01:09:17 -0000 @@ -61,7 +61,7 @@ extern pool_cache_t ufs_direct_cache; /* __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 *); Index: sys/ufs/ufs/ufs_lookup.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ufs/ufs_lookup.c,v retrieving revision 1.152 diff -u -p -u -p -r1.152 ufs_lookup.c --- sys/ufs/ufs/ufs_lookup.c 4 Apr 2020 20:49:31 -0000 1.152 +++ sys/ufs/ufs/ufs_lookup.c 25 Apr 2020 01:09:17 -0000 @@ -211,6 +211,38 @@ ufs_can_delete(struct vnode *tdp, struct 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. */ @@ -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_ACCESS(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. Index: sys/ufs/ufs/ufs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ufs/ufs_vnops.c,v retrieving revision 1.252 diff -u -p -u -p -r1.252 ufs_vnops.c --- sys/ufs/ufs/ufs_vnops.c 18 Apr 2020 19:18:34 -0000 1.252 +++ sys/ufs/ufs/ufs_vnops.c 25 Apr 2020 01:09:17 -0000 @@ -95,6 +95,7 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c, #include #include +#include #include #include #include @@ -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, str * 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, str /* 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)(enum vtype, mode_t, uid_t, gid_t, struct acl *, accmode_t, + kauth_cred_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->v_type, + ip->i_mode & ALLPERMS, ip->i_uid, ip->i_gid, acl, accmode, cred)); } 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 */ @@ -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, ka 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)); 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,6 +766,15 @@ ufs_chown(struct vnode *vp, uid_t uid, g 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)); if (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); @@ -1909,6 +2264,20 @@ ufs_makeinode(struct vattr *vap, struct */ 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);