Index: bin/Makefile =================================================================== RCS file: /cvsroot/src/bin/Makefile,v retrieving revision 1.22 diff -u -p -p -u -r1.22 Makefile --- bin/Makefile 31 Dec 2007 15:31:24 -0000 1.22 +++ bin/Makefile 16 May 2020 16:13:47 -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 -p -u -r1.59 cp.c --- bin/cp/cp.c 5 Mar 2016 19:48:55 -0000 1.59 +++ bin/cp/cp.c 16 May 2020 16:13:47 -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 -p -u -r1.17 extern.h --- bin/cp/extern.h 4 Jan 2012 15:58:37 -0000 1.17 +++ bin/cp/extern.h 16 May 2020 16:13:47 -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 -p -u -r1.47 utils.c --- bin/cp/utils.c 23 Sep 2019 18:01:09 -0000 1.47 +++ bin/cp/utils.c 16 May 2020 16:13:47 -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 16 May 2020 16:13:47 -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 16 May 2020 16:13:47 -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 16 May 2020 16:13:47 -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 -p -u -r1.80 ls.1 --- bin/ls/ls.1 3 Jul 2017 21:33:23 -0000 1.80 +++ bin/ls/ls.1 16 May 2020 16:13:47 -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 -p -u -r1.55 print.c --- bin/ls/print.c 10 May 2014 09:39:18 -0000 1.55 +++ bin/ls/print.c 16 May 2020 16:13:47 -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 (supports_acls == -1 || previous_dev != p->fts_statp->st_dev) { + previous_dev = p->fts_statp->st_dev; + supports_acls = 0; + + ret = lpathconf(name, _PC_ACL_NFS4); + if (ret > 0) { + type = ACL_TYPE_NFS4; + supports_acls = 1; + } else if (ret < 0 && errno != EINVAL) { + warn("%s", name); + return; + } + if (supports_acls == 0) { + ret = lpathconf(name, _PC_ACL_EXTENDED); + if (ret > 0) { + type = ACL_TYPE_ACCESS; + supports_acls = 1; + } else if (ret < 0 && errno != EINVAL) { + warn("%s", name); + return; + } + } + } + if (supports_acls == 0) + return; + facl = acl_get_link_np(name, type); + if (facl == NULL) { + warn("%s", name); + return; + } + if (acl_is_trivial_np(facl, &trivial)) { + acl_free(facl); + warn("%s", name); + return; + } + if (!trivial) + buf[10] = '+'; + acl_free(facl); +} 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 16 May 2020 16:13:47 -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 16 May 2020 16:13:47 -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 16 May 2020 16:13:47 -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 16 May 2020 16:13:47 -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 16 May 2020 16:13:47 -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 16 May 2020 16:13:47 -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 16 May 2020 16:13:48 -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 16 May 2020 16:13:48 -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 16 May 2020 16:13:48 -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.1242 diff -u -p -p -u -r1.1242 mi --- distrib/sets/lists/base/mi 1 May 2020 22:25:18 -0000 1.1242 +++ distrib/sets/lists/base/mi 16 May 2020 16:13:48 -0000 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1242 2020/05/01 22:25:18 christos Exp $ +# $NetBSD: mi,v 1.1241 2020/04/25 12:18:47 kre Exp $ # # Note: Don't delete entries from here - mark them as "obsolete" instead, # unless otherwise stated below. @@ -33,6 +33,7 @@ ./bin/echo base-util-root ./bin/ed base-util-root ./bin/expr base-util-root +./bin/getfacl base-util-root ./bin/hostname base-util-root ./bin/kill base-util-root ./bin/ksh base-util-root @@ -51,6 +52,7 @@ ./bin/rmail base-obsolete obsolete ./bin/rmdir base-util-root ./bin/rump.dd base-util-root rump +./bin/setfacl base-util-root ./bin/sh base-util-root ./bin/sleep base-util-root ./bin/stty base-util-root Index: distrib/sets/lists/comp/mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/comp/mi,v retrieving revision 1.2326 diff -u -p -p -u -r1.2326 mi --- distrib/sets/lists/comp/mi 15 May 2020 23:32:27 -0000 1.2326 +++ distrib/sets/lists/comp/mi 16 May 2020 16:13:50 -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 @@ -3493,10 +3494,10 @@ ./usr/lib/libexecinfo_p.a comp-c-proflib compatfile,profile ./usr/lib/libexpat.a comp-c-lib compatfile ./usr/lib/libexpat_p.a comp-c-proflib compatfile,profile -./usr/lib/libfido2.a comp-c-lib compatfile -./usr/lib/libfido2_p.a comp-c-proflib compatfile,profile ./usr/lib/libfetch.a comp-c-lib compatfile ./usr/lib/libfetch_p.a comp-c-proflib compatfile,profile +./usr/lib/libfido2.a comp-c-lib compatfile +./usr/lib/libfido2_p.a comp-c-proflib compatfile,profile ./usr/lib/libfl.a comp-c-lib compatfile ./usr/lib/libfl_p.a comp-c-proflib compatfile,profile ./usr/lib/libform.a comp-c-lib compatfile @@ -5561,6 +5562,58 @@ ./usr/share/man/cat3/a64l.0 comp-c-catman .cat ./usr/share/man/cat3/abort.0 comp-c-catman .cat ./usr/share/man/cat3/abs.0 comp-c-catman .cat +./usr/share/man/cat3/acl.0 comp-c-catman .cat +./usr/share/man/cat3/acl_add_flag_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_add_perm.0 comp-c-catman .cat +./usr/share/man/cat3/acl_calc_mask.0 comp-c-catman .cat +./usr/share/man/cat3/acl_clear_flags_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_clear_perms.0 comp-c-catman .cat +./usr/share/man/cat3/acl_copy_entry.0 comp-c-catman .cat +./usr/share/man/cat3/acl_create_entry.0 comp-c-catman .cat +./usr/share/man/cat3/acl_create_entry_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_delete.0 comp-c-catman .cat +./usr/share/man/cat3/acl_delete_def_file.0 comp-c-catman .cat +./usr/share/man/cat3/acl_delete_entry.0 comp-c-catman .cat +./usr/share/man/cat3/acl_delete_entry_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_delete_fd_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_delete_file_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_delete_flag_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_delete_perm.0 comp-c-catman .cat +./usr/share/man/cat3/acl_dup.0 comp-c-catman .cat +./usr/share/man/cat3/acl_free.0 comp-c-catman .cat +./usr/share/man/cat3/acl_from_text.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_brand_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_entry.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_entry_type_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_fd.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_fd_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_file.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_flag_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_flagset_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_link_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_perm_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_permset.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_qualifier.0 comp-c-catman .cat +./usr/share/man/cat3/acl_get_tag_type.0 comp-c-catman .cat +./usr/share/man/cat3/acl_init.0 comp-c-catman .cat +./usr/share/man/cat3/acl_is_trivial_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_set.0 comp-c-catman .cat +./usr/share/man/cat3/acl_set_entry_type_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_set_fd.0 comp-c-catman .cat +./usr/share/man/cat3/acl_set_fd_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_set_file.0 comp-c-catman .cat +./usr/share/man/cat3/acl_set_flagset_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_set_link_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_set_permset.0 comp-c-catman .cat +./usr/share/man/cat3/acl_set_qualifier.0 comp-c-catman .cat +./usr/share/man/cat3/acl_set_tag_type.0 comp-c-catman .cat +./usr/share/man/cat3/acl_strip_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_to_text.0 comp-c-catman .cat +./usr/share/man/cat3/acl_to_text_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_valid.0 comp-c-catman .cat +./usr/share/man/cat3/acl_valid_fd_np.0 comp-c-catman .cat +./usr/share/man/cat3/acl_valid_file_np.0 comp-c-catman .cat ./usr/share/man/cat3/acos.0 comp-c-catman .cat ./usr/share/man/cat3/acosf.0 comp-c-catman .cat ./usr/share/man/cat3/acosh.0 comp-c-catman .cat @@ -8872,6 +8925,7 @@ ./usr/share/man/cat3/popenve.0 comp-c-catman .cat ./usr/share/man/cat3/pos_form_cursor.0 comp-c-catman .cat ./usr/share/man/cat3/pos_menu_cursor.0 comp-c-catman .cat +./usr/share/man/cat3/posix1e.0 comp-c-catman .cat ./usr/share/man/cat3/posix2time.0 comp-c-catman .cat ./usr/share/man/cat3/posix2time_z.0 comp-c-catman .cat ./usr/share/man/cat3/posix_memalign.0 comp-c-catman .cat @@ -13650,6 +13704,58 @@ ./usr/share/man/html3/a64l.html comp-c-htmlman html ./usr/share/man/html3/abort.html comp-c-htmlman html ./usr/share/man/html3/abs.html comp-c-htmlman html +./usr/share/man/html3/acl.html comp-c-htmlman html +./usr/share/man/html3/acl_add_flag_np.html comp-c-htmlman html +./usr/share/man/html3/acl_add_perm.html comp-c-htmlman html +./usr/share/man/html3/acl_calc_mask.html comp-c-htmlman html +./usr/share/man/html3/acl_clear_flags_np.html comp-c-htmlman html +./usr/share/man/html3/acl_clear_perms.html comp-c-htmlman html +./usr/share/man/html3/acl_copy_entry.html comp-c-htmlman html +./usr/share/man/html3/acl_create_entry.html comp-c-htmlman html +./usr/share/man/html3/acl_create_entry_np.html comp-c-htmlman html +./usr/share/man/html3/acl_delete.html comp-c-htmlman html +./usr/share/man/html3/acl_delete_def_file.html comp-c-htmlman html +./usr/share/man/html3/acl_delete_entry.html comp-c-htmlman html +./usr/share/man/html3/acl_delete_entry_np.html comp-c-htmlman html +./usr/share/man/html3/acl_delete_fd_np.html comp-c-htmlman html +./usr/share/man/html3/acl_delete_file_np.html comp-c-htmlman html +./usr/share/man/html3/acl_delete_flag_np.html comp-c-htmlman html +./usr/share/man/html3/acl_delete_perm.html comp-c-htmlman html +./usr/share/man/html3/acl_dup.html comp-c-htmlman html +./usr/share/man/html3/acl_free.html comp-c-htmlman html +./usr/share/man/html3/acl_from_text.html comp-c-htmlman html +./usr/share/man/html3/acl_get.html comp-c-htmlman html +./usr/share/man/html3/acl_get_brand_np.html comp-c-htmlman html +./usr/share/man/html3/acl_get_entry.html comp-c-htmlman html +./usr/share/man/html3/acl_get_entry_type_np.html comp-c-htmlman html +./usr/share/man/html3/acl_get_fd.html comp-c-htmlman html +./usr/share/man/html3/acl_get_fd_np.html comp-c-htmlman html +./usr/share/man/html3/acl_get_file.html comp-c-htmlman html +./usr/share/man/html3/acl_get_flag_np.html comp-c-htmlman html +./usr/share/man/html3/acl_get_flagset_np.html comp-c-htmlman html +./usr/share/man/html3/acl_get_link_np.html comp-c-htmlman html +./usr/share/man/html3/acl_get_perm_np.html comp-c-htmlman html +./usr/share/man/html3/acl_get_permset.html comp-c-htmlman html +./usr/share/man/html3/acl_get_qualifier.html comp-c-htmlman html +./usr/share/man/html3/acl_get_tag_type.html comp-c-htmlman html +./usr/share/man/html3/acl_init.html comp-c-htmlman html +./usr/share/man/html3/acl_is_trivial_np.html comp-c-htmlman html +./usr/share/man/html3/acl_set.html comp-c-htmlman html +./usr/share/man/html3/acl_set_entry_type_np.html comp-c-htmlman html +./usr/share/man/html3/acl_set_fd.html comp-c-htmlman html +./usr/share/man/html3/acl_set_fd_np.html comp-c-htmlman html +./usr/share/man/html3/acl_set_file.html comp-c-htmlman html +./usr/share/man/html3/acl_set_flagset_np.html comp-c-htmlman html +./usr/share/man/html3/acl_set_link_np.html comp-c-htmlman html +./usr/share/man/html3/acl_set_permset.html comp-c-htmlman html +./usr/share/man/html3/acl_set_qualifier.html comp-c-htmlman html +./usr/share/man/html3/acl_set_tag_type.html comp-c-htmlman html +./usr/share/man/html3/acl_strip_np.html comp-c-htmlman html +./usr/share/man/html3/acl_to_text.html comp-c-htmlman html +./usr/share/man/html3/acl_to_text_np.html comp-c-htmlman html +./usr/share/man/html3/acl_valid.html comp-c-htmlman html +./usr/share/man/html3/acl_valid_fd_np.html comp-c-htmlman html +./usr/share/man/html3/acl_valid_file_np.html comp-c-htmlman html ./usr/share/man/html3/acos.html comp-c-htmlman html ./usr/share/man/html3/acosf.html comp-c-htmlman html ./usr/share/man/html3/acosh.html comp-c-htmlman html @@ -16902,6 +17008,7 @@ ./usr/share/man/html3/popenve.html comp-c-htmlman html ./usr/share/man/html3/pos_form_cursor.html comp-c-htmlman html ./usr/share/man/html3/pos_menu_cursor.html comp-c-htmlman html +./usr/share/man/html3/posix1e.html comp-c-htmlman html ./usr/share/man/html3/posix2time.html comp-c-htmlman html ./usr/share/man/html3/posix2time_z.html comp-c-htmlman html ./usr/share/man/html3/posix_memalign.html comp-c-htmlman html @@ -21576,6 +21683,58 @@ ./usr/share/man/man3/a64l.3 comp-c-man .man ./usr/share/man/man3/abort.3 comp-c-man .man ./usr/share/man/man3/abs.3 comp-c-man .man +./usr/share/man/man3/acl.3 comp-c-man .man +./usr/share/man/man3/acl_add_flag_np.3 comp-c-man .man +./usr/share/man/man3/acl_add_perm.3 comp-c-man .man +./usr/share/man/man3/acl_calc_mask.3 comp-c-man .man +./usr/share/man/man3/acl_clear_flags_np.3 comp-c-man .man +./usr/share/man/man3/acl_clear_perms.3 comp-c-man .man +./usr/share/man/man3/acl_copy_entry.3 comp-c-man .man +./usr/share/man/man3/acl_create_entry.3 comp-c-man .man +./usr/share/man/man3/acl_create_entry_np.3 comp-c-man .man +./usr/share/man/man3/acl_delete.3 comp-c-man .man +./usr/share/man/man3/acl_delete_def_file.3 comp-c-man .man +./usr/share/man/man3/acl_delete_entry.3 comp-c-man .man +./usr/share/man/man3/acl_delete_entry_np.3 comp-c-man .man +./usr/share/man/man3/acl_delete_fd_np.3 comp-c-man .man +./usr/share/man/man3/acl_delete_file_np.3 comp-c-man .man +./usr/share/man/man3/acl_delete_flag_np.3 comp-c-man .man +./usr/share/man/man3/acl_delete_perm.3 comp-c-man .man +./usr/share/man/man3/acl_dup.3 comp-c-man .man +./usr/share/man/man3/acl_free.3 comp-c-man .man +./usr/share/man/man3/acl_from_text.3 comp-c-man .man +./usr/share/man/man3/acl_get.3 comp-c-man .man +./usr/share/man/man3/acl_get_brand_np.3 comp-c-man .man +./usr/share/man/man3/acl_get_entry.3 comp-c-man .man +./usr/share/man/man3/acl_get_entry_type_np.3 comp-c-man .man +./usr/share/man/man3/acl_get_fd.3 comp-c-man .man +./usr/share/man/man3/acl_get_fd_np.3 comp-c-man .man +./usr/share/man/man3/acl_get_file.3 comp-c-man .man +./usr/share/man/man3/acl_get_flag_np.3 comp-c-man .man +./usr/share/man/man3/acl_get_flagset_np.3 comp-c-man .man +./usr/share/man/man3/acl_get_link_np.3 comp-c-man .man +./usr/share/man/man3/acl_get_perm_np.3 comp-c-man .man +./usr/share/man/man3/acl_get_permset.3 comp-c-man .man +./usr/share/man/man3/acl_get_qualifier.3 comp-c-man .man +./usr/share/man/man3/acl_get_tag_type.3 comp-c-man .man +./usr/share/man/man3/acl_init.3 comp-c-man .man +./usr/share/man/man3/acl_is_trivial_np.3 comp-c-man .man +./usr/share/man/man3/acl_set.3 comp-c-man .man +./usr/share/man/man3/acl_set_entry_type_np.3 comp-c-man .man +./usr/share/man/man3/acl_set_fd.3 comp-c-man .man +./usr/share/man/man3/acl_set_fd_np.3 comp-c-man .man +./usr/share/man/man3/acl_set_file.3 comp-c-man .man +./usr/share/man/man3/acl_set_flagset_np.3 comp-c-man .man +./usr/share/man/man3/acl_set_link_np.3 comp-c-man .man +./usr/share/man/man3/acl_set_permset.3 comp-c-man .man +./usr/share/man/man3/acl_set_qualifier.3 comp-c-man .man +./usr/share/man/man3/acl_set_tag_type.3 comp-c-man .man +./usr/share/man/man3/acl_strip_np.3 comp-c-man .man +./usr/share/man/man3/acl_to_text.3 comp-c-man .man +./usr/share/man/man3/acl_to_text_np.3 comp-c-man .man +./usr/share/man/man3/acl_valid.3 comp-c-man .man +./usr/share/man/man3/acl_valid_fd_np.3 comp-c-man .man +./usr/share/man/man3/acl_valid_file_np.3 comp-c-man .man ./usr/share/man/man3/acos.3 comp-c-man .man ./usr/share/man/man3/acosf.3 comp-c-man .man ./usr/share/man/man3/acosh.3 comp-c-man .man @@ -24922,6 +25081,7 @@ ./usr/share/man/man3/popenve.3 comp-c-man .man ./usr/share/man/man3/pos_form_cursor.3 comp-c-man .man ./usr/share/man/man3/pos_menu_cursor.3 comp-c-man .man +./usr/share/man/man3/posix1e.3 comp-c-man .man ./usr/share/man/man3/posix2time.3 comp-c-man .man ./usr/share/man/man3/posix2time_z.3 comp-c-man .man ./usr/share/man/man3/posix_memalign.3 comp-c-man .man @@ -26483,8 +26643,8 @@ ./usr/share/man/man3/wdelch.3 comp-c-man .man ./usr/share/man/man3/wdeleteln.3 comp-c-man .man ./usr/share/man/man3/wechochar.3 comp-c-man .man -./usr/share/man/man3/werase.3 comp-c-man .man ./usr/share/man/man3/wenclose.3 comp-c-man .man +./usr/share/man/man3/werase.3 comp-c-man .man ./usr/share/man/man3/wgetch.3 comp-c-man .man ./usr/share/man/man3/wgetnstr.3 comp-c-man .man ./usr/share/man/man3/wgetstr.3 comp-c-man .man Index: distrib/sets/lists/debug/mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/debug/mi,v retrieving revision 1.310 diff -u -p -p -u -r1.310 mi --- distrib/sets/lists/debug/mi 15 May 2020 23:32:28 -0000 1.310 +++ distrib/sets/lists/debug/mi 16 May 2020 16:13:50 -0000 @@ -287,6 +287,7 @@ ./usr/libdata/debug/bin/echo.debug comp-util-debug debug ./usr/libdata/debug/bin/ed.debug comp-util-debug debug ./usr/libdata/debug/bin/expr.debug comp-util-debug debug +./usr/libdata/debug/bin/getfacl.debug comp-util-debug debug ./usr/libdata/debug/bin/hostname.debug comp-util-debug debug ./usr/libdata/debug/bin/kill.debug comp-util-debug debug ./usr/libdata/debug/bin/ksh.debug comp-util-debug debug @@ -303,6 +304,7 @@ ./usr/libdata/debug/bin/rm.debug comp-util-debug debug ./usr/libdata/debug/bin/rmdir.debug comp-util-debug debug ./usr/libdata/debug/bin/rump.dd.debug comp-util-debug debug,rump +./usr/libdata/debug/bin/setfacl.debug comp-util-debug debug ./usr/libdata/debug/bin/sh.debug comp-util-debug debug ./usr/libdata/debug/bin/sleep.debug comp-util-debug debug ./usr/libdata/debug/bin/stty.debug comp-util-debug debug Index: distrib/sets/lists/man/mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/man/mi,v retrieving revision 1.1687 diff -u -p -p -u -r1.1687 mi --- distrib/sets/lists/man/mi 12 Apr 2020 01:10:53 -0000 1.1687 +++ distrib/sets/lists/man/mi 16 May 2020 16:13:50 -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 -p -u -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 16 May 2020 16:13:52 -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 -p -u -r1.11 Makefile --- external/bsd/libarchive/lib/libarchive/Makefile 13 Oct 2019 07:28:06 -0000 1.11 +++ external/bsd/libarchive/lib/libarchive/Makefile 16 May 2020 16:13:52 -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 -p -u -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 16 May 2020 16:13:55 -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.66 diff -u -p -p -u -r1.66 zfs_vnops.c --- external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c 13 May 2020 05:52:54 -0000 1.66 +++ external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c 16 May 2020 16:13:55 -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; @@ -5631,8 +5631,7 @@ zfs_netbsd_setattr(void *v) } error = kauth_authorize_vnode(cred, action, vp, NULL, - genfs_can_chflags(cred, vp->v_type, zp->z_uid, - changing_sysflags)); + genfs_can_chflags(vp, cred, zp->z_uid, changing_sysflags)); if (error) return error; } @@ -5640,8 +5639,8 @@ zfs_netbsd_setattr(void *v) if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || vap->va_birthtime.tv_sec != VNOVAL) { error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, - NULL, genfs_can_chtimes(vp, vap->va_vaflags, zp->z_uid, - cred)); + NULL, genfs_can_chtimes(vp, cred, zp->z_uid, + vap->va_vaflags)); if (error) return error; } @@ -6332,6 +6331,7 @@ const struct vnodeopv_entry_desc zfs_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 }, @@ -6377,6 +6377,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 }, @@ -6424,6 +6425,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 -p -u -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 16 May 2020 16:13:55 -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 -p -u -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 16 May 2020 16:13:55 -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 -p -u -r1.18 mntopts.h --- include/mntopts.h 9 Jan 2018 03:31:12 -0000 1.18 +++ include/mntopts.h 16 May 2020 16:14:02 -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.157 diff -u -p -p -u -r1.157 unistd.h --- include/unistd.h 6 May 2020 16:17:36 -0000 1.157 +++ include/unistd.h 16 May 2020 16:14:02 -0000 @@ -361,6 +361,7 @@ __aconst char *getusershell(void); int initgroups(const char *, gid_t); int iruserok(uint32_t, int, const char *, const char *); int issetugid(void); +long lpathconf(const char *, int); int mkstemps(char *, int); int nfssvc(int, void *); int pipe2(int *, int); Index: lib/libc/Makefile =================================================================== RCS file: /cvsroot/src/lib/libc/Makefile,v retrieving revision 1.172 diff -u -p -p -u -r1.172 Makefile --- lib/libc/Makefile 3 Aug 2018 14:01:21 -0000 1.172 +++ lib/libc/Makefile 16 May 2020 16:14:03 -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/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 16 May 2020 16:14:03 -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 16 May 2020 16:14:03 -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 16 May 2020 16:14:03 -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 16 May 2020 16:14:03 -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 16 May 2020 16:14:03 -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 16 May 2020 16:14:03 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 16 May 2020 16:14:04 -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 -p -u -r1.242 Makefile.inc --- lib/libc/sys/Makefile.inc 22 Sep 2019 22:59:38 -0000 1.242 +++ lib/libc/sys/Makefile.inc 16 May 2020 16:14:04 -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 -p -u -r1.26 makelintstub --- lib/libc/sys/makelintstub 3 Apr 2016 00:48:29 -0000 1.26 +++ lib/libc/sys/makelintstub 16 May 2020 16:14:04 -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 -p -u -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 16 May 2020 16:14:05 -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 -p -u -r1.44 tunefs.8 --- sbin/tunefs/tunefs.8 9 Aug 2014 10:41:05 -0000 1.44 +++ sbin/tunefs/tunefs.8 16 May 2020 16:14:05 -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 NFSv4 ACL enable flag. .It Fl e Ar maxbpg This indicates the maximum number of blocks any single file can allocate out of a cylinder group before it is forced to begin @@ -130,6 +134,8 @@ running out of full sized blocks. For values of minfree greater than or equal to 5%, fragmentation is unlikely to be problematical, and the file system can be optimized for time. +.It Fl p Cm enable | disable +Turn on/off the administrative POSIX.1e ACL enable flag. .Pp .Ar optimize_preference can be specified as either Index: sbin/tunefs/tunefs.c =================================================================== RCS file: /cvsroot/src/sbin/tunefs/tunefs.c,v retrieving revision 1.51 diff -u -p -p -u -r1.51 tunefs.c --- sbin/tunefs/tunefs.c 9 Apr 2020 14:44:38 -0000 1.51 +++ sbin/tunefs/tunefs.c 16 May 2020 16:14:05 -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'\n"); fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); fprintf(stderr, "\t-g average file size\n"); fprintf(stderr, "\t-h expected number of files per directory\n"); fprintf(stderr, "\t-l journal log file size (`0' to clear journal)\n"); fprintf(stderr, "\t-m minimum percentage of free space\n"); + fprintf(stderr, "\t-p POSIX.1e ACLS: `enable' or `disable'\n"); fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); fprintf(stderr, "\t-q quota type (`[no]user' or `[no]group')\n"); fprintf(stderr, "\t-S sector size\n"); Index: sys/arch/amd64/amd64/genassym.cf =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/genassym.cf,v retrieving revision 1.84 diff -u -p -p -u -r1.84 genassym.cf --- sys/arch/amd64/amd64/genassym.cf 2 May 2020 16:44:34 -0000 1.84 +++ sys/arch/amd64/amd64/genassym.cf 16 May 2020 16:14:05 -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.567 diff -u -p -p -u -r1.567 GENERIC --- sys/arch/amd64/conf/GENERIC 2 May 2020 16:44:35 -0000 1.567 +++ sys/arch/amd64/conf/GENERIC 16 May 2020 16:14:05 -0000 @@ -197,6 +197,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 -p -u -r1.111 coda_vnops.c --- sys/coda/coda_vnops.c 13 Apr 2020 19:23:17 -0000 1.111 +++ sys/coda/coda_vnops.c 16 May 2020 16:14:06 -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/compat/netbsd32/files.netbsd32 =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/files.netbsd32,v retrieving revision 1.51 diff -u -p -p -u -r1.51 files.netbsd32 --- sys/compat/netbsd32/files.netbsd32 26 Apr 2020 18:53:33 -0000 1.51 +++ sys/compat/netbsd32/files.netbsd32 16 May 2020 16:14:06 -0000 @@ -10,6 +10,7 @@ define compat_netbsd32 #makeoptions drmkms CPPFLAGS+="-DNETBSD32_DRMKMS" +file compat/netbsd32/netbsd32_acl.c compat_netbsd32 file compat/netbsd32/netbsd32_core.c compat_netbsd32 & coredump file compat/netbsd32/netbsd32_exec_elf32.c compat_netbsd32 & exec_elf32 file compat/netbsd32/netbsd32_exec_aout.c compat_netbsd32 & exec_aout Index: sys/compat/netbsd32/netbsd32.h =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32.h,v retrieving revision 1.132 diff -u -p -p -u -r1.132 netbsd32.h --- sys/compat/netbsd32/netbsd32.h 24 Dec 2019 14:50:59 -0000 1.132 +++ sys/compat/netbsd32/netbsd32.h 16 May 2020 16:14:06 -0000 @@ -190,6 +190,7 @@ typedef netbsd32_pointer_t netbsd32_cadd typedef netbsd32_pointer_t netbsd32_lwpctlp; typedef netbsd32_pointer_t netbsd32_pid_tp; typedef netbsd32_pointer_t netbsd32_psetidp_t; +typedef netbsd32_pointer_t netbsd32_aclp_t; /* * now, the compatibility structures and their fake pointer types. Index: sys/compat/netbsd32/netbsd32_acl.c =================================================================== RCS file: sys/compat/netbsd32/netbsd32_acl.c diff -N sys/compat/netbsd32/netbsd32_acl.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/compat/netbsd32/netbsd32_acl.c 16 May 2020 16:14:06 -0000 @@ -0,0 +1,216 @@ +/* $NetBSD: netbsd32_acl.c,v 1.1 2020/04/26 18:53:33 christos Exp $ */ + +/*- + * Copyright (c) 2020 The NetBSD Foundation. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: netbsd32_acl.c,v 1.1 2020/04/26 18:53:33 christos Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Syscalls conversion */ +int +netbsd32___acl_get_file(struct lwp *l, + const struct netbsd32___acl_get_file_args *uap, register_t *retval) +{ + + return kern___acl_get_path(l, SCARG_P32(uap, path), SCARG(uap, type), + SCARG_P32(uap, aclp), NSM_FOLLOW_NOEMULROOT); +} + +/* + * Given a file path, get an ACL for it; don't follow links. + */ +int +netbsd32___acl_get_link(struct lwp *l, + const struct netbsd32___acl_get_link_args *uap, register_t *retval) +{ + + return kern___acl_get_path(l, SCARG_P32(uap, path), SCARG(uap, type), + SCARG_P32(uap, aclp), NSM_NOFOLLOW_NOEMULROOT); +} + +/* + * Given a file path, set an ACL for it. + */ +int +netbsd32___acl_set_file(struct lwp *l, + const struct netbsd32___acl_set_file_args *uap, register_t *retval) +{ + + return kern___acl_set_path(l, SCARG_P32(uap, path), SCARG(uap, type), + SCARG_P32(uap, aclp), NSM_FOLLOW_NOEMULROOT); +} + +/* + * Given a file path, set an ACL for it; don't follow links. + */ +int +netbsd32___acl_set_link(struct lwp *l, + const struct netbsd32___acl_set_link_args *uap, register_t *retval) +{ + + return kern___acl_set_path(l, SCARG_P32(uap, path), SCARG(uap, type), + SCARG_P32(uap, aclp), NSM_NOFOLLOW_NOEMULROOT); +} + +/* + * Given a file descriptor, get an ACL for it. + */ +int +netbsd32___acl_get_fd(struct lwp *l, + const struct netbsd32___acl_get_fd_args *uap, register_t *retval) +{ + struct file *fp; + int error; + error = fd_getvnode(SCARG(uap, filedes), &fp); + if (error == 0) { + error = vacl_get_acl(l, fp->f_vnode, SCARG(uap, type), + SCARG_P32(uap, aclp)); + fd_putfile(SCARG(uap, filedes)); + } + return error; +} + +/* + * Given a file descriptor, set an ACL for it. + */ +int +netbsd32___acl_set_fd(struct lwp *l, + const struct netbsd32___acl_set_fd_args *uap, register_t *retval) +{ + struct file *fp; + int error; + + error = fd_getvnode(SCARG(uap, filedes), &fp); + if (error == 0) { + error = vacl_set_acl(l, fp->f_vnode, SCARG(uap, type), + SCARG_P32(uap, aclp)); + fd_putfile(SCARG(uap, filedes)); + } + return error; +} + +/* + * Given a file path, delete an ACL from it. + */ +int +netbsd32___acl_delete_file(struct lwp *l, + const struct netbsd32___acl_delete_file_args *uap, register_t *retval) +{ + + return kern___acl_delete_path(l, SCARG_P32(uap, path), SCARG(uap, type), + NSM_FOLLOW_NOEMULROOT); +} + +/* + * Given a file path, delete an ACL from it; don't follow links. + */ +int +netbsd32___acl_delete_link(struct lwp *l, + const struct netbsd32___acl_delete_link_args *uap, register_t *retval) +{ + return kern___acl_delete_path(l, SCARG_P32(uap, path), SCARG(uap, type), + NSM_NOFOLLOW_NOEMULROOT); +} + +/* + * Given a file path, delete an ACL from it. + */ +int +netbsd32___acl_delete_fd(struct lwp *l, + const struct netbsd32___acl_delete_fd_args *uap, register_t *retval) +{ + struct file *fp; + int error; + + error = fd_getvnode(SCARG(uap, filedes), &fp); + if (error == 0) { + error = vacl_delete(l, fp->f_vnode, SCARG(uap, type)); + fd_putfile(SCARG(uap, filedes)); + } + return error; +} + +/* + * Given a file path, check an ACL for it. + */ +int +netbsd32___acl_aclcheck_file(struct lwp *l, + const struct netbsd32___acl_aclcheck_file_args *uap, register_t *retval) +{ + + return kern___acl_aclcheck_path(l, SCARG_P32(uap, path), + SCARG(uap, type), SCARG_P32(uap, aclp), NSM_FOLLOW_NOEMULROOT); +} + +/* + * Given a file path, check an ACL for it; don't follow links. + */ +int +netbsd32___acl_aclcheck_link(struct lwp *l, + const struct netbsd32___acl_aclcheck_link_args *uap, register_t *retval) +{ + + return kern___acl_aclcheck_path(l, SCARG_P32(uap, path), + SCARG(uap, type), SCARG_P32(uap, aclp), NSM_NOFOLLOW_NOEMULROOT); +} + +/* + * Given a file descriptor, check an ACL for it. + */ +int +netbsd32___acl_aclcheck_fd(struct lwp *l, + const struct netbsd32___acl_aclcheck_fd_args *uap, register_t *retval) +{ + struct file *fp; + int error; + + error = fd_getvnode(SCARG(uap, filedes), &fp); + if (error == 0) { + error = vacl_aclcheck(l, fp->f_vnode, SCARG(uap, type), + SCARG_P32(uap, aclp)); + fd_putfile(SCARG(uap, filedes)); + } + return error; +} Index: sys/compat/netbsd32/netbsd32_netbsd.c =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_netbsd.c,v retrieving revision 1.228 diff -u -p -p -u -r1.228 netbsd32_netbsd.c --- sys/compat/netbsd32/netbsd32_netbsd.c 20 Jun 2019 03:31:54 -0000 1.228 +++ sys/compat/netbsd32/netbsd32_netbsd.c 16 May 2020 16:14:06 -0000 @@ -1253,6 +1253,21 @@ netbsd32_seteuid(struct lwp *l, const st } int +netbsd32_lpathconf(struct lwp *l, const struct netbsd32_lpathconf_args *uap, register_t *retval) +{ + /* { + syscallarg(netbsd32_charp) path; + syscallarg(int) name; + } */ + struct sys_lpathconf_args ua; + + NETBSD32TOP_UAP(path, const char); + NETBSD32TO64_UAP(name); + + return sys_lpathconf(l, &ua, retval); +} + +int netbsd32_pathconf(struct lwp *l, const struct netbsd32_pathconf_args *uap, register_t *retval) { /* { Index: sys/compat/netbsd32/netbsd32_syscall.h =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_syscall.h,v retrieving revision 1.153 diff -u -p -p -u -r1.153 netbsd32_syscall.h --- sys/compat/netbsd32/netbsd32_syscall.h 26 Apr 2020 19:18:52 -0000 1.153 +++ sys/compat/netbsd32/netbsd32_syscall.h 16 May 2020 16:14:06 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_syscall.h,v 1.153 2020/04/26 19:18:52 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call numbers. @@ -1284,6 +1284,45 @@ /* syscall: "netbsd32___fhstatvfs190" ret: "int" args: "netbsd32_voidp" "netbsd32_size_t" "netbsd32_statvfsp_t" "int" */ #define NETBSD32_SYS_netbsd32___fhstatvfs190 486 -#define NETBSD32_SYS_MAXSYSCALL 487 +/* syscall: "netbsd32___acl_get_link" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */ +#define NETBSD32_SYS_netbsd32___acl_get_link 487 + +/* syscall: "netbsd32___acl_set_link" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */ +#define NETBSD32_SYS_netbsd32___acl_set_link 488 + +/* syscall: "netbsd32___acl_delete_link" ret: "int" args: "const netbsd32_charp" "acl_type_t" */ +#define NETBSD32_SYS_netbsd32___acl_delete_link 489 + +/* syscall: "netbsd32___acl_aclcheck_link" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */ +#define NETBSD32_SYS_netbsd32___acl_aclcheck_link 490 + +/* syscall: "netbsd32___acl_get_file" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */ +#define NETBSD32_SYS_netbsd32___acl_get_file 491 + +/* syscall: "netbsd32___acl_set_file" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */ +#define NETBSD32_SYS_netbsd32___acl_set_file 492 + +/* syscall: "netbsd32___acl_get_fd" ret: "int" args: "int" "acl_type_t" "netbsd32_aclp_t" */ +#define NETBSD32_SYS_netbsd32___acl_get_fd 493 + +/* syscall: "netbsd32___acl_set_fd" ret: "int" args: "int" "acl_type_t" "netbsd32_aclp_t" */ +#define NETBSD32_SYS_netbsd32___acl_set_fd 494 + +/* syscall: "netbsd32___acl_delete_file" ret: "int" args: "const netbsd32_charp" "acl_type_t" */ +#define NETBSD32_SYS_netbsd32___acl_delete_file 495 + +/* syscall: "netbsd32___acl_delete_fd" ret: "int" args: "int" "acl_type_t" */ +#define NETBSD32_SYS_netbsd32___acl_delete_fd 496 + +/* syscall: "netbsd32___acl_aclcheck_file" ret: "int" args: "const netbsd32_charp" "acl_type_t" "netbsd32_aclp_t" */ +#define NETBSD32_SYS_netbsd32___acl_aclcheck_file 497 + +/* syscall: "netbsd32___acl_aclcheck_fd" ret: "int" args: "int" "acl_type_t" "netbsd32_aclp_t" */ +#define NETBSD32_SYS_netbsd32___acl_aclcheck_fd 498 + +/* syscall: "netbsd32_lpathconf" ret: "long" args: "const netbsd32_charp" "int" */ +#define NETBSD32_SYS_netbsd32_lpathconf 499 + +#define NETBSD32_SYS_MAXSYSCALL 500 #define NETBSD32_SYS_NSYSENT 512 #endif /* _NETBSD32_SYS_SYSCALL_H_ */ Index: sys/compat/netbsd32/netbsd32_syscallargs.h =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_syscallargs.h,v retrieving revision 1.152 diff -u -p -p -u -r1.152 netbsd32_syscallargs.h --- sys/compat/netbsd32/netbsd32_syscallargs.h 26 Apr 2020 19:18:52 -0000 1.152 +++ sys/compat/netbsd32/netbsd32_syscallargs.h 16 May 2020 16:14:06 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_syscallargs.h,v 1.152 2020/04/26 19:18:52 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call argument lists. @@ -2669,6 +2669,93 @@ struct netbsd32___fhstatvfs190_args { }; check_syscall_args(netbsd32___fhstatvfs190) +struct netbsd32___acl_get_link_args { + syscallarg(const netbsd32_charp) path; + syscallarg(acl_type_t) type; + syscallarg(netbsd32_aclp_t) aclp; +}; +check_syscall_args(netbsd32___acl_get_link) + +struct netbsd32___acl_set_link_args { + syscallarg(const netbsd32_charp) path; + syscallarg(acl_type_t) type; + syscallarg(netbsd32_aclp_t) aclp; +}; +check_syscall_args(netbsd32___acl_set_link) + +struct netbsd32___acl_delete_link_args { + syscallarg(const netbsd32_charp) path; + syscallarg(acl_type_t) type; +}; +check_syscall_args(netbsd32___acl_delete_link) + +struct netbsd32___acl_aclcheck_link_args { + syscallarg(const netbsd32_charp) path; + syscallarg(acl_type_t) type; + syscallarg(netbsd32_aclp_t) aclp; +}; +check_syscall_args(netbsd32___acl_aclcheck_link) + +struct netbsd32___acl_get_file_args { + syscallarg(const netbsd32_charp) path; + syscallarg(acl_type_t) type; + syscallarg(netbsd32_aclp_t) aclp; +}; +check_syscall_args(netbsd32___acl_get_file) + +struct netbsd32___acl_set_file_args { + syscallarg(const netbsd32_charp) path; + syscallarg(acl_type_t) type; + syscallarg(netbsd32_aclp_t) aclp; +}; +check_syscall_args(netbsd32___acl_set_file) + +struct netbsd32___acl_get_fd_args { + syscallarg(int) filedes; + syscallarg(acl_type_t) type; + syscallarg(netbsd32_aclp_t) aclp; +}; +check_syscall_args(netbsd32___acl_get_fd) + +struct netbsd32___acl_set_fd_args { + syscallarg(int) filedes; + syscallarg(acl_type_t) type; + syscallarg(netbsd32_aclp_t) aclp; +}; +check_syscall_args(netbsd32___acl_set_fd) + +struct netbsd32___acl_delete_file_args { + syscallarg(const netbsd32_charp) path; + syscallarg(acl_type_t) type; +}; +check_syscall_args(netbsd32___acl_delete_file) + +struct netbsd32___acl_delete_fd_args { + syscallarg(int) filedes; + syscallarg(acl_type_t) type; +}; +check_syscall_args(netbsd32___acl_delete_fd) + +struct netbsd32___acl_aclcheck_file_args { + syscallarg(const netbsd32_charp) path; + syscallarg(acl_type_t) type; + syscallarg(netbsd32_aclp_t) aclp; +}; +check_syscall_args(netbsd32___acl_aclcheck_file) + +struct netbsd32___acl_aclcheck_fd_args { + syscallarg(int) filedes; + syscallarg(acl_type_t) type; + syscallarg(netbsd32_aclp_t) aclp; +}; +check_syscall_args(netbsd32___acl_aclcheck_fd) + +struct netbsd32_lpathconf_args { + syscallarg(const netbsd32_charp) path; + syscallarg(int) name; +}; +check_syscall_args(netbsd32_lpathconf) + /* * System call prototypes. */ @@ -3503,4 +3590,30 @@ int netbsd32___fstatvfs190(struct lwp *, int netbsd32___fhstatvfs190(struct lwp *, const struct netbsd32___fhstatvfs190_args *, register_t *); +int netbsd32___acl_get_link(struct lwp *, const struct netbsd32___acl_get_link_args *, register_t *); + +int netbsd32___acl_set_link(struct lwp *, const struct netbsd32___acl_set_link_args *, register_t *); + +int netbsd32___acl_delete_link(struct lwp *, const struct netbsd32___acl_delete_link_args *, register_t *); + +int netbsd32___acl_aclcheck_link(struct lwp *, const struct netbsd32___acl_aclcheck_link_args *, register_t *); + +int netbsd32___acl_get_file(struct lwp *, const struct netbsd32___acl_get_file_args *, register_t *); + +int netbsd32___acl_set_file(struct lwp *, const struct netbsd32___acl_set_file_args *, register_t *); + +int netbsd32___acl_get_fd(struct lwp *, const struct netbsd32___acl_get_fd_args *, register_t *); + +int netbsd32___acl_set_fd(struct lwp *, const struct netbsd32___acl_set_fd_args *, register_t *); + +int netbsd32___acl_delete_file(struct lwp *, const struct netbsd32___acl_delete_file_args *, register_t *); + +int netbsd32___acl_delete_fd(struct lwp *, const struct netbsd32___acl_delete_fd_args *, register_t *); + +int netbsd32___acl_aclcheck_file(struct lwp *, const struct netbsd32___acl_aclcheck_file_args *, register_t *); + +int netbsd32___acl_aclcheck_fd(struct lwp *, const struct netbsd32___acl_aclcheck_fd_args *, register_t *); + +int netbsd32_lpathconf(struct lwp *, const struct netbsd32_lpathconf_args *, register_t *); + #endif /* _NETBSD32_SYS_SYSCALLARGS_H_ */ Index: sys/compat/netbsd32/netbsd32_syscalls.c =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_syscalls.c,v retrieving revision 1.152 diff -u -p -p -u -r1.152 netbsd32_syscalls.c --- sys/compat/netbsd32/netbsd32_syscalls.c 26 Apr 2020 19:18:52 -0000 1.152 +++ sys/compat/netbsd32/netbsd32_syscalls.c 16 May 2020 16:14:07 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_syscalls.c,v 1.152 2020/04/26 19:18:52 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call names. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: netbsd32_syscalls.c,v 1.152 2020/04/26 19:18:52 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #if defined(_KERNEL_OPT) #if defined(_KERNEL_OPT) @@ -525,19 +525,19 @@ const char *const netbsd32_syscallnames[ /* 484 */ "netbsd32___statvfs190", /* 485 */ "netbsd32___fstatvfs190", /* 486 */ "netbsd32___fhstatvfs190", - /* 487 */ "# filler", - /* 488 */ "# filler", - /* 489 */ "# filler", - /* 490 */ "# filler", - /* 491 */ "# filler", - /* 492 */ "# filler", - /* 493 */ "# filler", - /* 494 */ "# filler", - /* 495 */ "# filler", - /* 496 */ "# filler", - /* 497 */ "# filler", - /* 498 */ "# filler", - /* 499 */ "# filler", + /* 487 */ "netbsd32___acl_get_link", + /* 488 */ "netbsd32___acl_set_link", + /* 489 */ "netbsd32___acl_delete_link", + /* 490 */ "netbsd32___acl_aclcheck_link", + /* 491 */ "netbsd32___acl_get_file", + /* 492 */ "netbsd32___acl_set_file", + /* 493 */ "netbsd32___acl_get_fd", + /* 494 */ "netbsd32___acl_set_fd", + /* 495 */ "netbsd32___acl_delete_file", + /* 496 */ "netbsd32___acl_delete_fd", + /* 497 */ "netbsd32___acl_aclcheck_file", + /* 498 */ "netbsd32___acl_aclcheck_fd", + /* 499 */ "netbsd32_lpathconf", /* 500 */ "# filler", /* 501 */ "# filler", /* 502 */ "# filler", @@ -1050,19 +1050,19 @@ const char *const altnetbsd32_syscallnam /* 484 */ "statvfs1", /* 485 */ "fstatvfs1", /* 486 */ "fhstatvfs1", - /* 487 */ NULL, /* filler */ - /* 488 */ NULL, /* filler */ - /* 489 */ NULL, /* filler */ - /* 490 */ NULL, /* filler */ - /* 491 */ NULL, /* filler */ - /* 492 */ NULL, /* filler */ - /* 493 */ NULL, /* filler */ - /* 494 */ NULL, /* filler */ - /* 495 */ NULL, /* filler */ - /* 496 */ NULL, /* filler */ - /* 497 */ NULL, /* filler */ - /* 498 */ NULL, /* filler */ - /* 499 */ NULL, /* filler */ + /* 487 */ "__acl_get_link", + /* 488 */ "__acl_set_link", + /* 489 */ "__acl_delete_link", + /* 490 */ "__acl_aclcheck_link", + /* 491 */ "__acl_get_file", + /* 492 */ "__acl_set_file", + /* 493 */ "__acl_get_fd", + /* 494 */ "__acl_set_fd", + /* 495 */ "__acl_delete_file", + /* 496 */ "__acl_delete_fd", + /* 497 */ "__acl_aclcheck_file", + /* 498 */ "__acl_aclcheck_fd", + /* 499 */ "lpathconf", /* 500 */ NULL, /* filler */ /* 501 */ NULL, /* filler */ /* 502 */ NULL, /* filler */ Index: sys/compat/netbsd32/netbsd32_syscalls_autoload.c =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_syscalls_autoload.c,v retrieving revision 1.32 diff -u -p -p -u -r1.32 netbsd32_syscalls_autoload.c --- sys/compat/netbsd32/netbsd32_syscalls_autoload.c 26 Apr 2020 19:18:52 -0000 1.32 +++ sys/compat/netbsd32/netbsd32_syscalls_autoload.c 16 May 2020 16:14:07 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_syscalls_autoload.c,v 1.32 2020/04/26 19:18:52 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call autoload table. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: netbsd32_syscalls_autoload.c,v 1.32 2020/04/26 19:18:52 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" Index: sys/compat/netbsd32/netbsd32_sysent.c =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_sysent.c,v retrieving revision 1.151 diff -u -p -p -u -r1.151 netbsd32_sysent.c --- sys/compat/netbsd32/netbsd32_sysent.c 26 Apr 2020 19:18:52 -0000 1.151 +++ sys/compat/netbsd32/netbsd32_sysent.c 16 May 2020 16:14:07 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_sysent.c,v 1.151 2020/04/26 19:18:52 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call switch table. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: netbsd32_sysent.c,v 1.151 2020/04/26 19:18:52 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -2009,44 +2009,57 @@ struct sysent netbsd32_sysent[] = { .sy_call = (sy_call_t *)netbsd32___fhstatvfs190 }, /* 486 = netbsd32___fhstatvfs190 */ { - .sy_call = sys_nosys, - }, /* 487 = filler */ - { - .sy_call = sys_nosys, - }, /* 488 = filler */ - { - .sy_call = sys_nosys, - }, /* 489 = filler */ - { - .sy_call = sys_nosys, - }, /* 490 = filler */ - { - .sy_call = sys_nosys, - }, /* 491 = filler */ - { - .sy_call = sys_nosys, - }, /* 492 = filler */ - { - .sy_call = sys_nosys, - }, /* 493 = filler */ - { - .sy_call = sys_nosys, - }, /* 494 = filler */ - { - .sy_call = sys_nosys, - }, /* 495 = filler */ - { - .sy_call = sys_nosys, - }, /* 496 = filler */ - { - .sy_call = sys_nosys, - }, /* 497 = filler */ - { - .sy_call = sys_nosys, - }, /* 498 = filler */ - { - .sy_call = sys_nosys, - }, /* 499 = filler */ + ns(struct netbsd32___acl_get_link_args), + .sy_call = (sy_call_t *)netbsd32___acl_get_link + }, /* 487 = netbsd32___acl_get_link */ + { + ns(struct netbsd32___acl_set_link_args), + .sy_call = (sy_call_t *)netbsd32___acl_set_link + }, /* 488 = netbsd32___acl_set_link */ + { + ns(struct netbsd32___acl_delete_link_args), + .sy_call = (sy_call_t *)netbsd32___acl_delete_link + }, /* 489 = netbsd32___acl_delete_link */ + { + ns(struct netbsd32___acl_aclcheck_link_args), + .sy_call = (sy_call_t *)netbsd32___acl_aclcheck_link + }, /* 490 = netbsd32___acl_aclcheck_link */ + { + ns(struct netbsd32___acl_get_file_args), + .sy_call = (sy_call_t *)netbsd32___acl_get_file + }, /* 491 = netbsd32___acl_get_file */ + { + ns(struct netbsd32___acl_set_file_args), + .sy_call = (sy_call_t *)netbsd32___acl_set_file + }, /* 492 = netbsd32___acl_set_file */ + { + ns(struct netbsd32___acl_get_fd_args), + .sy_call = (sy_call_t *)netbsd32___acl_get_fd + }, /* 493 = netbsd32___acl_get_fd */ + { + ns(struct netbsd32___acl_set_fd_args), + .sy_call = (sy_call_t *)netbsd32___acl_set_fd + }, /* 494 = netbsd32___acl_set_fd */ + { + ns(struct netbsd32___acl_delete_file_args), + .sy_call = (sy_call_t *)netbsd32___acl_delete_file + }, /* 495 = netbsd32___acl_delete_file */ + { + ns(struct netbsd32___acl_delete_fd_args), + .sy_call = (sy_call_t *)netbsd32___acl_delete_fd + }, /* 496 = netbsd32___acl_delete_fd */ + { + ns(struct netbsd32___acl_aclcheck_file_args), + .sy_call = (sy_call_t *)netbsd32___acl_aclcheck_file + }, /* 497 = netbsd32___acl_aclcheck_file */ + { + ns(struct netbsd32___acl_aclcheck_fd_args), + .sy_call = (sy_call_t *)netbsd32___acl_aclcheck_fd + }, /* 498 = netbsd32___acl_aclcheck_fd */ + { + ns(struct netbsd32_lpathconf_args), + .sy_call = (sy_call_t *)netbsd32_lpathconf + }, /* 499 = netbsd32_lpathconf */ { .sy_call = sys_nosys, }, /* 500 = filler */ Index: sys/compat/netbsd32/netbsd32_systrace_args.c =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_systrace_args.c,v retrieving revision 1.43 diff -u -p -p -u -r1.43 netbsd32_systrace_args.c --- sys/compat/netbsd32/netbsd32_systrace_args.c 26 Apr 2020 19:18:52 -0000 1.43 +++ sys/compat/netbsd32/netbsd32_systrace_args.c 16 May 2020 16:14:07 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_systrace_args.c,v 1.43 2020/04/26 19:18:52 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call argument to DTrace register array converstion. @@ -3548,6 +3548,119 @@ systrace_args(register_t sysnum, const v *n_args = 4; break; } + /* netbsd32___acl_get_link */ + case 487: { + const struct netbsd32___acl_get_link_args *p = params; + uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */ + *n_args = 3; + break; + } + /* netbsd32___acl_set_link */ + case 488: { + const struct netbsd32___acl_set_link_args *p = params; + uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */ + *n_args = 3; + break; + } + /* netbsd32___acl_delete_link */ + case 489: { + const struct netbsd32___acl_delete_link_args *p = params; + uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + *n_args = 2; + break; + } + /* netbsd32___acl_aclcheck_link */ + case 490: { + const struct netbsd32___acl_aclcheck_link_args *p = params; + uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */ + *n_args = 3; + break; + } + /* netbsd32___acl_get_file */ + case 491: { + const struct netbsd32___acl_get_file_args *p = params; + uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */ + *n_args = 3; + break; + } + /* netbsd32___acl_set_file */ + case 492: { + const struct netbsd32___acl_set_file_args *p = params; + uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */ + *n_args = 3; + break; + } + /* netbsd32___acl_get_fd */ + case 493: { + const struct netbsd32___acl_get_fd_args *p = params; + iarg[0] = SCARG(p, filedes); /* int */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */ + *n_args = 3; + break; + } + /* netbsd32___acl_set_fd */ + case 494: { + const struct netbsd32___acl_set_fd_args *p = params; + iarg[0] = SCARG(p, filedes); /* int */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */ + *n_args = 3; + break; + } + /* netbsd32___acl_delete_file */ + case 495: { + const struct netbsd32___acl_delete_file_args *p = params; + uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + *n_args = 2; + break; + } + /* netbsd32___acl_delete_fd */ + case 496: { + const struct netbsd32___acl_delete_fd_args *p = params; + iarg[0] = SCARG(p, filedes); /* int */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + *n_args = 2; + break; + } + /* netbsd32___acl_aclcheck_file */ + case 497: { + const struct netbsd32___acl_aclcheck_file_args *p = params; + uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */ + *n_args = 3; + break; + } + /* netbsd32___acl_aclcheck_fd */ + case 498: { + const struct netbsd32___acl_aclcheck_fd_args *p = params; + iarg[0] = SCARG(p, filedes); /* int */ + iarg[1] = SCARG(p, type); /* acl_type_t */ + uarg[2] = (intptr_t) SCARG(p, aclp).i32; /* netbsd32_aclp_t */ + *n_args = 3; + break; + } + /* netbsd32_lpathconf */ + case 499: { + const struct netbsd32_lpathconf_args *p = params; + uarg[0] = (intptr_t) SCARG(p, path).i32; /* const netbsd32_charp */ + iarg[1] = SCARG(p, name); /* int */ + *n_args = 2; + break; + } default: *n_args = 0; break; @@ -9597,6 +9710,202 @@ systrace_entry_setargdesc(int sysnum, in break; }; break; + /* netbsd32___acl_get_link */ + case 487: + switch(ndx) { + case 0: + p = "const netbsd32_charp"; + break; + case 1: + p = "acl_type_t"; + break; + case 2: + p = "netbsd32_aclp_t"; + break; + default: + break; + }; + break; + /* netbsd32___acl_set_link */ + case 488: + switch(ndx) { + case 0: + p = "const netbsd32_charp"; + break; + case 1: + p = "acl_type_t"; + break; + case 2: + p = "netbsd32_aclp_t"; + break; + default: + break; + }; + break; + /* netbsd32___acl_delete_link */ + case 489: + switch(ndx) { + case 0: + p = "const netbsd32_charp"; + break; + case 1: + p = "acl_type_t"; + break; + default: + break; + }; + break; + /* netbsd32___acl_aclcheck_link */ + case 490: + switch(ndx) { + case 0: + p = "const netbsd32_charp"; + break; + case 1: + p = "acl_type_t"; + break; + case 2: + p = "netbsd32_aclp_t"; + break; + default: + break; + }; + break; + /* netbsd32___acl_get_file */ + case 491: + switch(ndx) { + case 0: + p = "const netbsd32_charp"; + break; + case 1: + p = "acl_type_t"; + break; + case 2: + p = "netbsd32_aclp_t"; + break; + default: + break; + }; + break; + /* netbsd32___acl_set_file */ + case 492: + switch(ndx) { + case 0: + p = "const netbsd32_charp"; + break; + case 1: + p = "acl_type_t"; + break; + case 2: + p = "netbsd32_aclp_t"; + break; + default: + break; + }; + break; + /* netbsd32___acl_get_fd */ + case 493: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "acl_type_t"; + break; + case 2: + p = "netbsd32_aclp_t"; + break; + default: + break; + }; + break; + /* netbsd32___acl_set_fd */ + case 494: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "acl_type_t"; + break; + case 2: + p = "netbsd32_aclp_t"; + break; + default: + break; + }; + break; + /* netbsd32___acl_delete_file */ + case 495: + switch(ndx) { + case 0: + p = "const netbsd32_charp"; + break; + case 1: + p = "acl_type_t"; + break; + default: + break; + }; + break; + /* netbsd32___acl_delete_fd */ + case 496: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "acl_type_t"; + break; + default: + break; + }; + break; + /* netbsd32___acl_aclcheck_file */ + case 497: + switch(ndx) { + case 0: + p = "const netbsd32_charp"; + break; + case 1: + p = "acl_type_t"; + break; + case 2: + p = "netbsd32_aclp_t"; + break; + default: + break; + }; + break; + /* netbsd32___acl_aclcheck_fd */ + case 498: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "acl_type_t"; + break; + case 2: + p = "netbsd32_aclp_t"; + break; + default: + break; + }; + break; + /* netbsd32_lpathconf */ + case 499: + switch(ndx) { + case 0: + p = "const netbsd32_charp"; + break; + case 1: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -11599,6 +11908,71 @@ systrace_return_setargdesc(int sysnum, i if (ndx == 0 || ndx == 1) p = "int"; break; + /* netbsd32___acl_get_link */ + case 487: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32___acl_set_link */ + case 488: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32___acl_delete_link */ + case 489: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32___acl_aclcheck_link */ + case 490: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32___acl_get_file */ + case 491: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32___acl_set_file */ + case 492: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32___acl_get_fd */ + case 493: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32___acl_set_fd */ + case 494: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32___acl_delete_file */ + case 495: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32___acl_delete_fd */ + case 496: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32___acl_aclcheck_file */ + case 497: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32___acl_aclcheck_fd */ + case 498: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* netbsd32_lpathconf */ + case 499: + if (ndx == 0 || ndx == 1) + p = "long"; + break; default: break; }; Index: sys/compat/netbsd32/syscalls.master =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/syscalls.master,v retrieving revision 1.137 diff -u -p -p -u -r1.137 syscalls.master --- sys/compat/netbsd32/syscalls.master 26 Apr 2020 19:18:36 -0000 1.137 +++ sys/compat/netbsd32/syscalls.master 16 May 2020 16:14:07 -0000 @@ -1172,3 +1172,37 @@ 486 STD { int|netbsd32|90|fhstatvfs1(netbsd32_voidp fhp, \ netbsd32_size_t fh_size, netbsd32_statvfsp_t buf, \ int flags); } +487 STD { int|netbsd32||__acl_get_link( \ + const netbsd32_charp path, \ + acl_type_t type, netbsd32_aclp_t aclp); } +488 STD { int|netbsd32||__acl_set_link( \ + const netbsd32_charp path, \ + acl_type_t type, netbsd32_aclp_t aclp); } +489 STD { int|netbsd32||__acl_delete_link( \ + const netbsd32_charp path, \ + acl_type_t type); } +490 STD { int|netbsd32||__acl_aclcheck_link( \ + const netbsd32_charp path, \ + acl_type_t type, netbsd32_aclp_t aclp); } +491 STD { int|netbsd32||__acl_get_file( \ + const netbsd32_charp path, \ + acl_type_t type, netbsd32_aclp_t aclp); } +492 STD { int|netbsd32||__acl_set_file( \ + const netbsd32_charp path, \ + acl_type_t type, netbsd32_aclp_t aclp); } +493 STD { int|netbsd32||__acl_get_fd(int filedes, \ + acl_type_t type, netbsd32_aclp_t aclp); } +494 STD { int|netbsd32||__acl_set_fd(int filedes, \ + acl_type_t type, netbsd32_aclp_t aclp); } +495 STD { int|netbsd32||__acl_delete_file( \ + const netbsd32_charp path, \ + acl_type_t type); } +496 STD { int|netbsd32||__acl_delete_fd(int filedes, \ + acl_type_t type); } +497 STD { int|netbsd32||__acl_aclcheck_file( \ + const netbsd32_charp path, \ + acl_type_t type, netbsd32_aclp_t aclp); } +498 STD { int|netbsd32||__acl_aclcheck_fd(int filedes, \ + acl_type_t type, netbsd32_aclp_t aclp); } +499 STD { long|netbsd32||lpathconf(const netbsd32_charp path, \ + int name); } Index: sys/fs/adosfs/advnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/adosfs/advnops.c,v retrieving revision 1.53 diff -u -p -p -u -r1.53 advnops.c --- sys/fs/adosfs/advnops.c 23 Apr 2020 21:47:07 -0000 1.53 +++ sys/fs/adosfs/advnops.c 16 May 2020 16:14:08 -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 */ @@ -749,7 +750,7 @@ reterr: } static int -adosfs_check_possible(struct vnode *vp, struct anode *ap, mode_t mode) +adosfs_check_possible(struct vnode *vp, struct anode *ap, accmode_t accmode) { /* @@ -757,7 +758,7 @@ adosfs_check_possible(struct vnode *vp, * fifo, or a block or character device resident on the * file system. */ - if (mode & VWRITE) { + if (accmode & VWRITE) { switch (vp->v_type) { case VDIR: case VLNK: @@ -772,14 +773,14 @@ adosfs_check_possible(struct vnode *vp, } static int -adosfs_check_permitted(struct vnode *vp, struct anode *ap, mode_t mode, +adosfs_check_permitted(struct vnode *vp, struct anode *ap, accmode_t accmode, kauth_cred_t cred) { mode_t file_mode = adunixprot(ap->adprot) & ap->amp->mask; - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, - vp->v_type, file_mode), vp, NULL, genfs_can_access(vp->v_type, - file_mode, ap->uid, ap->gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, file_mode), vp, NULL, genfs_can_access(vp, + cred, ap->uid, ap->gid, file_mode, NULL, accmode)); } int @@ -787,7 +788,7 @@ adosfs_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *sp = v; struct anode *ap; @@ -806,11 +807,11 @@ adosfs_access(void *v) } #endif - error = adosfs_check_possible(vp, ap, sp->a_mode); + error = adosfs_check_possible(vp, ap, sp->a_accmode); if (error) return error; - error = adosfs_check_permitted(vp, ap, sp->a_mode, sp->a_cred); + error = adosfs_check_permitted(vp, ap, sp->a_accmode, sp->a_cred); #ifdef ADOSFS_DIAGNOSTIC printf(" %d)", error); 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 -p -u -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 16 May 2020 16:14:08 -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 -p -u -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 16 May 2020 16:14:08 -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)); + genfs_can_access(vp, cred, ip->inode.iso_uid, ip->inode.iso_gid, + ip->inode.iso_mode & ALLPERMS, NULL, accmode)); } int @@ -128,18 +128,18 @@ cd9660_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *ap = v; struct vnode *vp = ap->a_vp; struct iso_node *ip = VTOI(vp); int error; - error = cd9660_check_possible(vp, ip, ap->a_mode); + error = cd9660_check_possible(vp, ip, ap->a_accmode); if (error) return error; - error = cd9660_check_permitted(vp, ip, ap->a_mode, ap->a_cred); + error = cd9660_check_permitted(vp, ip, ap->a_accmode, ap->a_cred); return error; } @@ -855,6 +855,7 @@ const struct vnodeopv_entry_desc cd9660_ { &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 -p -u -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 16 May 2020 16:14:08 -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, - vp->v_type, eip->ei_mode), vp, NULL, genfs_can_access(vp->v_type, - eip->ei_mode, eip->ei_uid, eip->ei_gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, eip->ei_mode), vp, NULL, genfs_can_access(vp, + cred, eip->ei_uid, eip->ei_gid, eip->ei_mode, NULL, accmode)); } static int @@ -146,18 +146,18 @@ efs_access(void *v) struct vop_access_args /* { const struct vnodeop_desc *a_desc; struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; struct ucred *a_cred; } */ *ap = v; struct vnode *vp = ap->a_vp; struct efs_inode *eip = EFS_VTOI(vp); int error; - error = efs_check_possible(vp, eip, ap->a_mode); + error = efs_check_possible(vp, eip, ap->a_accmode); if (error) return error; - error = efs_check_permitted(vp, eip, ap->a_mode, ap->a_cred); + error = efs_check_permitted(vp, eip, ap->a_accmode, ap->a_cred); return error; } @@ -789,6 +789,7 @@ const struct vnodeopv_entry_desc efs_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 -p -u -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 16 May 2020 16:14:08 -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)); + genfs_can_access(vp, cred, fcmp->fc_uid, fcmp->fc_gid, + filecore_mode(ip), NULL, accmode)); } int @@ -137,18 +137,18 @@ filecore_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *ap = v; struct vnode *vp = ap->a_vp; struct filecore_node *ip = VTOI(vp); int error; - error = filecore_check_possible(vp, ip, ap->a_mode); + error = filecore_check_possible(vp, ip, ap->a_accmode); if (error) return error; - error = filecore_check_permitted(vp, ip, ap->a_mode, ap->a_cred); + error = filecore_check_permitted(vp, ip, ap->a_accmode, ap->a_cred); return error; } @@ -560,6 +560,7 @@ const struct vnodeopv_entry_desc 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 -p -u -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 16 May 2020 16:14:08 -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 */ @@ -531,7 +534,7 @@ hfs_vop_close(void *v) } static int -hfs_check_possible(struct vnode *vp, mode_t mode) +hfs_check_possible(struct vnode *vp, accmode_t accmode) { /* @@ -539,7 +542,7 @@ hfs_check_possible(struct vnode *vp, mod * since we have no write support yet. */ - if (mode & VWRITE) { + if (accmode & VWRITE) { switch (vp->v_type) { case VDIR: case VLNK: @@ -554,13 +557,13 @@ hfs_check_possible(struct vnode *vp, mod } static int -hfs_check_permitted(vnode_t *vp, struct vattr *va, mode_t mode, +hfs_check_permitted(vnode_t *vp, struct vattr *va, accmode_t accmode, kauth_cred_t cred) { - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, - va->va_type, va->va_mode), vp, NULL, genfs_can_access(va->va_type, - va->va_mode, va->va_uid, va->va_gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + va->va_type, va->va_mode), vp, NULL, genfs_can_access(vp, cred, + va->va_uid, va->va_gid, va->va_mode, NULL, accmode)); } int @@ -568,7 +571,7 @@ hfs_vop_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + int a_accmode; kauth_cred_t a_cred; } */ *ap = v; struct vattr va; @@ -576,14 +579,14 @@ hfs_vop_access(void *v) DPRINTF(("VOP = hfs_vop_access()\n")); - error = hfs_check_possible(ap->a_vp, ap->a_mode); + error = hfs_check_possible(ap->a_vp, ap->a_accmode); if (error) return error; if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0) return error; - error = hfs_check_permitted(ap->a_vp, &va, ap->a_mode, ap->a_cred); + error = hfs_check_permitted(ap->a_vp, &va, ap->a_accmode, ap->a_cred); return error; } 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 -p -u -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 16 May 2020 16:14:08 -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, - vp->v_type, file_mode), vp, NULL, genfs_can_access(vp->v_type, - file_mode, pmp->pm_uid, pmp->pm_gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, file_mode), vp, NULL, genfs_can_access(vp, cred, + pmp->pm_uid, pmp->pm_gid, file_mode, NULL, accmode)); } int @@ -227,18 +227,18 @@ msdosfs_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *ap = v; struct vnode *vp = ap->a_vp; struct denode *dep = VTODE(vp); int error; - error = msdosfs_check_possible(vp, dep, ap->a_mode); + error = msdosfs_check_possible(vp, dep, ap->a_accmode); if (error) return error; - error = msdosfs_check_permitted(vp, dep, ap->a_mode, ap->a_cred); + error = msdosfs_check_permitted(vp, dep, ap->a_accmode, ap->a_cred); return error; } @@ -371,8 +371,8 @@ msdosfs_setattr(void *v) goto bad; } error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, - ap->a_vp, NULL, genfs_can_chtimes(ap->a_vp, vap->va_vaflags, - pmp->pm_uid, cred)); + ap->a_vp, NULL, genfs_can_chtimes(ap->a_vp, cred, + pmp->pm_uid, vap->va_vaflags)); if (error) goto bad; if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && @@ -395,7 +395,7 @@ msdosfs_setattr(void *v) goto bad; } error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp, - NULL, genfs_can_chflags(cred, vp->v_type, pmp->pm_uid, false)); + NULL, genfs_can_chflags(vp, cred, pmp->pm_uid, false)); if (error) goto bad; /* We ignore the read and execute bits. */ @@ -415,7 +415,7 @@ msdosfs_setattr(void *v) goto bad; } error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp, - NULL, genfs_can_chflags(cred, vp->v_type, pmp->pm_uid, false)); + NULL, genfs_can_chflags(vp, cred, pmp->pm_uid, false)); if (error) goto bad; if (vap->va_flags & SF_ARCHIVED) @@ -1847,6 +1847,7 @@ const struct vnodeopv_entry_desc msdosfs { &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 -p -u -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 16 May 2020 16:14:08 -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,21 +1020,21 @@ 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; } static int -nilfs_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode, +nilfs_check_permitted(struct vnode *vp, struct vattr *vap, accmode_t accmode, kauth_cred_t cred) { /* ask the generic genfs_can_access to advice on security */ - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, - vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp->v_type, - vap->va_mode, vap->va_uid, vap->va_gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp, cred, + vap->va_uid, vap->va_gid, vap->va_mode, NULL, accmode)); } int @@ -1042,12 +1042,12 @@ nilfs_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; struct proc *a_p; } */ *ap = v; struct vnode *vp = ap->a_vp; - mode_t mode = ap->a_mode; + accmode_t accmode = ap->a_accmode; kauth_cred_t cred = ap->a_cred; /* struct nilfs_node *nilfs_node = VTOI(vp); */ struct vattr vap; @@ -1059,11 +1059,11 @@ nilfs_access(void *v) if (error) return error; - error = nilfs_check_possible(vp, &vap, mode); + error = nilfs_check_possible(vp, &vap, accmode); if (error) return error; - error = nilfs_check_permitted(vp, &vap, mode, cred); + error = nilfs_check_permitted(vp, &vap, accmode, cred); return error; } @@ -1549,6 +1549,7 @@ const struct vnodeopv_entry_desc nilfs_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 -p -u -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 16 May 2020 16:14:08 -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,16 @@ 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, cred, + ip->i_mp->ntm_uid, ip->i_mp->ntm_gid, file_mode, NULL, accmode)); } int @@ -439,7 +439,7 @@ ntfs_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *ap = v; struct vnode *vp = ap->a_vp; @@ -448,11 +448,11 @@ ntfs_access(void *v) dprintf(("ntfs_access: %llu\n", (unsigned long long)ip->i_number)); - error = ntfs_check_possible(vp, ip, ap->a_mode); + error = ntfs_check_possible(vp, ip, ap->a_accmode); if (error) return error; - error = ntfs_check_permitted(vp, ip, ap->a_mode, ap->a_cred); + error = ntfs_check_permitted(vp, ip, ap->a_accmode, ap->a_cred); return error; } @@ -814,6 +814,7 @@ const struct vnodeopv_entry_desc ntfs_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 -p -u -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 16 May 2020 16:14:08 -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 */ @@ -435,7 +436,7 @@ ptyfs_setattr(void *v) } error = kauth_authorize_vnode(cred, action, vp, NULL, - genfs_can_chflags(cred, vp->v_type, ptyfs->ptyfs_uid, + genfs_can_chflags(vp, cred, ptyfs->ptyfs_uid, changing_sysflags)); if (error) return error; @@ -469,8 +470,8 @@ ptyfs_setattr(void *v) if ((ptyfs->ptyfs_flags & SF_SNAPSHOT) != 0) return EPERM; error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, - NULL, genfs_can_chtimes(vp, vap->va_vaflags, - ptyfs->ptyfs_uid, cred)); + NULL, genfs_can_chtimes(vp, cred, ptyfs->ptyfs_uid, + vap->va_vaflags)); if (error) return (error); if (vap->va_atime.tv_sec != VNOVAL) @@ -516,8 +517,8 @@ ptyfs_chmod(struct vnode *vp, mode_t mod int error; error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp, - NULL, genfs_can_chmod(vp->v_type, cred, ptyfs->ptyfs_uid, - ptyfs->ptyfs_gid, mode)); + NULL, genfs_can_chmod(vp, cred, ptyfs->ptyfs_uid, ptyfs->ptyfs_gid, + mode)); if (error) return (error); @@ -543,7 +544,7 @@ ptyfs_chown(struct vnode *vp, uid_t uid, gid = ptyfs->ptyfs_gid; error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, - NULL, genfs_can_chown(cred, ptyfs->ptyfs_uid, ptyfs->ptyfs_gid, + NULL, genfs_can_chown(vp, cred, ptyfs->ptyfs_uid, ptyfs->ptyfs_gid, uid, gid)); if (error) return (error); @@ -567,7 +568,7 @@ ptyfs_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *ap = v; struct vattr va; @@ -577,9 +578,9 @@ ptyfs_access(void *v) return error; return kauth_authorize_vnode(ap->a_cred, - KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode), - ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode, va.va_uid, - va.va_gid, ap->a_mode, ap->a_cred)); + KAUTH_ACCESS_ACTION(ap->a_accmode, ap->a_vp->v_type, va.va_mode), + ap->a_vp, NULL, genfs_can_access(ap->a_vp, ap->a_cred, va.va_uid, + va.va_gid, va.va_mode, NULL, ap->a_accmode)); } /* Index: sys/fs/puffs/puffs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/puffs/puffs_vnops.c,v retrieving revision 1.216 diff -u -p -p -u -r1.216 puffs_vnops.c --- sys/fs/puffs/puffs_vnops.c 15 May 2020 19:28:10 -0000 1.216 +++ sys/fs/puffs/puffs_vnops.c 16 May 2020 16:14:08 -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 -p -u -r1.17 sysvbfs.c --- sys/fs/sysvbfs/sysvbfs.c 28 May 2018 21:04:37 -0000 1.17 +++ sys/fs/sysvbfs/sysvbfs.c 16 May 2020 16:14:08 -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 -p -u -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 16 May 2020 16:14:08 -0000 @@ -249,13 +249,13 @@ sysvbfs_check_possible(struct vnode *vp, static int sysvbfs_check_permitted(struct vnode *vp, struct sysvbfs_node *bnode, - mode_t mode, kauth_cred_t cred) + accmode_t accmode, kauth_cred_t cred) { struct bfs_fileattr *attr = &bnode->inode->attr; - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, - vp->v_type, attr->mode), vp, NULL, genfs_can_access(vp->v_type, - attr->mode, attr->uid, attr->gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, attr->mode), vp, NULL, genfs_can_access(vp, cred, + attr->uid, attr->gid, attr->mode, NULL, accmode)); } int @@ -263,7 +263,7 @@ sysvbfs_access(void *arg) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *ap = arg; struct vnode *vp = ap->a_vp; @@ -272,11 +272,11 @@ sysvbfs_access(void *arg) DPRINTF("%s:\n", __func__); - error = sysvbfs_check_possible(vp, bnode, ap->a_mode); + error = sysvbfs_check_possible(vp, bnode, ap->a_accmode); if (error) return error; - error = sysvbfs_check_permitted(vp, bnode, ap->a_mode, ap->a_cred); + error = sysvbfs_check_permitted(vp, bnode, ap->a_accmode, ap->a_cred); return error; } @@ -359,7 +359,7 @@ sysvbfs_setattr(void *arg) (vap->va_gid != (gid_t)VNOVAL) ? vap->va_gid : attr->gid; error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, NULL, - genfs_can_chown(cred, attr->uid, attr->gid, uid, gid)); + genfs_can_chown(vp, cred, attr->uid, attr->gid, uid, gid)); if (error) return error; attr->uid = uid; @@ -386,7 +386,7 @@ sysvbfs_setattr(void *arg) if (vap->va_mode != (mode_t)VNOVAL) { mode_t mode = vap->va_mode; error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, - vp, NULL, genfs_can_chmod(vp->v_type, cred, attr->uid, + vp, NULL, genfs_can_chmod(vp, cred, attr->uid, attr->gid, mode)); if (error) return error; @@ -397,8 +397,8 @@ sysvbfs_setattr(void *arg) (vap->va_mtime.tv_sec != VNOVAL) || (vap->va_ctime.tv_sec != VNOVAL)) { error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, - NULL, genfs_can_chtimes(vp, vap->va_vaflags, attr->uid, - cred)); + NULL, genfs_can_chtimes(vp, cred, attr->uid, + vap->va_vaflags)); if (error) return error; 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 -p -u -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 16 May 2020 16:14:08 -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 -p -u -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 16 May 2020 16:14:08 -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_subr.c =================================================================== RCS file: /cvsroot/src/sys/fs/tmpfs/tmpfs_subr.c,v retrieving revision 1.110 diff -u -p -p -u -r1.110 tmpfs_subr.c --- sys/fs/tmpfs/tmpfs_subr.c 12 May 2020 23:17:41 -0000 1.110 +++ sys/fs/tmpfs/tmpfs_subr.c 16 May 2020 16:14:08 -0000 @@ -988,8 +988,7 @@ tmpfs_chflags(vnode_t *vp, int flags, ka } error = kauth_authorize_vnode(cred, action, vp, NULL, - genfs_can_chflags(cred, vp->v_type, node->tn_uid, - changing_sysflags)); + genfs_can_chflags(vp, cred, node->tn_uid, changing_sysflags)); if (error) return error; @@ -1034,7 +1033,7 @@ tmpfs_chmod(vnode_t *vp, mode_t mode, ka return EPERM; error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp, - NULL, genfs_can_chmod(vp->v_type, cred, node->tn_uid, node->tn_gid, mode)); + NULL, genfs_can_chmod(vp, cred, node->tn_uid, node->tn_gid, mode)); if (error) { return error; } @@ -1077,7 +1076,7 @@ tmpfs_chown(vnode_t *vp, uid_t uid, gid_ return EPERM; error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, - NULL, genfs_can_chown(cred, node->tn_uid, node->tn_gid, uid, + NULL, genfs_can_chown(vp, cred, node->tn_uid, node->tn_gid, uid, gid)); if (error) { return error; @@ -1164,7 +1163,7 @@ tmpfs_chtimes(vnode_t *vp, const struct return EPERM; error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, NULL, - genfs_can_chtimes(vp, vaflags, node->tn_uid, cred)); + genfs_can_chtimes(vp, cred, node->tn_uid, vaflags)); if (error) return error; Index: sys/fs/tmpfs/tmpfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/tmpfs/tmpfs_vnops.c,v retrieving revision 1.137 diff -u -p -p -u -r1.137 tmpfs_vnops.c --- sys/fs/tmpfs/tmpfs_vnops.c 15 May 2020 22:15:43 -0000 1.137 +++ sys/fs/tmpfs/tmpfs_vnops.c 16 May 2020 16:14:08 -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_accessx }, { &vop_getattr_desc, tmpfs_getattr }, { &vop_setattr_desc, tmpfs_setattr }, { &vop_read_desc, tmpfs_read }, @@ -269,7 +270,7 @@ tmpfs_lookup(void *v) if ((dnode->tn_mode & S_ISTXT) != 0) { error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_DELETE, tnode->tn_vnode, - dnode->tn_vnode, genfs_can_sticky(cnp->cn_cred, + dnode->tn_vnode, genfs_can_sticky(dvp, cnp->cn_cred, dnode->tn_uid, tnode->tn_uid)); if (error) { error = EPERM; @@ -377,14 +378,14 @@ tmpfs_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *ap = v; vnode_t *vp = ap->a_vp; - mode_t mode = ap->a_mode; + accmode_t accmode = ap->a_accmode; kauth_cred_t cred = ap->a_cred; tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp); - const bool writing = (mode & VWRITE) != 0; + const bool writing = (accmode & VWRITE) != 0; KASSERT(VOP_ISLOCKED(vp)); @@ -409,9 +410,9 @@ tmpfs_access(void *v) return EPERM; } - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, - vp->v_type, node->tn_mode), vp, NULL, genfs_can_access(vp->v_type, - node->tn_mode, node->tn_uid, node->tn_gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, node->tn_mode), vp, NULL, genfs_can_access(vp, cred, + node->tn_uid, node->tn_gid, node->tn_mode, NULL, accmode)); } int 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 -p -u -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 16 May 2020 16:14:08 -0000 @@ -826,7 +826,7 @@ udf_lookup(void *v) udf_getownership(dir_node, &d_uid, &d_gid); error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_DELETE, res_node->vnode, - dir_node->vnode, genfs_can_sticky(cnp->cn_cred, + dir_node->vnode, genfs_can_sticky(dvp, cnp->cn_cred, d_uid, d_uid)); if (error) { error = EPERM; @@ -1041,7 +1041,7 @@ udf_chown(struct vnode *vp, uid_t new_ui /* check permissions */ error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, - vp, NULL, genfs_can_chown(cred, uid, gid, new_uid, new_gid)); + vp, NULL, genfs_can_chown(vp, cred, uid, gid, new_uid, new_gid)); if (error) return (error); @@ -1078,7 +1078,7 @@ udf_chmod(struct vnode *vp, mode_t mode, /* check permissions */ error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp, - NULL, genfs_can_chmod(vp->v_type, cred, uid, gid, mode)); + NULL, genfs_can_chmod(vp, cred, uid, gid, mode)); if (error) return (error); @@ -1187,7 +1187,7 @@ udf_chtimes(struct vnode *vp, /* check permissions */ error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, - NULL, genfs_can_chtimes(vp, setattrflags, uid, cred)); + NULL, genfs_can_chtimes(vp, cred, uid, setattrflags)); if (error) return (error); @@ -1437,13 +1437,13 @@ udf_check_possible(struct vnode *vp, str } static int -udf_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode, +udf_check_permitted(struct vnode *vp, struct vattr *vap, accmode_t accmode, kauth_cred_t cred) { /* ask the generic genfs_can_access to advice on security */ - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, - vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp->v_type, - vap->va_mode, vap->va_uid, vap->va_gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp, cred, + vap->va_uid, vap->va_gid, vap->va_mode, NULL, accmode)); } int @@ -1451,12 +1451,12 @@ udf_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; struct proc *a_p; } */ *ap = v; struct vnode *vp = ap->a_vp; - mode_t mode = ap->a_mode; + accmode_t accmode = ap->a_accmode; kauth_cred_t cred = ap->a_cred; /* struct udf_node *udf_node = VTOI(vp); */ struct vattr vap; @@ -1468,11 +1468,11 @@ udf_access(void *v) if (error) return error; - error = udf_check_possible(vp, &vap, mode); + error = udf_check_possible(vp, &vap, accmode); if (error) return error; - error = udf_check_permitted(vp, &vap, mode, cred); + error = udf_check_permitted(vp, &vap, accmode, cred); return error; } @@ -2179,6 +2179,7 @@ const struct vnodeopv_entry_desc udf_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 -p -u -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 16 May 2020 16:14:08 -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 -p -u -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 16 May 2020 16:14:08 -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 -p -u -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 16 May 2020 16:14:08 -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 -p -u -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 16 May 2020 16:14:08 -0000 @@ -372,33 +372,33 @@ v7fs_check_possible(struct vnode *vp, st static int v7fs_check_permitted(struct vnode *vp, struct v7fs_node *v7node, - mode_t mode, kauth_cred_t cred) + accmode_t accmode, kauth_cred_t cred) { struct v7fs_inode *inode = &v7node->inode; - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, - vp->v_type, inode->mode), vp, NULL, genfs_can_access(vp->v_type, - inode->mode, inode->uid, inode->gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, inode->mode), vp, NULL, genfs_can_access(vp, cred, + inode->uid, inode->gid, inode->mode, NULL, accmode)); } int v7fs_access(void *v) { struct vop_access_args /* { - struct vnode *a_vp; - int a_mode; - kauth_cred_t a_cred; - } */ *ap = v; + struct vnode *a_vp; + accmode_t a_accmode; + kauth_cred_t a_cred; + } */ *ap = v; struct vnode *vp = ap->a_vp; struct v7fs_node *v7node = vp->v_data; int error; - error = v7fs_check_possible(vp, v7node, ap->a_mode); + error = v7fs_check_possible(vp, v7node, ap->a_accmode); if (error) return error; - error = v7fs_check_permitted(vp, v7node, ap->a_mode, ap->a_cred); + error = v7fs_check_permitted(vp, v7node, ap->a_accmode, ap->a_cred); return error; } @@ -492,7 +492,7 @@ v7fs_setattr(void *v) /* File pointer mode. */ if (vap->va_flags != VNOVAL) { error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, - vp, NULL, genfs_can_chflags(cred, vp->v_type, inode->uid, + vp, NULL, genfs_can_chflags(vp, cred, inode->uid, false)); if (error) return error; @@ -515,7 +515,7 @@ v7fs_setattr(void *v) uid = vap->va_uid; error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, NULL, - genfs_can_chown(cred, inode->uid, inode->gid, uid, + genfs_can_chown(vp, cred, inode->uid, inode->gid, uid, gid)); if (error) return error; @@ -525,7 +525,7 @@ v7fs_setattr(void *v) gid = vap->va_gid; error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, NULL, - genfs_can_chown(cred, inode->uid, inode->gid, uid, + genfs_can_chown(vp, cred, inode->uid, inode->gid, uid, gid)); if (error) return error; @@ -534,7 +534,7 @@ v7fs_setattr(void *v) if (vap->va_mode != (mode_t)VNOVAL) { mode_t mode = vap->va_mode; error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, - vp, NULL, genfs_can_chmod(vp->v_type, cred, inode->uid, inode->gid, + vp, NULL, genfs_can_chmod(vp, cred, inode->uid, inode->gid, mode)); if (error) { return error; @@ -545,8 +545,8 @@ v7fs_setattr(void *v) (vap->va_mtime.tv_sec != VNOVAL) || (vap->va_ctime.tv_sec != VNOVAL)) { error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, - NULL, genfs_can_chtimes(vp, vap->va_vaflags, inode->uid, - cred)); + NULL, genfs_can_chtimes(vp, cred, inode->uid, + vap->va_vaflags)); if (error) return error; Index: sys/kern/files.kern =================================================================== RCS file: /cvsroot/src/sys/kern/files.kern,v retrieving revision 1.47 diff -u -p -p -u -r1.47 files.kern --- sys/kern/files.kern 30 Apr 2020 03:28:18 -0000 1.47 +++ sys/kern/files.kern 16 May 2020 16:14:08 -0000 @@ -96,6 +96,8 @@ file kern/kern_uuid.c kern file kern/kgdb_stub.c kgdb file kern/sched_4bsd.c sched_4bsd file kern/sched_m2.c sched_m2 +file kern/subr_acl_posix1e.c kern +file kern/subr_acl_nfs4.c kern file kern/subr_asan.c kasan file kern/subr_autoconf.c kern file kern/subr_blist.c vmswap @@ -192,6 +194,7 @@ file kern/uipc_syscalls.c kern file kern/uipc_usrreq.c kern define vfs: kern +file kern/vfs_acl.c vfs file kern/vfs_bio.c vfs file kern/vfs_cache.c vfs file kern/vfs_cwd.c vfs Index: sys/kern/init_sysent.c =================================================================== RCS file: /cvsroot/src/sys/kern/init_sysent.c,v retrieving revision 1.331 diff -u -p -p -u -r1.331 init_sysent.c --- sys/kern/init_sysent.c 26 Apr 2020 19:16:36 -0000 1.331 +++ sys/kern/init_sysent.c 16 May 2020 16:14:08 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: init_sysent.c,v 1.331 2020/04/26 19:16:36 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call switch table. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: init_sysent.c,v 1.331 2020/04/26 19:16:36 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) @@ -2365,44 +2366,69 @@ struct sysent sysent[] = { .sy_call = (sy_call_t *)sys___fhstatvfs190 }, /* 486 = __fhstatvfs190 */ { - .sy_call = sys_nosys, - }, /* 487 = filler */ + ns(struct sys___acl_get_link_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys___acl_get_link + }, /* 487 = __acl_get_link */ { - .sy_call = sys_nosys, - }, /* 488 = filler */ + ns(struct sys___acl_set_link_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys___acl_set_link + }, /* 488 = __acl_set_link */ { - .sy_call = sys_nosys, - }, /* 489 = filler */ + ns(struct sys___acl_delete_link_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys___acl_delete_link + }, /* 489 = __acl_delete_link */ { - .sy_call = sys_nosys, - }, /* 490 = filler */ + ns(struct sys___acl_aclcheck_link_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys___acl_aclcheck_link + }, /* 490 = __acl_aclcheck_link */ { - .sy_call = sys_nosys, - }, /* 491 = filler */ + ns(struct sys___acl_get_file_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys___acl_get_file + }, /* 491 = __acl_get_file */ { - .sy_call = sys_nosys, - }, /* 492 = filler */ + ns(struct sys___acl_set_file_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys___acl_set_file + }, /* 492 = __acl_set_file */ { - .sy_call = sys_nosys, - }, /* 493 = filler */ + ns(struct sys___acl_get_fd_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys___acl_get_fd + }, /* 493 = __acl_get_fd */ { - .sy_call = sys_nosys, - }, /* 494 = filler */ + ns(struct sys___acl_set_fd_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys___acl_set_fd + }, /* 494 = __acl_set_fd */ { - .sy_call = sys_nosys, - }, /* 495 = filler */ + ns(struct sys___acl_delete_file_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys___acl_delete_file + }, /* 495 = __acl_delete_file */ { - .sy_call = sys_nosys, - }, /* 496 = filler */ + ns(struct sys___acl_delete_fd_args), + .sy_call = (sy_call_t *)sys___acl_delete_fd + }, /* 496 = __acl_delete_fd */ { - .sy_call = sys_nosys, - }, /* 497 = filler */ + ns(struct sys___acl_aclcheck_file_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys___acl_aclcheck_file + }, /* 497 = __acl_aclcheck_file */ { - .sy_call = sys_nosys, - }, /* 498 = filler */ + ns(struct sys___acl_aclcheck_fd_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys___acl_aclcheck_fd + }, /* 498 = __acl_aclcheck_fd */ { - .sy_call = sys_nosys, - }, /* 499 = filler */ + ns(struct sys_lpathconf_args), + .sy_flags = SYCALL_ARG_PTR, + .sy_call = (sy_call_t *)sys_lpathconf + }, /* 499 = lpathconf */ { .sy_call = sys_nosys, }, /* 500 = filler */ Index: sys/kern/kern_auth.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_auth.c,v retrieving revision 1.77 diff -u -p -p -u -r1.77 kern_auth.c --- sys/kern/kern_auth.c 3 Sep 2018 16:29:35 -0000 1.77 +++ sys/kern/kern_auth.c 16 May 2020 16:14:08 -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 16 May 2020 16:14:08 -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 16 May 2020 16:14:08 -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 -p -u -r1.46 sys_mqueue.c --- sys/kern/sys_mqueue.c 16 Mar 2020 21:20:10 -0000 1.46 +++ sys/kern/sys_mqueue.c 16 May 2020 16:14:08 -0000 @@ -393,17 +393,17 @@ mq_close_fop(file_t *fp) static int mqueue_access(mqueue_t *mq, int access, kauth_cred_t cred) { - mode_t acc_mode = 0; + accmode_t accmode = 0; /* Note the difference between VREAD/VWRITE and FREAD/FWRITE. */ if (access & FREAD) { - acc_mode |= VREAD; + accmode |= VREAD; } if (access & FWRITE) { - acc_mode |= VWRITE; + accmode |= VWRITE; } - if (genfs_can_access(VNON, mq->mq_mode, mq->mq_euid, - mq->mq_egid, acc_mode, cred)) { + if (genfs_can_access(NULL, cred, mq->mq_euid, mq->mq_egid, + mq->mq_mode, NULL, accmode)) { return EACCES; } return 0; Index: sys/kern/syscalls.c =================================================================== RCS file: /cvsroot/src/sys/kern/syscalls.c,v retrieving revision 1.319 diff -u -p -p -u -r1.319 syscalls.c --- sys/kern/syscalls.c 26 Apr 2020 19:16:36 -0000 1.319 +++ sys/kern/syscalls.c 16 May 2020 16:14:08 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: syscalls.c,v 1.319 2020/04/26 19:16:36 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call names. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: syscalls.c,v 1.319 2020/04/26 19:16:36 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 -p -u -r1.30 syscalls.conf --- sys/kern/syscalls.conf 22 Sep 2019 22:59:39 -0000 1.30 +++ sys/kern/syscalls.conf 16 May 2020 16:14:08 -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.304 diff -u -p -p -u -r1.304 syscalls.master --- sys/kern/syscalls.master 26 Apr 2020 19:15:55 -0000 1.304 +++ sys/kern/syscalls.master 16 May 2020 16:14:08 -0000 @@ -59,6 +59,7 @@ #include #include #include +#include %% @@ -1019,3 +1020,28 @@ struct statvfs *buf, int flags); } 486 STD RUMP { int|sys|90|fhstatvfs1(const void *fhp, \ size_t fh_size, struct statvfs *buf, int flags); } +487 STD { int|sys||__acl_get_link(const char *path, \ + acl_type_t type, struct acl *aclp); } +488 STD { int|sys||__acl_set_link(const char *path, \ + acl_type_t type, struct acl *aclp); } +489 STD { int|sys||__acl_delete_link(const char *path, \ + acl_type_t type); } +490 STD { int|sys||__acl_aclcheck_link(const char *path, \ + acl_type_t type, struct acl *aclp); } +491 STD { int|sys||__acl_get_file(const char *path, \ + acl_type_t type, struct acl *aclp); } +492 STD { int|sys||__acl_set_file(const char *path, \ + acl_type_t type, struct acl *aclp); } +493 STD { int|sys||__acl_get_fd(int filedes, acl_type_t type, \ + struct acl *aclp); } +494 STD { int|sys||__acl_set_fd(int filedes, acl_type_t type, \ + struct acl *aclp); } +495 STD { int|sys||__acl_delete_file(const char *path, \ + acl_type_t type); } +496 STD { int|sys||__acl_delete_fd(int filedes, \ + acl_type_t type); } +497 STD { int|sys||__acl_aclcheck_file(const char *path, \ + acl_type_t type, struct acl *aclp); } +498 STD { int|sys||__acl_aclcheck_fd(int filedes, \ + acl_type_t type, struct acl *aclp); } +499 STD RUMP { long|sys||lpathconf(const char *path, int name); } Index: sys/kern/syscalls_autoload.c =================================================================== RCS file: /cvsroot/src/sys/kern/syscalls_autoload.c,v retrieving revision 1.36 diff -u -p -p -u -r1.36 syscalls_autoload.c --- sys/kern/syscalls_autoload.c 26 Apr 2020 19:16:36 -0000 1.36 +++ sys/kern/syscalls_autoload.c 16 May 2020 16:14:08 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: syscalls_autoload.c,v 1.36 2020/04/26 19:16:36 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call autoload table. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: syscalls_autoload.c,v 1.36 2020/04/26 19:16:36 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.38 diff -u -p -p -u -r1.38 systrace_args.c --- sys/kern/systrace_args.c 26 Apr 2020 19:16:36 -0000 1.38 +++ sys/kern/systrace_args.c 16 May 2020 16:14:08 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: systrace_args.c,v 1.38 2020/04/26 19:16:36 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call argument to DTrace register array converstion. @@ -3731,6 +3731,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; @@ -10066,6 +10179,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; }; @@ -12178,6 +12487,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 16 May 2020 16:14:08 -0000 @@ -0,0 +1,542 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 1999-2006, 2016-2017 Robert N. M. Watson + * All rights reserved. + * + * This software was developed by Robert Watson for the TrustedBSD Project. + * + * Portions of this software were developed by BAE Systems, the University of + * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL + * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent + * Computing (TC) research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Developed by the TrustedBSD Project. + * + * ACL system calls and other functions common across different ACL types. + * Type-specific routines go into subr_acl_.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); + + +int +acl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest) +{ + int i; + + if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES) + return EINVAL; + + memset(dest, 0, sizeof(*dest)); + + dest->acl_cnt = source->acl_cnt; + dest->acl_maxcnt = ACL_MAX_ENTRIES; + + for (i = 0; i < dest->acl_cnt; i++) { + dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; + dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; + dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; + } + + return 0; +} + +int +acl_copy_acl_into_oldacl(const struct acl *source, struct oldacl *dest) +{ + int i; + + if (source->acl_cnt > OLDACL_MAX_ENTRIES) + return EINVAL; + + memset(dest, 0, sizeof(*dest)); + + dest->acl_cnt = source->acl_cnt; + + for (i = 0; i < dest->acl_cnt; i++) { + dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; + dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; + dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; + } + + return 0; +} + +/* + * At one time, "struct ACL" was extended in order to add support for NFSv4 + * ACLs. Instead of creating compatibility versions of all the ACL-related + * syscalls, they were left intact. It's possible to find out what the code + * calling these syscalls (libc) expects basing on "type" argument - if it's + * either ACL_TYPE_ACCESS_OLD or ACL_TYPE_DEFAULT_OLD (which previously were + * known as ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT), then it's the "struct + * oldacl". If it's something else, then it's the new "struct acl". In the + * latter case, the routines below just copyin/copyout the contents. In the + * former case, they copyin the "struct oldacl" and convert it to the new + * format. + */ +static int +acl_copyin(const void *user_acl, struct acl *kernel_acl, acl_type_t type) +{ + int error; + struct oldacl old; + + switch (type) { + case ACL_TYPE_ACCESS_OLD: + case ACL_TYPE_DEFAULT_OLD: + error = copyin(user_acl, &old, sizeof(old)); + if (error != 0) + break; + acl_copy_oldacl_into_acl(&old, kernel_acl); + break; + + default: + error = copyin(user_acl, kernel_acl, sizeof(*kernel_acl)); + if (kernel_acl->acl_maxcnt != ACL_MAX_ENTRIES) + return EINVAL; + } + + return error; +} + +static int +acl_copyout(const struct acl *kernel_acl, void *user_acl, acl_type_t type) +{ + uint32_t am; + int error; + struct oldacl old; + + switch (type) { + case ACL_TYPE_ACCESS_OLD: + case ACL_TYPE_DEFAULT_OLD: + error = acl_copy_acl_into_oldacl(kernel_acl, &old); + if (error != 0) + break; + + error = copyout(&old, user_acl, sizeof(old)); + break; + + default: + error = ufetch_32((const uint32_t *) + (const void *)((const char *)user_acl + + offsetof(struct acl, acl_maxcnt)), &am); + if (error) + return error; + if (am != ACL_MAX_ENTRIES) + return EINVAL; + + error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl)); + } + + return error; +} + +/* + * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new" + * counterpart. It's required for old (pre-NFSv4 ACLs) libc to work + * with new kernel. Fixing 'type' for old binaries with new libc + * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold(). + */ +static int +acl_type_unold(int type) +{ + switch (type) { + case ACL_TYPE_ACCESS_OLD: + return ACL_TYPE_ACCESS; + + case ACL_TYPE_DEFAULT_OLD: + return ACL_TYPE_DEFAULT; + + default: + return type; + } +} + +/* + * These calls wrap the real vnode operations, and are called by the syscall + * code once the syscall has converted the path or file descriptor to a vnode + * (unlocked). The aclp pointer is assumed still to point to userland, so + * this should not be consumed within the kernel except by syscall code. + * Other code should directly invoke VOP_{SET,GET}ACL. + */ + +/* + * Given a vnode, set its ACL. + */ +int +vacl_set_acl(struct lwp *l, struct vnode *vp, acl_type_t type, + const struct acl *aclp) +{ + struct acl *inkernelacl; + int error; + + inkernelacl = acl_alloc(KM_SLEEP); + error = acl_copyin(aclp, inkernelacl, type); + if (error != 0) + goto out; + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl, l->l_cred); + VOP_UNLOCK(vp); +out: + acl_free(inkernelacl); + return error; +} + +/* + * Given a vnode, get its ACL. + */ +int +vacl_get_acl(struct lwp *l, struct vnode *vp, acl_type_t type, + struct acl *aclp) +{ + struct acl *inkernelacl; + int error; + + inkernelacl = acl_alloc(KM_SLEEP); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl, l->l_cred); + + VOP_UNLOCK(vp); + if (error == 0) + error = acl_copyout(inkernelacl, aclp, type); + acl_free(inkernelacl); + return error; +} + +/* + * Given a vnode, delete its ACL. + */ +int +vacl_delete(struct lwp *l, struct vnode *vp, acl_type_t type) +{ + int error; + + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + error = VOP_SETACL(vp, acl_type_unold(type), 0, l->l_cred); + VOP_UNLOCK(vp); + return error; +} + +/* + * Given a vnode, check whether an ACL is appropriate for it + * + * XXXRW: No vnode lock held so can't audit vnode state...? + */ +int +vacl_aclcheck(struct lwp *l, struct vnode *vp, acl_type_t type, + const struct acl *aclp) +{ + struct acl *inkernelacl; + int error; + + inkernelacl = acl_alloc(KM_SLEEP); + error = acl_copyin(aclp, inkernelacl, type); + if (error != 0) + goto out; + error = VOP_ACLCHECK(vp, acl_type_unold(type), inkernelacl, + l->l_cred); +out: + acl_free(inkernelacl); + return error; +} + +/* + * syscalls -- convert the path/fd to a vnode, and call vacl_whatever. Don't + * need to lock, as the vacl_ code will get/release any locks required. + */ + +/* + * Given a file path, get an ACL for it + */ +int +sys___acl_get_file(struct lwp *l, + const struct sys___acl_get_file_args *uap, register_t *retval) +{ + + return kern___acl_get_path(l, SCARG(uap, path), SCARG(uap, type), + SCARG(uap, aclp), NSM_FOLLOW_NOEMULROOT); +} + +/* + * Given a file path, get an ACL for it; don't follow links. + */ +int +sys___acl_get_link(struct lwp *l, + const struct sys___acl_get_link_args *uap, register_t *retval) +{ + + return kern___acl_get_path(l, SCARG(uap, path), SCARG(uap, type), + SCARG(uap, aclp), NSM_NOFOLLOW_NOEMULROOT); +} + +int +kern___acl_get_path(struct lwp *l, const char *path, acl_type_t type, + struct acl *aclp, namei_simple_flags_t flags) +{ + struct vnode *path_vp; + int error; + + error = namei_simple_user(path, flags, &path_vp); + if (error == 0) { + error = vacl_get_acl(l, path_vp, type, aclp); + vrele(path_vp); + } + return error; +} + +/* + * Given a file path, set an ACL for it. + */ +int +sys___acl_set_file(struct lwp *l, + const struct sys___acl_set_file_args *uap, register_t *retval) +{ + + return kern___acl_set_path(l, SCARG(uap, path), SCARG(uap, type), + SCARG(uap, aclp), NSM_FOLLOW_NOEMULROOT); +} + +/* + * Given a file path, set an ACL for it; don't follow links. + */ +int +sys___acl_set_link(struct lwp *l, + const struct sys___acl_set_link_args *uap, register_t *retval) +{ + + return kern___acl_set_path(l, SCARG(uap, path), SCARG(uap, type), + SCARG(uap, aclp), NSM_NOFOLLOW_NOEMULROOT); +} + +int +kern___acl_set_path(struct lwp *l, const char *path, + acl_type_t type, const struct acl *aclp, namei_simple_flags_t flags) +{ + struct vnode *path_vp; + int error; + + error = namei_simple_user(path, flags, &path_vp); + if (error == 0) { + error = vacl_set_acl(l, path_vp, type, aclp); + vrele(path_vp); + } + return error; +} + +/* + * Given a file descriptor, get an ACL for it. + */ +int +sys___acl_get_fd(struct lwp *l, const struct sys___acl_get_fd_args *uap, + register_t *retval) +{ + struct file *fp; + int error; + error = fd_getvnode(SCARG(uap, filedes), &fp); + if (error == 0) { + error = vacl_get_acl(l, fp->f_vnode, SCARG(uap, type), + SCARG(uap, aclp)); + fd_putfile(SCARG(uap, filedes)); + } + return error; +} + +/* + * Given a file descriptor, set an ACL for it. + */ +int +sys___acl_set_fd(struct lwp *l, const struct sys___acl_set_fd_args *uap, + register_t *retval) +{ + struct file *fp; + int error; + + error = fd_getvnode(SCARG(uap, filedes), &fp); + if (error == 0) { + error = vacl_set_acl(l, fp->f_vnode, SCARG(uap, type), + SCARG(uap, aclp)); + fd_putfile(SCARG(uap, filedes)); + } + return error; +} + +/* + * Given a file path, delete an ACL from it. + */ +int +sys___acl_delete_file(struct lwp *l, + const struct sys___acl_delete_file_args *uap, register_t *retval) +{ + + return kern___acl_delete_path(l, SCARG(uap, path), SCARG(uap, type), + NSM_FOLLOW_NOEMULROOT); +} + +/* + * Given a file path, delete an ACL from it; don't follow links. + */ +int +sys___acl_delete_link(struct lwp *l, + const struct sys___acl_delete_link_args *uap, register_t *retval) +{ + + return kern___acl_delete_path(l, SCARG(uap, path), SCARG(uap, type), + NSM_NOFOLLOW_NOEMULROOT); +} + +int +kern___acl_delete_path(struct lwp *l, const char *path, + acl_type_t type, namei_simple_flags_t flags) +{ + struct vnode *path_vp; + int error; + + error = namei_simple_user(path, flags, &path_vp); + if (error == 0) { + error = vacl_delete(l, path_vp, type); + vrele(path_vp); + } + return error; +} + +/* + * Given a file path, delete an ACL from it. + */ +int +sys___acl_delete_fd(struct lwp *l, + const struct sys___acl_delete_fd_args *uap, register_t *retval) +{ + struct file *fp; + int error; + + error = fd_getvnode(SCARG(uap, filedes), &fp); + if (error == 0) { + error = vacl_delete(l, fp->f_vnode, SCARG(uap, type)); + fd_putfile(SCARG(uap, filedes)); + } + return error; +} + +/* + * Given a file path, check an ACL for it. + */ +int +sys___acl_aclcheck_file(struct lwp *l, + const struct sys___acl_aclcheck_file_args *uap, register_t *retval) +{ + + return kern___acl_aclcheck_path(l, SCARG(uap, path), SCARG(uap, type), + SCARG(uap, aclp), NSM_FOLLOW_NOEMULROOT); +} + +/* + * Given a file path, check an ACL for it; don't follow links. + */ +int +sys___acl_aclcheck_link(struct lwp *l, + const struct sys___acl_aclcheck_link_args *uap, register_t *retval) +{ + return kern___acl_aclcheck_path(l, SCARG(uap, path), + SCARG(uap, type), SCARG(uap, aclp), NSM_NOFOLLOW_NOEMULROOT); +} + +int +kern___acl_aclcheck_path(struct lwp *l, const char *path, acl_type_t type, + struct acl *aclp, namei_simple_flags_t flags) +{ + struct vnode *path_vp; + int error; + + error = namei_simple_user(path, flags, &path_vp); + if (error == 0) { + error = vacl_aclcheck(l, path_vp, type, aclp); + vrele(path_vp); + + } + return error; +} + +/* + * Given a file descriptor, check an ACL for it. + */ +int +sys___acl_aclcheck_fd(struct lwp *l, + const struct sys___acl_aclcheck_fd_args *uap, register_t *retval) +{ + struct file *fp; + int error; + + error = fd_getvnode(SCARG(uap, filedes), &fp); + if (error == 0) { + error = vacl_aclcheck(l, fp->f_vnode, SCARG(uap, type), + SCARG(uap, aclp)); + fd_putfile(SCARG(uap, filedes)); + } + return error; +} + +struct acl * +acl_alloc(int flags) +{ + struct acl *aclp; + + aclp = kmem_zalloc(sizeof(*aclp), flags); + if (aclp == NULL) + return NULL; + + aclp->acl_maxcnt = ACL_MAX_ENTRIES; + + return aclp; +} + +void +acl_free(struct acl *aclp) +{ + + kmem_free(aclp, sizeof(*aclp)); +} Index: sys/kern/vfs_cache.c =================================================================== RCS file: /cvsroot/src/sys/kern/vfs_cache.c,v retrieving revision 1.142 diff -u -p -p -u -r1.142 vfs_cache.c --- sys/kern/vfs_cache.c 12 May 2020 23:17:41 -0000 1.142 +++ sys/kern/vfs_cache.c 16 May 2020 16:14:08 -0000 @@ -689,8 +689,8 @@ cache_lookup_linked(struct vnode *dvp, c KASSERT(dvi->vi_nc_uid != VNOVAL && dvi->vi_nc_gid != VNOVAL); error = kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(VEXEC, dvp->v_type, dvi->vi_nc_mode & ALLPERMS), dvp, NULL, - genfs_can_access(dvp->v_type, dvi->vi_nc_mode & ALLPERMS, - dvi->vi_nc_uid, dvi->vi_nc_gid, VEXEC, cred)); + genfs_can_access(dvp, cred, dvi->vi_nc_uid, dvi->vi_nc_gid, + dvi->vi_nc_mode & ALLPERMS, NULL, VEXEC)); if (error != 0) { COUNT(ncs_denied); return false; @@ -741,7 +741,7 @@ cache_lookup_linked(struct vnode *dvp, c */ int cache_revlookup(struct vnode *vp, struct vnode **dvpp, char **bpp, char *bufp, - bool checkaccess, int perms) + bool checkaccess, accmode_t accmode) { vnode_impl_t *vi = VNODE_TO_VIMPL(vp); struct namecache *ncp; @@ -772,9 +772,9 @@ cache_revlookup(struct vnode *vp, struct KASSERT(vi->vi_nc_uid != VNOVAL && vi->vi_nc_gid != VNOVAL); error = kauth_authorize_vnode(curlwp->l_cred, KAUTH_ACCESS_ACTION(VEXEC, vp->v_type, vi->vi_nc_mode & - ALLPERMS), vp, NULL, genfs_can_access(vp->v_type, - vi->vi_nc_mode & ALLPERMS, vi->vi_nc_uid, vi->vi_nc_gid, - perms, curlwp->l_cred)); + ALLPERMS), vp, NULL, genfs_can_access(vp, curlwp->l_cred, + vi->vi_nc_uid, vi->vi_nc_gid, vi->vi_nc_mode & ALLPERMS, + NULL, accmode)); if (error != 0) { rw_exit(&vi->vi_nc_listlock); COUNT(ncs_denied); Index: sys/kern/vfs_getcwd.c =================================================================== RCS file: /cvsroot/src/sys/kern/vfs_getcwd.c,v retrieving revision 1.59 diff -u -p -p -u -r1.59 vfs_getcwd.c --- sys/kern/vfs_getcwd.c 21 Apr 2020 21:42:47 -0000 1.59 +++ sys/kern/vfs_getcwd.c 16 May 2020 16:14:08 -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 -p -u -r1.50 vfs_init.c --- sys/kern/vfs_init.c 21 Feb 2020 00:26:22 -0000 1.50 +++ sys/kern/vfs_init.c 16 May 2020 16:14:08 -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 -p -u -r1.486 vfs_subr.c --- sys/kern/vfs_subr.c 21 Apr 2020 21:42:47 -0000 1.486 +++ sys/kern/vfs_subr.c 16 May 2020 16:14:08 -0000 @@ -1138,21 +1138,6 @@ 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) -{ - -#ifdef DIAGNOSTIC - printf("vaccess: deprecated interface used.\n"); -#endif /* DIAGNOSTIC */ - - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(acc_mode, - type, file_mode), NULL /* This may panic. */, NULL, - genfs_can_access(type, file_mode, uid, gid, acc_mode, cred)); -} - /* * Given a file system name, look up the vfsops for that * file system, or return NULL if file system isn't present @@ -1278,6 +1263,53 @@ vfs_timestamp(struct timespec *ts) nanotime(ts); } +/* + * The purpose of this routine is to remove granularity from accmode_t, + * reducing it into standard unix access bits - VEXEC, VREAD, VWRITE, + * VADMIN and VAPPEND. + * + * If it returns 0, the caller is supposed to continue with the usual + * access checks using 'accmode' as modified by this routine. If it + * returns nonzero value, the caller is supposed to return that value + * as errno. + * + * Note that after this routine runs, accmode may be zero. + */ +int +vfs_unixify_accmode(accmode_t *accmode) +{ + /* + * There is no way to specify explicit "deny" rule using + * file mode or POSIX.1e ACLs. + */ + if (*accmode & VEXPLICIT_DENY) { + *accmode = 0; + return (0); + } + + /* + * None of these can be translated into usual access bits. + * Also, the common case for NFSv4 ACLs is to not contain + * either of these bits. Caller should check for VWRITE + * on the containing directory instead. + */ + if (*accmode & (VDELETE_CHILD | VDELETE)) + return (EPERM); + + if (*accmode & VADMIN_PERMS) { + *accmode &= ~VADMIN_PERMS; + *accmode |= VADMIN; + } + + /* + * There is no way to deny VREAD_ATTRIBUTES, VREAD_ACL + * or VSYNCHRONIZE using file mode or POSIX.1e ACL. + */ + *accmode &= ~(VSTAT_PERMS | VSYNCHRONIZE); + + return (0); +} + time_t rootfstime; /* recorded root fs time, if known */ void setrootfstime(time_t t) Index: sys/kern/vfs_syscalls.c =================================================================== RCS file: /cvsroot/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.547 diff -u -p -p -u -r1.547 vfs_syscalls.c --- sys/kern/vfs_syscalls.c 21 Apr 2020 21:42:47 -0000 1.547 +++ sys/kern/vfs_syscalls.c 16 May 2020 16:14:08 -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 -p -u -r1.34 vfs_xattr.c --- sys/kern/vfs_xattr.c 20 Apr 2020 00:34:58 -0000 1.34 +++ sys/kern/vfs_xattr.c 16 May 2020 16:14:08 -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(vp, cred, access, attrspace)); } /* Index: sys/kern/vnode_if.c =================================================================== RCS file: /cvsroot/src/sys/kern/vnode_if.c,v retrieving revision 1.110 diff -u -p -p -u -r1.110 vnode_if.c --- sys/kern/vnode_if.c 23 Feb 2020 22:15:19 -0000 1.110 +++ sys/kern/vnode_if.c 16 May 2020 16:14:08 -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 -p -u -r1.69 vnode_if.sh --- sys/kern/vnode_if.sh 23 Feb 2020 22:14:04 -0000 1.69 +++ sys/kern/vnode_if.sh 16 May 2020 16:14:08 -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 -p -u -r1.78 vnode_if.src --- sys/kern/vnode_if.src 11 Oct 2019 08:04:52 -0000 1.78 +++ sys/kern/vnode_if.src 16 May 2020 16:14:08 -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 -p -u -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 16 May 2020 16:14:08 -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 -p -u -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 16 May 2020 16:14:08 -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 -p -u -r1.33 genfs.h --- sys/miscfs/genfs/genfs.h 17 Feb 2017 08:31:25 -0000 1.33 +++ sys/miscfs/genfs/genfs.h 16 May 2020 16:14:08 -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,19 @@ void genfs_renamelock_exit(struct mount int genfs_suspendctl(struct mount *, int); -int genfs_can_access(enum vtype, mode_t, uid_t, gid_t, mode_t, - kauth_cred_t); -int genfs_can_chmod(enum vtype, kauth_cred_t, uid_t, gid_t, mode_t); -int genfs_can_chown(kauth_cred_t, uid_t, gid_t, uid_t, gid_t); -int genfs_can_chtimes(vnode_t *, u_int, uid_t, kauth_cred_t); -int genfs_can_chflags(kauth_cred_t, enum vtype, uid_t, bool); -int genfs_can_sticky(kauth_cred_t, uid_t, uid_t); -int genfs_can_extattr(kauth_cred_t, int, vnode_t *, const char *); +int genfs_can_access(struct vnode *, kauth_cred_t, uid_t, gid_t, mode_t, + struct acl *, accmode_t); +int genfs_can_access_acl_posix1e(struct vnode *, kauth_cred_t, uid_t, + gid_t, mode_t, struct acl *, accmode_t); +int genfs_can_access_acl_nfs4(struct vnode *, kauth_cred_t, uid_t, gid_t, + mode_t, struct acl *, accmode_t); +int genfs_can_chmod(struct vnode *, kauth_cred_t, uid_t, gid_t, mode_t); +int genfs_can_chown(struct vnode *, kauth_cred_t, uid_t, gid_t, uid_t, + gid_t); +int genfs_can_chtimes(struct vnode *, kauth_cred_t, uid_t, u_int); +int genfs_can_chflags(struct vnode *, kauth_cred_t, uid_t, bool); +int genfs_can_sticky(struct vnode *, kauth_cred_t, uid_t, uid_t); +int genfs_can_extattr(struct vnode *, kauth_cred_t, int, int); /* * Rename is complicated. Sorry. Index: sys/miscfs/genfs/genfs_rename.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/genfs/genfs_rename.c,v retrieving revision 1.3 diff -u -p -p -u -r1.3 genfs_rename.c --- sys/miscfs/genfs/genfs_rename.c 30 Mar 2017 09:11:12 -0000 1.3 +++ sys/miscfs/genfs/genfs_rename.c 16 May 2020 16:14:08 -0000 @@ -1148,7 +1148,7 @@ genfs_ufslike_check_sticky(kauth_cred_t { if ((dmode & S_ISTXT) && (vp != NULL)) - return genfs_can_sticky(cred, duid, uid); + return genfs_can_sticky(vp, cred, duid, uid); return 0; } Index: sys/miscfs/genfs/genfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/genfs/genfs_vnops.c,v retrieving revision 1.203 diff -u -p -p -u -r1.203 genfs_vnops.c --- sys/miscfs/genfs/genfs_vnops.c 25 Apr 2020 22:28:47 -0000 1.203 +++ sys/miscfs/genfs/genfs_vnops.c 16 May 2020 16:14:08 -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, cred, uid, gid, mode, acl, requested access mode. + * Returns 0 on success, or an errno on failure. */ int -genfs_can_access(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid, - mode_t acc_mode, kauth_cred_t cred) +genfs_can_access(vnode_t *vp, kauth_cred_t cred, uid_t file_uid, gid_t file_gid, + mode_t file_mode, struct acl *acl, accmode_t accmode) { - mode_t mask; - int error, ismember; + accmode_t dac_granted; + int error; + + KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND)) == 0); + KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE)); + + /* + * Look for a normal, non-privileged way to access the file/directory + * as requested. If it exists, go with that. + */ - mask = 0; + 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(vnode_t *vp, kauth_cred_t cred, uid_t file_uid, + gid_t file_gid, mode_t file_mode, struct acl *acl, accmode_t accmode) +{ + struct acl_entry *acl_other, *acl_mask; + accmode_t dac_granted; + accmode_t acl_mask_granted; + int group_matched, i; + int error; + + KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND)) == 0); + KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE)); + + /* + * The owner matches if the effective uid associated with the + * credential matches that of the ACL_USER_OBJ entry. While we're + * doing the first scan, also cache the location of the ACL_MASK and + * ACL_OTHER entries, preventing some future iterations. + */ + acl_mask = acl_other = NULL; + for (i = 0; i < acl->acl_cnt; i++) { + struct acl_entry *ae = &acl->acl_entry[i]; + switch (ae->ae_tag) { + case ACL_USER_OBJ: + if (kauth_cred_geteuid(cred) != file_uid) + break; + dac_granted = 0; + dac_granted |= VADMIN; + if (ae->ae_perm & ACL_EXECUTE) + dac_granted |= VEXEC; + if (ae->ae_perm & ACL_READ) + dac_granted |= VREAD; + if (ae->ae_perm & ACL_WRITE) + dac_granted |= (VWRITE | VAPPEND); + goto out; + + case ACL_MASK: + acl_mask = ae; + break; + + case ACL_OTHER: + acl_other = ae; + break; + + default: + break; + } + } + + /* + * An ACL_OTHER entry should always exist in a valid access ACL. If + * it doesn't, then generate a serious failure. For now, this means + * a debugging message and EPERM, but in the future should probably + * be a panic. + */ + if (acl_other == NULL) { + /* + * XXX This should never happen + */ + printf("%s: ACL_OTHER missing\n", __func__); + return EPERM; + } + + /* + * Checks against ACL_USER, ACL_GROUP_OBJ, and ACL_GROUP fields are + * masked by an ACL_MASK entry, if any. As such, first identify the + * ACL_MASK field, then iterate through identifying potential user + * matches, then group matches. If there is no ACL_MASK, assume that + * the mask allows all requests to succeed. + */ + if (acl_mask != NULL) { + acl_mask_granted = 0; + if (acl_mask->ae_perm & ACL_EXECUTE) + acl_mask_granted |= VEXEC; + if (acl_mask->ae_perm & ACL_READ) + acl_mask_granted |= VREAD; + if (acl_mask->ae_perm & ACL_WRITE) + acl_mask_granted |= (VWRITE | VAPPEND); + } else + acl_mask_granted = VEXEC | VREAD | VWRITE | VAPPEND; + + /* + * Check ACL_USER ACL entries. There will either be one or no + * matches; if there is one, we accept or rejected based on the + * match; otherwise, we continue on to groups. + */ + for (i = 0; i < acl->acl_cnt; i++) { + struct acl_entry *ae = &acl->acl_entry[i]; + switch (ae->ae_tag) { + case ACL_USER: + if (kauth_cred_geteuid(cred) != ae->ae_id) + break; + dac_granted = 0; + if (ae->ae_perm & ACL_EXECUTE) + dac_granted |= VEXEC; + if (ae->ae_perm & ACL_READ) + dac_granted |= VREAD; + if (ae->ae_perm & ACL_WRITE) + dac_granted |= (VWRITE | VAPPEND); + dac_granted &= acl_mask_granted; + goto out; + } + } + + /* + * Group match is best-match, not first-match, so find a "best" + * match. Iterate across, testing each potential group match. Make + * sure we keep track of whether we found a match or not, so that we + * know if we should try again with any available privilege, or if we + * should move on to ACL_OTHER. + */ + group_matched = 0; + for (i = 0; i < acl->acl_cnt; i++) { + struct acl_entry *ae = &acl->acl_entry[i]; + switch (ae->ae_tag) { + case ACL_GROUP_OBJ: + error = groupmember(file_gid, cred); + if (error > 0) + return error; + if (error) + break; + dac_granted = 0; + if (ae->ae_perm & ACL_EXECUTE) + dac_granted |= VEXEC; + if (ae->ae_perm & ACL_READ) + dac_granted |= VREAD; + if (ae->ae_perm & ACL_WRITE) + dac_granted |= (VWRITE | VAPPEND); + dac_granted &= acl_mask_granted; + + if ((accmode & dac_granted) == accmode) + return 0; + + group_matched = 1; + break; + + case ACL_GROUP: + error = groupmember(ae->ae_id, cred); + if (error > 0) + return error; + if (error) + break; + dac_granted = 0; + if (ae->ae_perm & ACL_EXECUTE) + dac_granted |= VEXEC; + if (ae->ae_perm & ACL_READ) + dac_granted |= VREAD; + if (ae->ae_perm & ACL_WRITE) + dac_granted |= (VWRITE | VAPPEND); + dac_granted &= acl_mask_granted; + + if ((accmode & dac_granted) == accmode) + return 0; + + group_matched = 1; + break; + + default: + break; + } + } + + if (group_matched == 1) { + /* + * There was a match, but it did not grant rights via pure + * DAC. Try again, this time with privilege. + */ + for (i = 0; i < acl->acl_cnt; i++) { + struct acl_entry *ae = &acl->acl_entry[i]; + switch (ae->ae_tag) { + case ACL_GROUP_OBJ: + error = groupmember(file_gid, cred); + if (error > 0) + return error; + if (error) + break; + dac_granted = 0; + if (ae->ae_perm & ACL_EXECUTE) + dac_granted |= VEXEC; + if (ae->ae_perm & ACL_READ) + dac_granted |= VREAD; + if (ae->ae_perm & ACL_WRITE) + dac_granted |= (VWRITE | VAPPEND); + dac_granted &= acl_mask_granted; + goto out; + + case ACL_GROUP: + error = groupmember(ae->ae_id, cred); + if (error > 0) + return error; + if (error) + break; + dac_granted = 0; + if (ae->ae_perm & ACL_EXECUTE) + dac_granted |= VEXEC; + if (ae->ae_perm & ACL_READ) + dac_granted |= VREAD; + if (ae->ae_perm & ACL_WRITE) + dac_granted |= (VWRITE | VAPPEND); + dac_granted &= acl_mask_granted; + + goto out; + default: + break; + } + } + /* + * Even with privilege, group membership was not sufficient. + * Return failure. + */ + dac_granted = 0; + goto out; + } + + /* + * Fall back on ACL_OTHER. ACL_MASK is not applied to ACL_OTHER. + */ + dac_granted = 0; + if (acl_other->ae_perm & ACL_EXECUTE) + dac_granted |= VEXEC; + if (acl_other->ae_perm & ACL_READ) + dac_granted |= VREAD; + if (acl_other->ae_perm & ACL_WRITE) + dac_granted |= (VWRITE | VAPPEND); + +out: + if ((accmode & dac_granted) == accmode) + return 0; + return (accmode & VADMIN) ? EPERM : EACCES; +} + +static struct { + accmode_t accmode; + int mask; +} accmode2mask[] = { + { VREAD, ACL_READ_DATA }, + { VWRITE, ACL_WRITE_DATA }, + { VAPPEND, ACL_APPEND_DATA }, + { VEXEC, ACL_EXECUTE }, + { VREAD_NAMED_ATTRS, ACL_READ_NAMED_ATTRS }, + { VWRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS }, + { VDELETE_CHILD, ACL_DELETE_CHILD }, + { VREAD_ATTRIBUTES, ACL_READ_ATTRIBUTES }, + { VWRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES }, + { VDELETE, ACL_DELETE }, + { VREAD_ACL, ACL_READ_ACL }, + { VWRITE_ACL, ACL_WRITE_ACL }, + { VWRITE_OWNER, ACL_WRITE_OWNER }, + { VSYNCHRONIZE, ACL_SYNCHRONIZE }, + { 0, 0 }, +}; + +static int +_access_mask_from_accmode(accmode_t accmode) +{ + int access_mask = 0, i; + + for (i = 0; accmode2mask[i].accmode != 0; i++) { + if (accmode & accmode2mask[i].accmode) + access_mask |= accmode2mask[i].mask; + } + + /* + * VAPPEND is just a modifier for VWRITE; if the caller asked + * for 'VAPPEND | VWRITE', we want to check for ACL_APPEND_DATA only. + */ + if (access_mask & ACL_APPEND_DATA) + access_mask &= ~ACL_WRITE_DATA; + + return (access_mask); +} + +/* + * Return 0, iff access is allowed, 1 otherwise. + */ +static int +_acl_denies(const struct acl *aclp, int access_mask, kauth_cred_t cred, + int file_uid, int file_gid, int *denied_explicitly) +{ + int i, error; + const struct acl_entry *ae; + + if (denied_explicitly != NULL) + *denied_explicitly = 0; + + KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES); + + for (i = 0; i < aclp->acl_cnt; i++) { + ae = &(aclp->acl_entry[i]); + + if (ae->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && + ae->ae_entry_type != ACL_ENTRY_TYPE_DENY) + continue; + if (ae->ae_flags & ACL_ENTRY_INHERIT_ONLY) + continue; + switch (ae->ae_tag) { + case ACL_USER_OBJ: + if (kauth_cred_geteuid(cred) != file_uid) + continue; + break; + case ACL_USER: + if (kauth_cred_geteuid(cred) != ae->ae_id) + continue; + break; + case ACL_GROUP_OBJ: + error = groupmember(file_gid, cred); + if (error > 0) + return error; + if (error != 0) + continue; + break; + case ACL_GROUP: + error = groupmember(ae->ae_id, cred); + if (error > 0) + return error; + if (error != 0) + continue; + break; + default: + KASSERT(ae->ae_tag == ACL_EVERYONE); + } + + if (ae->ae_entry_type == ACL_ENTRY_TYPE_DENY) { + if (ae->ae_perm & access_mask) { + if (denied_explicitly != NULL) + *denied_explicitly = 1; + return (1); + } + } + + access_mask &= ~(ae->ae_perm); + if (access_mask == 0) + return (0); + } + + if (access_mask == 0) + return (0); + + return (1); +} + +int +genfs_can_access_acl_nfs4(vnode_t *vp, kauth_cred_t cred, uid_t file_uid, + gid_t file_gid, mode_t file_mode, struct acl *aclp, accmode_t accmode) +{ + int denied, explicitly_denied, access_mask, is_directory, + must_be_owner = 0; + file_mode = 0; + + KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND | + VEXPLICIT_DENY | VREAD_NAMED_ATTRS | VWRITE_NAMED_ATTRS | + VDELETE_CHILD | VREAD_ATTRIBUTES | VWRITE_ATTRIBUTES | VDELETE | + VREAD_ACL | VWRITE_ACL | VWRITE_OWNER | VSYNCHRONIZE)) == 0); + KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE)); + +#ifdef ACL_DEBUG + char buf[128]; + snprintb(buf, sizeof(buf), __VNODE_PERM_BITS, accmode); + printf("%s: %s uid=%d gid=%d\n", __func__, buf, file_uid, file_gid); +#endif + + if (accmode & VADMIN) + must_be_owner = 1; + + /* + * Ignore VSYNCHRONIZE permission. + */ + accmode &= ~VSYNCHRONIZE; + + access_mask = _access_mask_from_accmode(accmode); + + if (vp && vp->v_type == VDIR) + is_directory = 1; + else + is_directory = 0; + + /* + * File owner is always allowed to read and write the ACL + * and basic attributes. This is to prevent a situation + * where user would change ACL in a way that prevents him + * from undoing the change. + */ + if (kauth_cred_geteuid(cred) == file_uid) + access_mask &= ~(ACL_READ_ACL | ACL_WRITE_ACL | + ACL_READ_ATTRIBUTES | ACL_WRITE_ATTRIBUTES); + + /* + * Ignore append permission for regular files; use write + * permission instead. + */ + if (!is_directory && (access_mask & ACL_APPEND_DATA)) { + access_mask &= ~ACL_APPEND_DATA; + access_mask |= ACL_WRITE_DATA; + } + + denied = _acl_denies(aclp, access_mask, cred, file_uid, file_gid, + &explicitly_denied); + + if (must_be_owner) { + if (kauth_cred_geteuid(cred) != file_uid) + denied = EPERM; + } + + /* + * For VEXEC, ensure that at least one execute bit is set for + * non-directories. We have to check the mode here to stay + * consistent with execve(2). See the test in + * exec_check_permissions(). + */ + __acl_nfs4_sync_mode_from_acl(&file_mode, aclp); + if (!denied && !is_directory && (accmode & VEXEC) && + (file_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) + denied = EACCES; + + if (!denied) + return (0); + + /* + * Access failed. Iff it was not denied explicitly and + * VEXPLICIT_DENY flag was specified, allow access. + */ + if ((accmode & VEXPLICIT_DENY) && explicitly_denied == 0) + return (0); + + accmode &= ~VEXPLICIT_DENY; + + if (accmode & (VADMIN_PERMS | VDELETE_CHILD | VDELETE)) + denied = EPERM; + else + denied = EACCES; + + return (denied); } /* @@ -724,29 +1191,32 @@ genfs_can_access(enum vtype type, mode_t * - You must own the file, and * - You must not set the "sticky" bit (meaningless, see chmod(2)) * - You must be a member of the group if you're trying to set the - * SGIDf bit + * SGIDf bit * - * cred - credentials of the invoker * vp - vnode of the file-system object + * cred - credentials of the invoker * cur_uid, cur_gid - current uid/gid of the file-system object * new_mode - new mode for the file-system object * * Returns 0 if the change is allowed, or an error value otherwise. */ int -genfs_can_chmod(enum vtype type, kauth_cred_t cred, uid_t cur_uid, +genfs_can_chmod(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid, gid_t cur_gid, mode_t new_mode) { int error; - /* The user must own the file. */ - if (kauth_cred_geteuid(cred) != cur_uid) - return (EPERM); + /* + * To modify the permissions on a file, must possess VADMIN + * for that file. + */ + if ((error = VOP_ACCESSX(vp, VWRITE_ACL, cred)) != 0) + return (error); /* * Unprivileged users can't set the sticky bit on files. */ - if ((type != VDIR) && (new_mode & S_ISTXT)) + if ((vp->v_type != VDIR) && (new_mode & S_ISTXT)) return (EFTYPE); /* @@ -762,6 +1232,12 @@ genfs_can_chmod(enum vtype type, kauth_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); } @@ -773,6 +1249,7 @@ genfs_can_chmod(enum vtype type, kauth_c * - You must not try to change ownership, and * - You must be member of the new group * + * vp - vnode * cred - credentials of the invoker * cur_uid, cur_gid - current uid/gid of the file-system object * new_uid, new_gid - target uid/gid of the file-system object @@ -780,12 +1257,19 @@ genfs_can_chmod(enum vtype type, kauth_c * Returns 0 if the change is allowed, or an error value otherwise. */ int -genfs_can_chown(kauth_cred_t cred, uid_t cur_uid, +genfs_can_chown(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid, gid_t cur_gid, uid_t new_uid, gid_t new_gid) { int error, ismember; /* + * To modify the ownership of a file, must possess VADMIN for that + * file. + */ + if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred)) != 0) + return (error); + + /* * You can only change ownership of a file if: * You own the file and... */ @@ -822,10 +1306,23 @@ genfs_can_chown(kauth_cred_t cred, uid_t } int -genfs_can_chtimes(vnode_t *vp, u_int vaflags, uid_t owner_uid, - kauth_cred_t cred) +genfs_can_chtimes(vnode_t *vp, kauth_cred_t cred, uid_t owner_uid, + u_int vaflags) { int error; + /* + * Grant permission if the caller is the owner of the file, or + * the super-user, or has ACL_WRITE_ATTRIBUTES permission on + * on the file. If the time pointer is null, then write + * permission on the file is also sufficient. + * + * From NFSv4.1, draft 21, 6.2.1.3.1, Discussion of Mask Attributes: + * A user having ACL_WRITE_DATA or ACL_WRITE_ATTRIBUTES + * will be allowed to set the times [..] to the current + * server time. + */ + if ((error = VOP_ACCESSX(vp, VWRITE_ATTRIBUTES, cred)) != 0) + return (error); /* Must be owner, or... */ if (kauth_cred_geteuid(cred) == owner_uid) @@ -851,13 +1348,14 @@ genfs_can_chtimes(vnode_t *vp, u_int vaf * - You must not change system flags, and * - You must not change flags on character/block devices. * + * vp - vnode * cred - credentials of the invoker * owner_uid - uid of the file-system object * changing_sysflags - true if the invoker wants to change system flags */ int -genfs_can_chflags(kauth_cred_t cred, enum vtype type, uid_t owner_uid, - bool changing_sysflags) +genfs_can_chflags(vnode_t *vp, kauth_cred_t cred, + uid_t owner_uid, bool changing_sysflags) { /* The user must own the file. */ @@ -873,7 +1371,7 @@ genfs_can_chflags(kauth_cred_t cred, enu * Unprivileged users cannot change the flags on devices, even if they * own them. */ - if (type == VCHR || type == VBLK) { + if (vp->v_type == VCHR || vp->v_type == VBLK) { return EPERM; } @@ -891,7 +1389,7 @@ genfs_can_chflags(kauth_cred_t cred, enu * directory or the file being deleted. */ int -genfs_can_sticky(kauth_cred_t cred, uid_t dir_uid, uid_t file_uid) +genfs_can_sticky(vnode_t *vp, kauth_cred_t cred, uid_t dir_uid, uid_t file_uid) { if (kauth_cred_geteuid(cred) != dir_uid && kauth_cred_geteuid(cred) != file_uid) @@ -901,16 +1399,49 @@ genfs_can_sticky(kauth_cred_t cred, uid_ } int -genfs_can_extattr(kauth_cred_t cred, int access_mode, vnode_t *vp, - const char *attr) +genfs_can_extattr(vnode_t *vp, kauth_cred_t cred, int accmode, + int attrnamespace) { /* - * This string comparison is bogus: see xattr_native in vfs_xattr.c; - * it is going to go away soon. + * Kernel-invoked always succeeds. */ - if (strncasecmp(attr, "system.", 7) == 0) - return kauth_authorize_system(cred, KAUTH_SYSTEM_FS_EXTATTR, - 0, vp->v_mount, NULL, NULL); + if (cred == NOCRED) + return 0; + + switch (attrnamespace) { + case EXTATTR_NAMESPACE_SYSTEM: + return kauth_authorize_system(cred, KAUTH_SYSTEM_FS_EXTATTR, + 0, vp->v_mount, NULL, NULL); + case EXTATTR_NAMESPACE_USER: + return VOP_ACCESS(vp, accmode, cred); + default: + return EPERM; + } +} + +int +genfs_access(void *v) +{ + struct vop_access_args *ap = v; + + KASSERT((ap->a_accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | + VAPPEND)) == 0); + + return VOP_ACCESSX(ap->a_vp, ap->a_accmode, ap->a_cred); +} + +int +genfs_accessx(void *v) +{ + struct vop_accessx_args *ap = v; + int error; + accmode_t accmode = ap->a_accmode; + error = vfs_unixify_accmode(&accmode); + if (error != 0) + return error; + + if (accmode == 0) + return 0; - return VOP_ACCESS(vp, access_mode, cred); + return VOP_ACCESS(ap->a_vp, accmode, ap->a_cred); } 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 -p -u -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 16 May 2020 16:14:08 -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 -p -u -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 16 May 2020 16:14:08 -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), - ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode, - va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); + KAUTH_ACCESS_ACTION(ap->a_accmode, ap->a_vp->v_type, va.va_mode), + ap->a_vp, NULL, genfs_can_access(ap->a_vp, ap->a_cred, + va.va_uid, va.va_gid, va.va_mode, NULL, ap->a_accmode)); } static int 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 -p -u -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 16 May 2020 16:14:08 -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 -p -u -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 16 May 2020 16:14:08 -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.212 diff -u -p -p -u -r1.212 procfs_vnops.c --- sys/miscfs/procfs/procfs_vnops.c 29 Apr 2020 01:56:54 -0000 1.212 +++ sys/miscfs/procfs/procfs_vnops.c 16 May 2020 16:14:08 -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 */ @@ -969,7 +970,7 @@ procfs_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *ap = v; struct vattr va; @@ -979,9 +980,9 @@ procfs_access(void *v) return (error); return kauth_authorize_vnode(ap->a_cred, - KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode), - ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode, - va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); + KAUTH_ACCESS_ACTION(ap->a_accmode, ap->a_vp->v_type, va.va_mode), + ap->a_vp, NULL, genfs_can_access(ap->a_vp, ap->a_cred, + va.va_uid, va.va_gid, va.va_mode, NULL, ap->a_accmode)); } /* 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 -p -u -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 16 May 2020 16:14:08 -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 -p -u -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 16 May 2020 16:14:08 -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/compat_netbsd32/Makefile =================================================================== RCS file: /cvsroot/src/sys/modules/compat_netbsd32/Makefile,v retrieving revision 1.34 diff -u -p -p -u -r1.34 Makefile --- sys/modules/compat_netbsd32/Makefile 2 May 2020 22:19:47 -0000 1.34 +++ sys/modules/compat_netbsd32/Makefile 16 May 2020 16:14:09 -0000 @@ -29,6 +29,7 @@ CPPFLAGS+= -I${NETBSDSRCDIR}/sys/externa .if ${NETBSD32_DRMKMS:Uno} == "yes" SRCS+= netbsd32_drm.c .endif +SRCS+= netbsd32_acl.c SRCS+= netbsd32_core.c netbsd32_event.c SRCS+= netbsd32_exec_elf32.c netbsd32_execve.c SRCS+= netbsd32_fd.c netbsd32_fs.c Index: sys/modules/ffs/Makefile =================================================================== RCS file: /cvsroot/src/sys/modules/ffs/Makefile,v retrieving revision 1.14 diff -u -p -p -u -r1.14 Makefile --- sys/modules/ffs/Makefile 18 Apr 2020 19:18:33 -0000 1.14 +++ sys/modules/ffs/Makefile 16 May 2020 16:14:09 -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 -p -u -r1.3 Makefile --- sys/modules/ufs/Makefile 12 Apr 2020 01:39:57 -0000 1.3 +++ sys/modules/ufs/Makefile 16 May 2020 16:14:09 -0000 @@ -5,12 +5,12 @@ KMOD= ufs CPPFLAGS+= -DUFS_DIRHASH -DFFS_EI -DWAPBL -DAPPLE_UFS -DQUOTA -DQUOTA2 -CPPFLAGS+= -DUFS_EXTATTR +CPPFLAGS+= -DUFS_EXTATTR -DUFS_ACL CWARNFLAGS.clang= -Wno-conversion .PATH: ${S}/ufs/ufs -SRCS= ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \ +SRCS= ufs_acl.c ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \ ufs_lookup.c ufs_quota.c ufs_quota1.c ufs_quota2.c ufs_rename.c \ ufs_vfsops.c ufs_vnops.c quota1_subr.c quota2_subr.c Index: sys/nfs/nfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/nfs/nfs_vnops.c,v retrieving revision 1.314 diff -u -p -p -u -r1.314 nfs_vnops.c --- sys/nfs/nfs_vnops.c 13 Apr 2020 19:23:20 -0000 1.314 +++ sys/nfs/nfs_vnops.c 16 May 2020 16:14:09 -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( + vp, ap->a_cred, va.va_uid, va.va_gid, va.va_mode, NULL, + ap->a_accmode)); } /* Index: sys/rump/rump.sysmap =================================================================== RCS file: /cvsroot/src/sys/rump/rump.sysmap,v retrieving revision 1.6 diff -u -p -p -u -r1.6 rump.sysmap --- sys/rump/rump.sysmap 22 Sep 2019 23:03:20 -0000 1.6 +++ sys/rump/rump.sysmap 16 May 2020 16:14:09 -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.19 diff -u -p -p -u -r1.19 Makefile --- sys/rump/fs/lib/libffs/Makefile 25 Apr 2020 15:42:15 -0000 1.19 +++ sys/rump/fs/lib/libffs/Makefile 16 May 2020 16:14:09 -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.118 diff -u -p -p -u -r1.118 rump_syscalls.h --- sys/rump/include/rump/rump_syscalls.h 26 Apr 2020 19:16:36 -0000 1.118 +++ sys/rump/include/rump/rump_syscalls.h 16 May 2020 16:14:09 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: rump_syscalls.h,v 1.118 2020/04/26 19:16:36 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 -p -u -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 16 May 2020 16:14:09 -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.149 diff -u -p -p -u -r1.149 rump_syscalls.c --- sys/rump/librump/rumpkern/rump_syscalls.c 26 Apr 2020 19:16:36 -0000 1.149 +++ sys/rump/librump/rumpkern/rump_syscalls.c 16 May 2020 16:14:09 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: rump_syscalls.c,v 1.149 2020/04/26 19:16:36 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.149 2020/04/26 19:16:36 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) @@ -8445,57 +8474,45 @@ struct sysent rump_sysent[] = { .sy_call = (sy_call_t *)(void *)rumpns_enosys, }, /* 486 = __fhstatvfs190 */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 487 = filler */ +}, /* 487 = __acl_get_link */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 488 = filler */ +}, /* 488 = __acl_set_link */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 489 = filler */ +}, /* 489 = __acl_delete_link */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 490 = filler */ +}, /* 490 = __acl_aclcheck_link */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 491 = filler */ +}, /* 491 = __acl_get_file */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 492 = filler */ +}, /* 492 = __acl_set_file */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 493 = filler */ +}, /* 493 = __acl_get_fd */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 494 = filler */ +}, /* 494 = __acl_set_fd */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 495 = filler */ +}, /* 495 = __acl_delete_file */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 496 = filler */ +}, /* 496 = __acl_delete_fd */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 497 = filler */ +}, /* 497 = __acl_aclcheck_file */ { - .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 498 = filler */ +}, /* 498 = __acl_aclcheck_fd */ { - .sy_flags = SYCALL_NOSYS, + ns(struct sys_lpathconf_args), .sy_call = (sy_call_t *)(void *)rumpns_enosys, - }, /* 499 = filler */ + }, /* 499 = lpathconf */ { .sy_flags = SYCALL_NOSYS, .sy_call = (sy_call_t *)(void *)rumpns_enosys, 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 -p -u -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 16 May 2020 16:14:09 -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.161 diff -u -p -p -u -r1.161 rumpfs.c --- sys/rump/librump/rumpvfs/rumpfs.c 15 May 2020 23:32:28 -0000 1.161 +++ sys/rump/librump/rumpvfs/rumpfs.c 16 May 2020 16:14:09 -0000 @@ -101,6 +101,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 }, @@ -815,13 +816,13 @@ rump_check_possible(struct vnode *vp, st static int rump_check_permitted(struct vnode *vp, struct rumpfs_node *rnode, - mode_t mode, kauth_cred_t cred) + accmode_t accmode, kauth_cred_t cred) { struct vattr *attr = &rnode->rn_va; - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, - vp->v_type, attr->va_mode), vp, NULL, genfs_can_access(vp->v_type, - attr->va_mode, attr->va_uid, attr->va_gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, attr->va_mode), vp, NULL, genfs_can_access(vp, cred, + attr->va_uid, attr->va_gid, attr->va_mode, NULL, accmode)); } int @@ -837,11 +838,11 @@ rump_vop_access(void *v) struct rumpfs_node *rn = vp->v_data; int error; - error = rump_check_possible(vp, rn, ap->a_mode); + error = rump_check_possible(vp, rn, ap->a_accmode); if (error) return error; - error = rump_check_permitted(vp, rn, ap->a_mode, ap->a_cred); + error = rump_check_permitted(vp, rn, ap->a_accmode, ap->a_cred); return error; } @@ -890,8 +891,8 @@ rump_vop_setattr(void *v) CHANGED(va_mtime.tv_nsec, long) || CHANGED(va_birthtime.tv_nsec, long)) { error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, - NULL, genfs_can_chtimes(vp, vap->va_vaflags, attr->va_uid, - cred)); + NULL, genfs_can_chtimes(vp, cred, attr->va_uid, + vap->va_vaflags)); if (error) return error; } @@ -919,8 +920,7 @@ rump_vop_setattr(void *v) if (CHANGED(va_flags, u_long)) { /* XXX Can we handle system flags here...? */ error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp, - NULL, genfs_can_chflags(cred, vp->v_type, attr->va_uid, - false)); + NULL, genfs_can_chflags(vp, cred, attr->va_uid, false)); if (error) return error; } @@ -936,7 +936,7 @@ rump_vop_setattr(void *v) (vap->va_gid != (gid_t)VNOVAL) ? vap->va_gid : attr->va_gid; error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, NULL, - genfs_can_chown(cred, attr->va_uid, attr->va_gid, uid, + genfs_can_chown(vp, cred, attr->va_uid, attr->va_gid, uid, gid)); if (error) return error; @@ -947,7 +947,7 @@ rump_vop_setattr(void *v) if (vap->va_mode != (mode_t)VNOVAL) { mode_t mode = vap->va_mode; error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, - vp, NULL, genfs_can_chmod(vp->v_type, cred, attr->va_uid, + vp, NULL, genfs_can_chmod(vp, cred, attr->va_uid, attr->va_gid, mode)); if (error) return error; 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 -p -u -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 16 May 2020 16:14:09 -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.173 diff -u -p -p -u -r1.173 Makefile --- sys/sys/Makefile 26 Apr 2020 18:53:33 -0000 1.173 +++ sys/sys/Makefile 16 May 2020 16:14:09 -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 16 May 2020 16:14:09 -0000 @@ -0,0 +1,440 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 1999-2001 Robert N. M. Watson + * Copyright (c) 2008 Edward Tomasz NapieraƂa + * 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) || defined(_MODULE) + +#define POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE EXTATTR_NAMESPACE_SYSTEM +#define POSIX1E_ACL_ACCESS_EXTATTR_NAME "posix1e.acl_access" +#define POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE EXTATTR_NAMESPACE_SYSTEM +#define POSIX1E_ACL_DEFAULT_EXTATTR_NAME "posix1e.acl_default" +#define NFS4_ACL_EXTATTR_NAMESPACE EXTATTR_NAMESPACE_SYSTEM +#define NFS4_ACL_EXTATTR_NAME "nfs4.acl" +#define OLDACL_MAX_ENTRIES 32 + +/* + * "struct oldacl" is used in compatibility ACL syscalls and for on-disk + * storage of POSIX.1e ACLs. + */ +typedef int oldacl_tag_t; +typedef mode_t oldacl_perm_t; + +struct oldacl_entry { + oldacl_tag_t ae_tag; + uid_t ae_id; + oldacl_perm_t ae_perm; +}; +typedef struct oldacl_entry *oldacl_entry_t; + +struct oldacl { + int acl_cnt; + struct oldacl_entry acl_entry[OLDACL_MAX_ENTRIES]; +}; + +/* + * Current "struct acl". + */ +struct acl_entry { + acl_tag_t ae_tag; + uid_t ae_id; + acl_perm_t ae_perm; + /* NFSv4 entry type, "allow" or "deny". Unused in POSIX.1e ACLs. */ + acl_entry_type_t ae_entry_type; + /* NFSv4 ACL inheritance. Unused in POSIX.1e ACLs. */ + acl_flag_t ae_flags; +}; +typedef struct acl_entry *acl_entry_t; + +/* + * Internal ACL structure, used in libc, kernel APIs and for on-disk + * storage of NFSv4 ACLs. POSIX.1e ACLs use "struct oldacl" for on-disk + * storage. + */ +struct acl { + unsigned int acl_maxcnt; + unsigned int acl_cnt; + /* Will be required e.g. to implement NFSv4.1 ACL inheritance. */ + int acl_spare[4]; + struct acl_entry acl_entry[ACL_MAX_ENTRIES]; +}; + +/* + * ACL structure internal to libc. + */ +struct acl_t_struct { + struct acl ats_acl; + unsigned int ats_cur_entry; + /* + * ats_brand is for libc internal bookkeeping only. + * Applications should use acl_get_brand_np(3). + * Kernel code should use the "type" argument passed + * to VOP_SETACL, VOP_GETACL or VOP_ACLCHECK calls; + * ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT mean POSIX.1e + * ACL, ACL_TYPE_NFS4 means NFSv4 ACL. + */ + int ats_brand; +}; +typedef struct acl_t_struct *acl_t; + +#else /* _KERNEL || _ACL_PRIVATE */ + +typedef void *acl_entry_t; +typedef void *acl_t; + +#endif /* !_KERNEL && !_ACL_PRIVATE */ + +/* + * Possible valid values for ats_brand field. + */ +#define ACL_BRAND_UNKNOWN 0 +#define ACL_BRAND_POSIX 1 +#define ACL_BRAND_NFS4 2 + +/* + * Possible valid values for ae_tag field. For explanation, see acl(9). + */ +#define ACL_UNDEFINED_TAG 0x00000000 +#define ACL_USER_OBJ 0x00000001 +#define ACL_USER 0x00000002 +#define ACL_GROUP_OBJ 0x00000004 +#define ACL_GROUP 0x00000008 +#define ACL_MASK 0x00000010 +#define ACL_OTHER 0x00000020 +#define ACL_OTHER_OBJ ACL_OTHER +#define ACL_EVERYONE 0x00000040 + +/* + * Possible valid values for ae_entry_type field, valid only for NFSv4 ACLs. + */ +#define ACL_ENTRY_TYPE_ALLOW 0x0100 +#define ACL_ENTRY_TYPE_DENY 0x0200 +#define ACL_ENTRY_TYPE_AUDIT 0x0400 +#define ACL_ENTRY_TYPE_ALARM 0x0800 + +/* + * Possible valid values for acl_type_t arguments. First two + * are provided only for backwards binary compatibility. + */ +#define ACL_TYPE_ACCESS_OLD 0x00000000 +#define ACL_TYPE_DEFAULT_OLD 0x00000001 +#define ACL_TYPE_ACCESS 0x00000002 +#define ACL_TYPE_DEFAULT 0x00000003 +#define ACL_TYPE_NFS4 0x00000004 + +/* + * Possible bits in ae_perm field for POSIX.1e ACLs. Note + * that ACL_EXECUTE may be used in both NFSv4 and POSIX.1e ACLs. + */ +#define ACL_EXECUTE 0x0001 +#define ACL_WRITE 0x0002 +#define ACL_READ 0x0004 +#define ACL_PERM_NONE 0x0000 +#define ACL_PERM_BITS (ACL_EXECUTE | ACL_WRITE | ACL_READ) +#define ACL_POSIX1E_BITS (ACL_EXECUTE | ACL_WRITE | ACL_READ) + +/* + * Possible bits in ae_perm field for NFSv4 ACLs. + */ +#define ACL_READ_DATA 0x00000008 +#define ACL_LIST_DIRECTORY 0x00000008 +#define ACL_WRITE_DATA 0x00000010 +#define ACL_ADD_FILE 0x00000010 +#define ACL_APPEND_DATA 0x00000020 +#define ACL_ADD_SUBDIRECTORY 0x00000020 +#define ACL_READ_NAMED_ATTRS 0x00000040 +#define ACL_WRITE_NAMED_ATTRS 0x00000080 +/* ACL_EXECUTE is defined above. */ +#define ACL_DELETE_CHILD 0x00000100 +#define ACL_READ_ATTRIBUTES 0x00000200 +#define ACL_WRITE_ATTRIBUTES 0x00000400 +#define ACL_DELETE 0x00000800 +#define ACL_READ_ACL 0x00001000 +#define ACL_WRITE_ACL 0x00002000 +#define ACL_WRITE_OWNER 0x00004000 +#define ACL_SYNCHRONIZE 0x00008000 + +#define ACL_FULL_SET (ACL_READ_DATA | ACL_WRITE_DATA | \ + ACL_APPEND_DATA | ACL_READ_NAMED_ATTRS | ACL_WRITE_NAMED_ATTRS | \ + ACL_EXECUTE | ACL_DELETE_CHILD | ACL_READ_ATTRIBUTES | \ + ACL_WRITE_ATTRIBUTES | ACL_DELETE | ACL_READ_ACL | ACL_WRITE_ACL | \ + ACL_WRITE_OWNER | ACL_SYNCHRONIZE) + +#define ACL_MODIFY_SET (ACL_FULL_SET & \ + ~(ACL_WRITE_ACL | ACL_WRITE_OWNER)) + +#define ACL_READ_SET (ACL_READ_DATA | ACL_READ_NAMED_ATTRS | \ + ACL_READ_ATTRIBUTES | ACL_READ_ACL) + +#define ACL_WRITE_SET (ACL_WRITE_DATA | ACL_APPEND_DATA | \ + ACL_WRITE_NAMED_ATTRS | ACL_WRITE_ATTRIBUTES) + +#define ACL_NFS4_PERM_BITS ACL_FULL_SET + +/* + * Possible entry_id values for acl_get_entry(3). + */ +#define ACL_FIRST_ENTRY 0 +#define ACL_NEXT_ENTRY 1 + +/* + * Possible values in ae_flags field; valid only for NFSv4 ACLs. + */ +#define ACL_ENTRY_FILE_INHERIT 0x0001 +#define ACL_ENTRY_DIRECTORY_INHERIT 0x0002 +#define ACL_ENTRY_NO_PROPAGATE_INHERIT 0x0004 +#define ACL_ENTRY_INHERIT_ONLY 0x0008 +#define ACL_ENTRY_SUCCESSFUL_ACCESS 0x0010 +#define ACL_ENTRY_FAILED_ACCESS 0x0020 +#define ACL_ENTRY_INHERITED 0x0080 + +#define ACL_FLAGS_BITS (ACL_ENTRY_FILE_INHERIT | \ + ACL_ENTRY_DIRECTORY_INHERIT | ACL_ENTRY_NO_PROPAGATE_INHERIT | \ + ACL_ENTRY_INHERIT_ONLY | ACL_ENTRY_SUCCESSFUL_ACCESS | \ + ACL_ENTRY_FAILED_ACCESS | ACL_ENTRY_INHERITED) + +/* + * Undefined value in ae_id field. ae_id should be set to this value + * iff ae_tag is ACL_USER_OBJ, ACL_GROUP_OBJ, ACL_OTHER or ACL_EVERYONE. + */ +#define ACL_UNDEFINED_ID ((uid_t)-1) + +/* + * Possible values for _flags parameter in acl_to_text_np(3). + */ +#define ACL_TEXT_VERBOSE 0x01 +#define ACL_TEXT_NUMERIC_IDS 0x02 +#define ACL_TEXT_APPEND_ID 0x04 + +/* + * POSIX.1e ACLs are capable of expressing the read, write, and execute bits + * of the POSIX mode field. We provide two masks: one that defines the bits + * the ACL will replace in the mode, and the other that defines the bits that + * must be preseved when an ACL is updating a mode. + */ +#define ACL_OVERRIDE_MASK (S_IRWXU | S_IRWXG | S_IRWXO) +#define ACL_PRESERVE_MASK (~ACL_OVERRIDE_MASK) + +#ifdef _KERNEL + +/* + * Filesystem-independent code to move back and forth between POSIX mode and + * POSIX.1e ACL representations. + */ +acl_perm_t acl_posix1e_mode_to_perm(acl_tag_t tag, mode_t mode); +struct acl_entry acl_posix1e_mode_to_entry(acl_tag_t tag, uid_t uid, + gid_t gid, mode_t mode); +mode_t acl_posix1e_perms_to_mode( + struct acl_entry *acl_user_obj_entry, + struct acl_entry *acl_group_obj_entry, + struct acl_entry *acl_other_entry); +mode_t acl_posix1e_acl_to_mode(struct acl *acl); +mode_t acl_posix1e_newfilemode(mode_t cmode, + struct acl *dacl); +struct acl *acl_alloc(int flags); +void acl_free(struct acl *aclp); + +void acl_nfs4_sync_acl_from_mode(struct acl *aclp, + mode_t mode, int file_owner_id); +void __acl_nfs4_sync_mode_from_acl(mode_t *mode, + const struct acl *aclp); +int acl_nfs4_is_trivial(const struct acl *aclp, + int file_owner_id); +void acl_nfs4_compute_inherited_acl( + const struct acl *parent_aclp, + struct acl *child_aclp, mode_t mode, + int file_owner_id, int is_directory); +int acl_copy_oldacl_into_acl(const struct oldacl *source, + struct acl *dest); +int acl_copy_acl_into_oldacl(const struct acl *source, + struct oldacl *dest); + +/* + * Filesystem-independent syntax check for a POSIX.1e ACL. + */ +int acl_posix1e_check(struct acl *acl); +int acl_nfs4_check(const struct acl *aclp, int is_directory); + +/* for compat32 */ +#include + +int kern___acl_aclcheck_path(struct lwp *, const char *, acl_type_t, + struct acl *, namei_simple_flags_t); +int kern___acl_delete_path(struct lwp *, const char *, acl_type_t, + namei_simple_flags_t); +int kern___acl_get_path(struct lwp *, const char *, acl_type_t, + struct acl *, namei_simple_flags_t); +int kern___acl_set_path(struct lwp *, const char *, acl_type_t, + const struct acl *, namei_simple_flags_t); +int vacl_set_acl(struct lwp *, struct vnode *, acl_type_t, + const struct acl *); +int vacl_get_acl(struct lwp *, struct vnode *, acl_type_t, struct acl *); +int vacl_aclcheck(struct lwp *, struct vnode *, acl_type_t, + const struct acl *); +int vacl_delete(struct lwp *, struct vnode *, acl_type_t); + +#else /* !_KERNEL */ + +#if defined(_ACL_PRIVATE) + +/* + * Syscall interface -- use the library calls instead as the syscalls have + * strict ACL entry ordering requirements. + */ +__BEGIN_DECLS +int __acl_aclcheck_fd(int _filedes, acl_type_t _type, struct acl *_aclp); +int __acl_aclcheck_file(const char *_path, acl_type_t _type, + struct acl *_aclp); +int __acl_aclcheck_link(const char *_path, acl_type_t _type, + struct acl *_aclp); +int __acl_delete_fd(int _filedes, acl_type_t _type); +int __acl_delete_file(const char *_path_p, acl_type_t _type); +int __acl_delete_link(const char *_path_p, acl_type_t _type); +int __acl_get_fd(int _filedes, acl_type_t _type, struct acl *_aclp); +int __acl_get_file(const char *_path, acl_type_t _type, struct acl *_aclp); +int __acl_get_link(const char *_path, acl_type_t _type, struct acl *_aclp); +int __acl_set_fd(int _filedes, acl_type_t _type, struct acl *_aclp); +int __acl_set_file(const char *_path, acl_type_t _type, struct acl *_aclp); +int __acl_set_link(const char *_path, acl_type_t _type, struct acl *_aclp); + +/* + * These routines from sys/kern/subr_acl_nfs4.c are used by both kernel + * and libc. + */ +void __acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *_aclp); +void __acl_nfs4_trivial_from_mode_libc(struct acl *_aclp, int _file_owner_id, + int _canonical_six); +__END_DECLS + +#endif /* _ACL_PRIVATE */ + +/* + * Supported POSIX.1e ACL manipulation and assignment/retrieval API _np calls + * are local extensions that reflect an environment capable of opening file + * descriptors of directories, and allowing additional ACL type for different + * filesystems (i.e., AFS). + */ +__BEGIN_DECLS +int acl_add_flag_np(acl_flagset_t _flagset_d, acl_flag_t _flag); +int acl_add_perm(acl_permset_t _permset_d, acl_perm_t _perm); +int acl_calc_mask(acl_t *_acl_p); +int acl_clear_flags_np(acl_flagset_t _flagset_d); +int acl_clear_perms(acl_permset_t _permset_d); +int acl_copy_entry(acl_entry_t _dest_d, acl_entry_t _src_d); +ssize_t acl_copy_ext(void *_buf_p, acl_t _acl, ssize_t _size); +acl_t acl_copy_int(const void *_buf_p); +int acl_create_entry(acl_t *_acl_p, acl_entry_t *_entry_p); +int acl_create_entry_np(acl_t *_acl_p, acl_entry_t *_entry_p, int _index); +int acl_delete_entry(acl_t _acl, acl_entry_t _entry_d); +int acl_delete_entry_np(acl_t _acl, int _index); +int acl_delete_fd_np(int _filedes, acl_type_t _type); +int acl_delete_file_np(const char *_path_p, acl_type_t _type); +int acl_delete_link_np(const char *_path_p, acl_type_t _type); +int acl_delete_def_file(const char *_path_p); +int acl_delete_def_link_np(const char *_path_p); +int acl_delete_flag_np(acl_flagset_t _flagset_d, acl_flag_t _flag); +int acl_delete_perm(acl_permset_t _permset_d, acl_perm_t _perm); +acl_t acl_dup(acl_t _acl); +int acl_free(void *_obj_p); +acl_t acl_from_text(const char *_buf_p); +int acl_get_brand_np(acl_t _acl, int *_brand_p); +int acl_get_entry(acl_t _acl, int _entry_id, acl_entry_t *_entry_p); +acl_t acl_get_fd(int _fd); +acl_t acl_get_fd_np(int fd, acl_type_t _type); +acl_t acl_get_file(const char *_path_p, acl_type_t _type); +int acl_get_entry_type_np(acl_entry_t _entry_d, acl_entry_type_t *_entry_type_p); +acl_t acl_get_link_np(const char *_path_p, acl_type_t _type); +void *acl_get_qualifier(acl_entry_t _entry_d); +int acl_get_flag_np(acl_flagset_t _flagset_d, acl_flag_t _flag); +int acl_get_perm_np(acl_permset_t _permset_d, acl_perm_t _perm); +int acl_get_flagset_np(acl_entry_t _entry_d, acl_flagset_t *_flagset_p); +int acl_get_permset(acl_entry_t _entry_d, acl_permset_t *_permset_p); +int acl_get_tag_type(acl_entry_t _entry_d, acl_tag_t *_tag_type_p); +acl_t acl_init(int _count); +int acl_set_fd(int _fd, acl_t _acl); +int acl_set_fd_np(int _fd, acl_t _acl, acl_type_t _type); +int acl_set_file(const char *_path_p, acl_type_t _type, acl_t _acl); +int acl_set_entry_type_np(acl_entry_t _entry_d, acl_entry_type_t _entry_type); +int acl_set_link_np(const char *_path_p, acl_type_t _type, acl_t _acl); +int acl_set_flagset_np(acl_entry_t _entry_d, acl_flagset_t _flagset_d); +int acl_set_permset(acl_entry_t _entry_d, acl_permset_t _permset_d); +int acl_set_qualifier(acl_entry_t _entry_d, const void *_tag_qualifier_p); +int acl_set_tag_type(acl_entry_t _entry_d, acl_tag_t _tag_type); +ssize_t acl_size(acl_t _acl); +char *acl_to_text(acl_t _acl, ssize_t *_len_p); +char *acl_to_text_np(acl_t _acl, ssize_t *_len_p, int _flags); +int acl_valid(acl_t _acl); +int acl_valid_fd_np(int _fd, acl_type_t _type, acl_t _acl); +int acl_valid_file_np(const char *_path_p, acl_type_t _type, acl_t _acl); +int acl_valid_link_np(const char *_path_p, acl_type_t _type, acl_t _acl); +int acl_is_trivial_np(const acl_t _acl, int *_trivialp); +acl_t acl_strip_np(const acl_t _acl, int recalculate_mask); +__END_DECLS + +#endif /* !_KERNEL */ + +#endif /* !_SYS_ACL_H_ */ Index: sys/sys/ansi.h =================================================================== RCS file: /cvsroot/src/sys/sys/ansi.h,v retrieving revision 1.14 diff -u -p -p -u -r1.14 ansi.h --- sys/sys/ansi.h 17 Jul 2011 20:54:54 -0000 1.14 +++ sys/sys/ansi.h 16 May 2020 16:14:09 -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 -p -u -r1.9 extattr.h --- sys/sys/extattr.h 13 Mar 2012 18:41:02 -0000 1.9 +++ sys/sys/extattr.h 16 May 2020 16:14:09 -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 -p -u -r1.38 fstypes.h --- sys/sys/fstypes.h 4 Apr 2020 20:49:31 -0000 1.38 +++ sys/sys/fstypes.h 16 May 2020 16:14:09 -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.84 diff -u -p -p -u -r1.84 kauth.h --- sys/sys/kauth.h 29 Apr 2020 05:54:37 -0000 1.84 +++ sys/sys/kauth.h 16 May 2020 16:14:09 -0000 @@ -525,11 +525,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.109 diff -u -p -p -u -r1.109 namei.h --- sys/sys/namei.h 12 May 2020 23:18:03 -0000 1.109 +++ sys/sys/namei.h 16 May 2020 16:14:09 -0000 @@ -45,7 +45,7 @@ #include #include -#ifdef _KERNEL +#if defined(_KERNEL) || defined(_MODULE) #include #include @@ -171,11 +171,12 @@ struct nameidata { #define ISDOTDOT 0x0002000 /* current component name is .. */ #define MAKEENTRY 0x0004000 /* entry is to be added to name cache */ #define ISLASTCN 0x0008000 /* this is last component of pathname */ +#define WILLBEDIR 0x0010000 /* new files will be dirs; */ #define ISWHITEOUT 0x0020000 /* found whiteout */ #define DOWHITEOUT 0x0040000 /* do whiteouts */ #define REQUIREDIR 0x0080000 /* must be a directory */ #define CREATEDIR 0x0200000 /* trailing slashes are ok */ -#define PARAMASK 0x02ef800 /* mask of parameter descriptors */ +#define PARAMASK 0x02ff800 /* mask of parameter descriptors */ /* * Initialization of a nameidata structure. @@ -298,7 +299,7 @@ bool cache_lookup_raw(struct vnode *, co bool cache_lookup_linked(struct vnode *, const char *, size_t, struct vnode **, krwlock_t **, kauth_cred_t); int cache_revlookup(struct vnode *, struct vnode **, char **, char *, - bool, int); + bool, accmode_t); int cache_diraccess(struct vnode *, int); void cache_enter(struct vnode *, struct vnode *, const char *, size_t, uint32_t); Index: sys/sys/namei.src =================================================================== RCS file: /cvsroot/src/sys/sys/namei.src,v retrieving revision 1.54 diff -u -p -p -u -r1.54 namei.src --- sys/sys/namei.src 12 May 2020 23:17:41 -0000 1.54 +++ sys/sys/namei.src 16 May 2020 16:14:09 -0000 @@ -37,7 +37,7 @@ #include #include -#ifdef _KERNEL +#if defined(_KERNEL) || defined(_MODULE) #include #include Index: sys/sys/statvfs.h =================================================================== RCS file: /cvsroot/src/sys/sys/statvfs.h,v retrieving revision 1.19 diff -u -p -p -u -r1.19 statvfs.h --- sys/sys/statvfs.h 22 Sep 2019 22:59:40 -0000 1.19 +++ sys/sys/statvfs.h 16 May 2020 16:14:09 -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.313 diff -u -p -p -u -r1.313 syscall.h --- sys/sys/syscall.h 26 Apr 2020 19:16:35 -0000 1.313 +++ sys/sys/syscall.h 16 May 2020 16:14:09 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: syscall.h,v 1.313 2020/04/26 19:16:35 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call numbers. @@ -1350,6 +1350,45 @@ /* syscall: "__fhstatvfs190" ret: "int" args: "const void *" "size_t" "struct statvfs *" "int" */ #define SYS___fhstatvfs190 486 -#define SYS_MAXSYSCALL 487 +/* syscall: "__acl_get_link" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */ +#define SYS___acl_get_link 487 + +/* syscall: "__acl_set_link" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */ +#define SYS___acl_set_link 488 + +/* syscall: "__acl_delete_link" ret: "int" args: "const char *" "acl_type_t" */ +#define SYS___acl_delete_link 489 + +/* syscall: "__acl_aclcheck_link" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */ +#define SYS___acl_aclcheck_link 490 + +/* syscall: "__acl_get_file" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */ +#define SYS___acl_get_file 491 + +/* syscall: "__acl_set_file" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */ +#define SYS___acl_set_file 492 + +/* syscall: "__acl_get_fd" ret: "int" args: "int" "acl_type_t" "struct acl *" */ +#define SYS___acl_get_fd 493 + +/* syscall: "__acl_set_fd" ret: "int" args: "int" "acl_type_t" "struct acl *" */ +#define SYS___acl_set_fd 494 + +/* syscall: "__acl_delete_file" ret: "int" args: "const char *" "acl_type_t" */ +#define SYS___acl_delete_file 495 + +/* syscall: "__acl_delete_fd" ret: "int" args: "int" "acl_type_t" */ +#define SYS___acl_delete_fd 496 + +/* syscall: "__acl_aclcheck_file" ret: "int" args: "const char *" "acl_type_t" "struct acl *" */ +#define SYS___acl_aclcheck_file 497 + +/* syscall: "__acl_aclcheck_fd" ret: "int" args: "int" "acl_type_t" "struct acl *" */ +#define SYS___acl_aclcheck_fd 498 + +/* syscall: "lpathconf" ret: "long" args: "const char *" "int" */ +#define SYS_lpathconf 499 + +#define SYS_MAXSYSCALL 500 #define SYS_NSYSENT 512 #endif /* _SYS_SYSCALL_H_ */ Index: sys/sys/syscallargs.h =================================================================== RCS file: /cvsroot/src/sys/sys/syscallargs.h,v retrieving revision 1.297 diff -u -p -p -u -r1.297 syscallargs.h --- sys/sys/syscallargs.h 26 Apr 2020 19:16:35 -0000 1.297 +++ sys/sys/syscallargs.h 16 May 2020 16:14:09 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: syscallargs.h,v 1.297 2020/04/26 19:16:35 thorpej Exp $ */ +/* $NetBSD$ */ /* * System call argument lists. @@ -14,6 +14,7 @@ #include #include #include +#include #endif #include @@ -3205,6 +3206,117 @@ struct sys___fhstatvfs190_args { }; check_syscall_args(sys___fhstatvfs190) +#ifndef RUMP_CLIENT +struct sys___acl_get_link_args { + syscallarg(const char *) path; + syscallarg(acl_type_t) type; + syscallarg(struct acl *) aclp; +}; +check_syscall_args(sys___acl_get_link) +#endif /* !RUMP_CLIENT */ + +#ifndef RUMP_CLIENT +struct sys___acl_set_link_args { + syscallarg(const char *) path; + syscallarg(acl_type_t) type; + syscallarg(struct acl *) aclp; +}; +check_syscall_args(sys___acl_set_link) +#endif /* !RUMP_CLIENT */ + +#ifndef RUMP_CLIENT +struct sys___acl_delete_link_args { + syscallarg(const char *) path; + syscallarg(acl_type_t) type; +}; +check_syscall_args(sys___acl_delete_link) +#endif /* !RUMP_CLIENT */ + +#ifndef RUMP_CLIENT +struct sys___acl_aclcheck_link_args { + syscallarg(const char *) path; + syscallarg(acl_type_t) type; + syscallarg(struct acl *) aclp; +}; +check_syscall_args(sys___acl_aclcheck_link) +#endif /* !RUMP_CLIENT */ + +#ifndef RUMP_CLIENT +struct sys___acl_get_file_args { + syscallarg(const char *) path; + syscallarg(acl_type_t) type; + syscallarg(struct acl *) aclp; +}; +check_syscall_args(sys___acl_get_file) +#endif /* !RUMP_CLIENT */ + +#ifndef RUMP_CLIENT +struct sys___acl_set_file_args { + syscallarg(const char *) path; + syscallarg(acl_type_t) type; + syscallarg(struct acl *) aclp; +}; +check_syscall_args(sys___acl_set_file) +#endif /* !RUMP_CLIENT */ + +#ifndef RUMP_CLIENT +struct sys___acl_get_fd_args { + syscallarg(int) filedes; + syscallarg(acl_type_t) type; + syscallarg(struct acl *) aclp; +}; +check_syscall_args(sys___acl_get_fd) +#endif /* !RUMP_CLIENT */ + +#ifndef RUMP_CLIENT +struct sys___acl_set_fd_args { + syscallarg(int) filedes; + syscallarg(acl_type_t) type; + syscallarg(struct acl *) aclp; +}; +check_syscall_args(sys___acl_set_fd) +#endif /* !RUMP_CLIENT */ + +#ifndef RUMP_CLIENT +struct sys___acl_delete_file_args { + syscallarg(const char *) path; + syscallarg(acl_type_t) type; +}; +check_syscall_args(sys___acl_delete_file) +#endif /* !RUMP_CLIENT */ + +#ifndef RUMP_CLIENT +struct sys___acl_delete_fd_args { + syscallarg(int) filedes; + syscallarg(acl_type_t) type; +}; +check_syscall_args(sys___acl_delete_fd) +#endif /* !RUMP_CLIENT */ + +#ifndef RUMP_CLIENT +struct sys___acl_aclcheck_file_args { + syscallarg(const char *) path; + syscallarg(acl_type_t) type; + syscallarg(struct acl *) aclp; +}; +check_syscall_args(sys___acl_aclcheck_file) +#endif /* !RUMP_CLIENT */ + +#ifndef RUMP_CLIENT +struct sys___acl_aclcheck_fd_args { + syscallarg(int) filedes; + syscallarg(acl_type_t) type; + syscallarg(struct acl *) aclp; +}; +check_syscall_args(sys___acl_aclcheck_fd) +#endif /* !RUMP_CLIENT */ + +struct sys_lpathconf_args { + syscallarg(const char *) path; + syscallarg(int) name; +}; +check_syscall_args(sys_lpathconf) + /* * System call prototypes. */ @@ -4093,5 +4205,31 @@ int sys___fstatvfs190(struct lwp *, 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 -p -u -r1.104 types.h --- sys/sys/types.h 28 Jan 2020 16:40:27 -0000 1.104 +++ sys/sys/types.h 16 May 2020 16:14:09 -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 -p -u -r1.62 unistd.h --- sys/sys/unistd.h 16 Oct 2019 20:43:18 -0000 1.62 +++ sys/sys/unistd.h 16 May 2020 16:14:09 -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 -p -u -r1.295 vnode.h --- sys/sys/vnode.h 13 Apr 2020 19:23:20 -0000 1.295 +++ sys/sys/vnode.h 16 May 2020 16:14:09 -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 -p -u -r1.104 vnode_if.h --- sys/sys/vnode_if.h 23 Feb 2020 22:15:18 -0000 1.104 +++ sys/sys/vnode_if.h 16 May 2020 16:14:09 -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 -p -u -r1.47 files.ufs --- sys/ufs/files.ufs 18 Apr 2020 19:18:33 -0000 1.47 +++ sys/ufs/files.ufs 16 May 2020 16:14:09 -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_subr.c =================================================================== RCS file: /cvsroot/src/sys/ufs/chfs/chfs_subr.c,v retrieving revision 1.12 diff -u -p -p -u -r1.12 chfs_subr.c --- sys/ufs/chfs/chfs_subr.c 23 Apr 2020 21:47:08 -0000 1.12 +++ sys/ufs/chfs/chfs_subr.c 16 May 2020 16:14:09 -0000 @@ -279,7 +279,7 @@ chfs_chflags(struct vnode *vp, int flags } error = kauth_authorize_vnode(cred, action, vp, NULL, - genfs_can_chflags(cred, CHTTOVT(ip->ch_type), ip->uid, changing_sysflags)); + genfs_can_chflags(vp, cred, ip->uid, changing_sysflags)); if (error) return error; Index: sys/ufs/chfs/chfs_vnode.c =================================================================== RCS file: /cvsroot/src/sys/ufs/chfs/chfs_vnode.c,v retrieving revision 1.18 diff -u -p -p -u -r1.18 chfs_vnode.c --- sys/ufs/chfs/chfs_vnode.c 17 Jan 2020 20:08:10 -0000 1.18 +++ sys/ufs/chfs/chfs_vnode.c 16 May 2020 16:14:09 -0000 @@ -251,9 +251,9 @@ chfs_makeinode(int mode, struct vnode *d /* authorize setting SGID if needed */ if (ip->mode & ISGID) { - error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY, - vp, NULL, genfs_can_chmod(vp->v_type, cnp->cn_cred, ip->uid, - ip->gid, mode)); + error = kauth_authorize_vnode(cnp->cn_cred, + KAUTH_VNODE_WRITE_SECURITY, vp, NULL, genfs_can_chmod(vp, + cnp->cn_cred, ip->uid, ip->gid, mode)); if (error) ip->mode &= ~ISGID; } 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 -p -u -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 16 May 2020 16:14:09 -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,12 @@ chfs_access(void *v) } } - if (mode & VWRITE && ip->flags & IMMUTABLE) + if (accmode & VWRITE && ip->flags & IMMUTABLE) return (EPERM); - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, vp->v_type, - ip->mode & ALLPERMS), vp, NULL, genfs_can_access(vp->v_type, - ip->mode & ALLPERMS, ip->uid, ip->gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, ip->mode & ALLPERMS), vp, NULL, genfs_can_access(vp, + cred, ip->uid, ip->gid, ip->mode & ALLPERMS, NULL, accmode)); } /* --------------------------------------------------------------------- */ @@ -510,7 +510,8 @@ chfs_setattr(void *v) /* set time */ if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, - NULL, genfs_can_chtimes(vp, vap->va_vaflags, ip->uid, cred)); + NULL, genfs_can_chtimes(vp, cred, ip->uid, + vap->va_vaflags)); if (error) return error; if (vap->va_atime.tv_sec != VNOVAL) @@ -539,7 +540,7 @@ chfs_chmod(struct vnode *vp, int mode, k dbg("chmod\n"); error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp, - NULL, genfs_can_chmod(vp->v_type, cred, ip->uid, ip->gid, mode)); + NULL, genfs_can_chmod(vp, cred, ip->uid, ip->gid, mode)); if (error) return error; ip->mode &= ~ALLPERMS; @@ -566,7 +567,7 @@ chfs_chown(struct vnode *vp, uid_t uid, gid = ip->gid; error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, - NULL, genfs_can_chown(cred, ip->uid, ip->gid, uid, gid)); + NULL, genfs_can_chown(vp, cred, ip->uid, ip->gid, uid, gid)); if (error) return error; @@ -1603,6 +1604,7 @@ const struct vnodeopv_entry_desc chfs_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_lookup.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_lookup.c,v retrieving revision 1.90 diff -u -p -p -u -r1.90 ext2fs_lookup.c --- sys/ufs/ext2fs/ext2fs_lookup.c 4 Apr 2020 20:49:31 -0000 1.90 +++ sys/ufs/ext2fs/ext2fs_lookup.c 16 May 2020 16:14:09 -0000 @@ -661,7 +661,7 @@ found: */ if (dp->i_e2fs_mode & ISVTX) { error = kauth_authorize_vnode(cred, KAUTH_VNODE_DELETE, - tdp, vdp, genfs_can_sticky(cred, dp->i_uid, + tdp, vdp, genfs_can_sticky(vdp, cred, dp->i_uid, VTOI(tdp)->i_uid)); if (error) { vrele(tdp); Index: sys/ufs/ext2fs/ext2fs_vfsops.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_vfsops.c,v retrieving revision 1.218 diff -u -p -p -u -r1.218 ext2fs_vfsops.c --- sys/ufs/ext2fs/ext2fs_vfsops.c 4 Apr 2020 20:49:31 -0000 1.218 +++ sys/ufs/ext2fs/ext2fs_vfsops.c 16 May 2020 16:14:09 -0000 @@ -1148,8 +1148,8 @@ ext2fs_newvnode(struct mount *mp, struct /* Authorize setting SGID if needed. */ if (ip->i_e2fs_mode & ISGID) { error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, - vp, NULL, genfs_can_chmod(vp->v_type, cred, ip->i_uid, - ip->i_gid, mode)); + vp, NULL, genfs_can_chmod(vp, cred, ip->i_uid, ip->i_gid, + mode)); if (error) ip->i_e2fs_mode &= ~ISGID; } 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 -p -u -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 16 May 2020 16:14:09 -0000 @@ -226,13 +226,14 @@ ext2fs_check_possible(struct vnode *vp, } static int -ext2fs_check_permitted(struct vnode *vp, struct inode *ip, mode_t mode, +ext2fs_check_permitted(struct vnode *vp, struct inode *ip, accmode_t accmode, kauth_cred_t cred) { - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, vp->v_type, - ip->i_e2fs_mode & ALLPERMS), vp, NULL, genfs_can_access(vp->v_type, - ip->i_e2fs_mode & ALLPERMS, ip->i_uid, ip->i_gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, ip->i_e2fs_mode & ALLPERMS), vp, NULL, + genfs_can_access(vp, cred, ip->i_uid, ip->i_gid, + ip->i_e2fs_mode & ALLPERMS, NULL, accmode)); } int @@ -240,12 +241,12 @@ ext2fs_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *ap = v; struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); - mode_t mode = ap->a_mode; + accmode_t mode = ap->a_accmode; int error; error = ext2fs_check_possible(vp, ip, mode); @@ -367,8 +368,7 @@ ext2fs_setattr(void *v) #endif /* EXT2FS_SYSTEM_FLAGS */ error = kauth_authorize_vnode(cred, action, vp, NULL, - genfs_can_chflags(cred, vp->v_type, ip->i_uid, - changing_sysflags)); + genfs_can_chflags(vp, cred, ip->i_uid, changing_sysflags)); if (error) return error; @@ -425,8 +425,8 @@ ext2fs_setattr(void *v) if (vp->v_mount->mnt_flag & MNT_RDONLY) return EROFS; error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, - NULL, genfs_can_chtimes(vp, vap->va_vaflags, ip->i_uid, - cred)); + NULL, genfs_can_chtimes(vp, cred, ip->i_uid, + vap->va_vaflags)); if (error) return error; if (vap->va_atime.tv_sec != VNOVAL) @@ -468,8 +468,7 @@ ext2fs_chmod(struct vnode *vp, int mode, int error; error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp, - NULL, genfs_can_chmod(vp->v_type, cred, ip->i_uid, ip->i_gid, - mode)); + NULL, genfs_can_chmod(vp, cred, ip->i_uid, ip->i_gid, mode)); if (error) return error; @@ -498,7 +497,7 @@ ext2fs_chown(struct vnode *vp, uid_t uid gid = ip->i_gid; error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, - NULL, genfs_can_chown(cred, ip->i_uid, ip->i_gid, uid, gid)); + NULL, genfs_can_chown(vp, cred, ip->i_uid, ip->i_gid, uid, gid)); if (error) return error; @@ -1101,6 +1100,7 @@ const struct vnodeopv_entry_desc ext2fs_ { &vop_open_desc, ext2fs_open }, /* open */ { &vop_close_desc, ufs_close }, /* close */ { &vop_access_desc, ext2fs_access }, /* access */ + { &vop_accessx_desc, genfs_accessx }, /* accessx */ { &vop_getattr_desc, ext2fs_getattr }, /* getattr */ { &vop_setattr_desc, ext2fs_setattr }, /* setattr */ { &vop_read_desc, ext2fs_read }, /* read */ @@ -1155,6 +1155,7 @@ const struct vnodeopv_entry_desc ext2fs_ { &vop_open_desc, spec_open }, /* open */ { &vop_close_desc, ufsspec_close }, /* close */ { &vop_access_desc, ext2fs_access }, /* access */ + { &vop_accessx_desc, genfs_accessx }, /* accessx */ { &vop_getattr_desc, ext2fs_getattr }, /* getattr */ { &vop_setattr_desc, ext2fs_setattr }, /* setattr */ { &vop_read_desc, ufsspec_read }, /* read */ @@ -1209,6 +1210,7 @@ const struct vnodeopv_entry_desc ext2fs_ { &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 -p -u -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 16 May 2020 16:14:09 -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.4 diff -u -p -p -u -r1.4 ffs_extattr.c --- sys/ufs/ffs/ffs_extattr.c 2 May 2020 22:11:16 -0000 1.4 +++ sys/ufs/ffs/ffs_extattr.c 16 May 2020 16:14:09 -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 @@ -683,7 +655,7 @@ ffs_getextattr(void *v) if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) return (EOPNOTSUPP); - error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace, + error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, ap->a_cred, VREAD); if (error) return (error); @@ -757,7 +729,7 @@ ffs_setextattr(void *v) if (ealen < 0 || ealen > lblktosize(fs, UFS_NXADDR)) return (EINVAL); - error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace, + error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, ap->a_cred, VWRITE); if (error) { @@ -862,7 +834,7 @@ ffs_listextattr(void *v) if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) return (EOPNOTSUPP); - error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace, + error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, ap->a_cred, VREAD); if (error) return (error); @@ -932,7 +904,7 @@ ffs_deleteextattr(void *v) if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); - error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace, + error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, ap->a_cred, VWRITE); if (error) { /* Index: sys/ufs/ffs/ffs_vfsops.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vfsops.c,v retrieving revision 1.368 diff -u -p -p -u -r1.368 ffs_vfsops.c --- sys/ufs/ffs/ffs_vfsops.c 12 May 2020 23:17:41 -0000 1.368 +++ sys/ufs/ffs/ffs_vfsops.c 16 May 2020 16:14:09 -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|IMNT_NCLOOKUP); + else + mp->mnt_iflag |= IMNT_SHRLOOKUP|IMNT_NCLOOKUP; +} + /* * 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 -p -u -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 16 May 2020 16:14:09 -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 -p -u -r1.67 fs.h --- sys/ufs/ffs/fs.h 18 Apr 2020 19:18:34 -0000 1.67 +++ sys/ufs/ffs/fs.h 16 May 2020 16:14:09 -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 -p -u -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 16 May 2020 16:14:09 -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 */ @@ -381,8 +384,9 @@ lfs_makeinode(struct vattr *vap, struct /* Authorize setting SGID if needed. */ if (ip->i_mode & ISGID) { - error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY, - tvp, NULL, genfs_can_chmod(tvp->v_type, cnp->cn_cred, ip->i_uid, + error = kauth_authorize_vnode(cnp->cn_cred, + KAUTH_VNODE_WRITE_SECURITY, + tvp, NULL, genfs_can_chmod(tvp, cnp->cn_cred, ip->i_uid, ip->i_gid, MAKEIMODE(vap->va_type, vap->va_mode))); if (error) { ip->i_mode &= ~ISGID; 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 -p -u -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 16 May 2020 16:14:09 -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_lookup.c =================================================================== RCS file: /cvsroot/src/sys/ufs/lfs/ulfs_lookup.c,v retrieving revision 1.43 diff -u -p -p -u -r1.43 ulfs_lookup.c --- sys/ufs/lfs/ulfs_lookup.c 4 Apr 2020 20:49:31 -0000 1.43 +++ sys/ufs/lfs/ulfs_lookup.c 16 May 2020 16:14:09 -0000 @@ -574,7 +574,7 @@ found: */ if (dp->i_mode & ISVTX) { error = kauth_authorize_vnode(cred, KAUTH_VNODE_DELETE, - tdp, vdp, genfs_can_sticky(cred, dp->i_uid, + tdp, vdp, genfs_can_sticky(vdp, cred, dp->i_uid, VTOI(tdp)->i_uid)); if (error) { vrele(tdp); 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 -p -u -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 16 May 2020 16:14:09 -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, cred, ip->i_uid, ip->i_gid, ip->i_mode & ALLPERMS, + NULL, accmode)); } int @@ -201,26 +202,26 @@ ulfs_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *ap = v; struct vnode *vp; struct inode *ip; - mode_t mode; + accmode_t accmode; int error; vp = ap->a_vp; - mode = ap->a_mode; + accmode = ap->a_accmode; KASSERT(VOP_ISLOCKED(vp)); ip = VTOI(vp); - error = ulfs_check_possible(vp, ip, mode, ap->a_cred); + error = ulfs_check_possible(vp, ip, accmode, ap->a_cred); if (error) return error; - error = ulfs_check_permitted(vp, ip, mode, ap->a_cred); + error = ulfs_check_permitted(vp, ip, accmode, ap->a_cred); return error; } @@ -292,7 +293,7 @@ ulfs_setattr(void *v) } error = kauth_authorize_vnode(cred, action, vp, NULL, - genfs_can_chflags(cred, vp->v_type, ip->i_uid, + genfs_can_chflags(vp, cred, ip->i_uid, changing_sysflags)); if (error) goto out; @@ -371,7 +372,8 @@ ulfs_setattr(void *v) goto out; } error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, - NULL, genfs_can_chtimes(vp, vap->va_vaflags, ip->i_uid, cred)); + NULL, genfs_can_chtimes(vp, cred, ip->i_uid, + vap->va_vaflags)); if (error) goto out; if (vap->va_atime.tv_sec != VNOVAL) @@ -424,7 +426,7 @@ ulfs_chmod(struct vnode *vp, int mode, k ip = VTOI(vp); error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp, - NULL, genfs_can_chmod(vp->v_type, cred, ip->i_uid, ip->i_gid, mode)); + NULL, genfs_can_chmod(vp, cred, ip->i_uid, ip->i_gid, mode)); if (error) return (error); @@ -462,7 +464,7 @@ ulfs_chown(struct vnode *vp, uid_t uid, gid = ip->i_gid; error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, - NULL, genfs_can_chown(cred, ip->i_uid, ip->i_gid, uid, gid)); + NULL, genfs_can_chown(vp, cred, ip->i_uid, ip->i_gid, uid, gid)); if (error) return (error); 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 -p -u -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 16 May 2020 16:14:09 -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 16 May 2020 16:14:09 -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 16 May 2020 16:14:09 -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 16 May 2020 16:14:09 -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 -p -u -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 16 May 2020 16:14:09 -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 -p -u -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 16 May 2020 16:14:09 -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 -p -u -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 16 May 2020 16:14:10 -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. */ @@ -228,7 +260,7 @@ ufs_can_delete(struct vnode *tdp, struct * implements append-only directories. */ error = kauth_authorize_vnode(cred, KAUTH_VNODE_DELETE, tdp, vdp, - genfs_can_sticky(cred, ip->i_uid, VTOI(tdp)->i_uid)); + genfs_can_sticky(vdp, cred, ip->i_uid, VTOI(tdp)->i_uid)); if (error) { error = EPERM; // Why override? goto out; @@ -590,7 +622,10 @@ notfound: * Access for write is interpreted as allowing * creation of files in the directory. */ - error = VOP_ACCESS(vdp, VWRITE, cred); + if (flags & WILLBEDIR) + error = VOP_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.253 diff -u -p -p -u -r1.253 ufs_vnops.c --- sys/ufs/ufs/ufs_vnops.c 12 May 2020 23:17:41 -0000 1.253 +++ sys/ufs/ufs/ufs_vnops.c 16 May 2020 16:14:10 -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)(struct vnode *, kauth_cred_t, uid_t, gid_t, mode_t, + struct acl *, accmode_t)) { - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, vp->v_type, - ip->i_mode & ALLPERMS), vp, NULL, genfs_can_access(vp->v_type, - ip->i_mode & ALLPERMS, ip->i_uid, ip->i_gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, ip->i_mode & ALLPERMS), vp, NULL, (*func)(vp, cred, + ip->i_uid, ip->i_gid, ip->i_mode & ALLPERMS, acl, accmode)); } int -ufs_access(void *v) +ufs_accessx(void *v) { - struct vop_access_args /* { - struct vnode *a_vp; - int a_mode; - kauth_cred_t a_cred; + struct vop_accessx_args /* { + struct vnode *a_vp; + accmode_t a_accmode; + kauth_cred_t a_cred; } */ *ap = v; - struct vnode *vp; - struct inode *ip; - mode_t mode; - int error; - - vp = ap->a_vp; - ip = VTOI(vp); - mode = ap->a_mode; + struct vnode *vp = ap->a_vp; + struct inode *ip = VTOI(vp); + accmode_t accmode = ap->a_accmode; + int error; +#ifdef UFS_ACL + struct acl *acl; + acl_type_t type; +#endif - error = ufs_check_possible(vp, ip, mode, ap->a_cred); + error = ufs_check_possible(vp, ip, accmode, ap->a_cred); if (error) return error; - error = ufs_check_permitted(vp, ip, mode, ap->a_cred); +#ifdef UFS_ACL + if ((vp->v_mount->mnt_flag & (MNT_POSIX1EACLS | MNT_ACLS)) != 0) { + if (vp->v_mount->mnt_flag & MNT_ACLS) + type = ACL_TYPE_NFS4; + else + type = ACL_TYPE_ACCESS; - return error; + acl = acl_alloc(KM_SLEEP); + if (type == ACL_TYPE_NFS4) + error = ufs_getacl_nfs4_internal(vp, acl, curlwp); + else + error = VOP_GETACL(vp, type, acl, ap->a_cred); + if (!error) { + if (type == ACL_TYPE_NFS4) { + error = ufs_check_permitted(vp, + ip, acl, accmode, ap->a_cred, + genfs_can_access_acl_nfs4); + } else { + error = vfs_unixify_accmode(&accmode); + if (error == 0) + error = ufs_check_permitted(vp, + ip, acl, accmode, ap->a_cred, + genfs_can_access_acl_posix1e); + } + acl_free(acl); + return error; + } + if (error != EOPNOTSUPP) + printf("%s: Error retrieving ACL: %d\n", + __func__, error); + /* + * XXX: Fall back until debugged. Should + * eventually possibly log an error, and return + * EPERM for safety. + */ + acl_free(acl); + } +#endif /* !UFS_ACL */ + error = vfs_unixify_accmode(&accmode); + if (error) + return error; + return ufs_check_permitted(vp, ip, + NULL, accmode, ap->a_cred, genfs_can_access); } /* ARGSUSED */ @@ -486,8 +533,7 @@ ufs_setattr(void *v) } error = kauth_authorize_vnode(cred, action, vp, NULL, - genfs_can_chflags(cred, vp->v_type, ip->i_uid, - changing_sysflags)); + genfs_can_chflags(vp, cred, ip->i_uid, changing_sysflags)); if (error) goto out; @@ -577,7 +623,8 @@ ufs_setattr(void *v) goto out; } error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, - NULL, genfs_can_chtimes(vp, vap->va_vaflags, ip->i_uid, cred)); + NULL, genfs_can_chtimes(vp, cred, ip->i_uid, + vap->va_vaflags)); if (error) goto out; error = UFS_WAPBL_BEGIN(vp->v_mount); @@ -625,6 +672,32 @@ out: return (error); } +#ifdef UFS_ACL +static int +ufs_update_nfs4_acl_after_mode_change(struct vnode *vp, int mode, + int file_owner_id, kauth_cred_t cred, struct lwp *l) +{ + int error; + struct acl *aclp; + + aclp = acl_alloc(KM_SLEEP); + error = ufs_getacl_nfs4_internal(vp, aclp, l); + /* + * We don't have to handle EOPNOTSUPP here, as the filesystem claims + * it supports ACLs. + */ + if (error) + goto out; + + acl_nfs4_sync_acl_from_mode(aclp, mode, file_owner_id); + error = ufs_setacl_nfs4_internal(vp, aclp, l, false); + +out: + acl_free(aclp); + return (error); +} +#endif /* UFS_ACL */ + /* * Change the mode on a file. * Inode must be locked before calling. @@ -639,11 +712,28 @@ ufs_chmod(struct vnode *vp, int mode, 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)); + NULL, genfs_can_chmod(vp, cred, ip->i_uid, ip->i_gid, mode)); if (error) return (error); +#ifdef UFS_ACL + if ((vp->v_mount->mnt_flag & MNT_ACLS) != 0) { + error = ufs_update_nfs4_acl_after_mode_change(vp, mode, + ip->i_uid, cred, l); + if (error) + return error; + } +#endif ip->i_mode &= ~ALLPERMS; ip->i_mode |= (mode & ALLPERMS); ip->i_flag |= IN_CHANGE; @@ -676,8 +766,17 @@ ufs_chown(struct vnode *vp, uid_t uid, 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)); + NULL, genfs_can_chown(vp, cred, ip->i_uid, ip->i_gid, uid, gid)); if (error) return (error); @@ -734,6 +833,17 @@ ufs_remove(void *v) mp = dvp->v_mount; KASSERT(mp == vp->v_mount); /* XXX Not stable without lock. */ +#ifdef UFS_ACL +#ifdef notyet + /* We don't do this because if the filesystem is mounted without ACLs + * this goes through vfs_unixify_accmode() and we get EPERM. + */ + error = VOP_ACCESSX(vp, VDELETE, ap->a_cnp->cn_cred); + if (error) + goto err; +#endif +#endif + /* XXX should handle this material another way */ ulr = &VTOI(dvp)->i_crap; UFS_CHECK_CRAPCOUNTER(VTOI(dvp)); @@ -751,6 +861,9 @@ ufs_remove(void *v) } VN_KNOTE(vp, NOTE_DELETE); VN_KNOTE(dvp, NOTE_WRITE); +#ifdef notyet +err: +#endif if (dvp == vp) vrele(vp); else @@ -906,6 +1019,193 @@ ufs_whiteout(void *v) return (error); } +#ifdef UFS_ACL +static int +ufs_do_posix1e_acl_inheritance_dir(struct vnode *dvp, struct vnode *tvp, + mode_t dmode, kauth_cred_t cred, struct lwp *l) +{ + int error; + struct inode *ip = VTOI(tvp); + struct acl *dacl, *acl; + + acl = acl_alloc(KM_SLEEP); + dacl = acl_alloc(KM_SLEEP); + + /* + * Retrieve default ACL from parent, if any. + */ + error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred); + switch (error) { + case 0: + /* + * Retrieved a default ACL, so merge mode and ACL if + * necessary. If the ACL is empty, fall through to + * the "not defined or available" case. + */ + if (acl->acl_cnt != 0) { + dmode = acl_posix1e_newfilemode(dmode, acl); + ip->i_mode = dmode; + DIP_ASSIGN(ip, mode, dmode); + *dacl = *acl; + ufs_sync_acl_from_inode(ip, acl); + break; + } + /* FALLTHROUGH */ + + case EOPNOTSUPP: + /* + * Just use the mode as-is. + */ + ip->i_mode = dmode; + DIP_ASSIGN(ip, mode, dmode); + error = 0; + goto out; + + default: + goto out; + } + + /* + * XXX: If we abort now, will Soft Updates notify the extattr + * code that the EAs for the file need to be released? + */ + UFS_WAPBL_END(tvp->v_mount); + error = ufs_setacl_posix1e(tvp, ACL_TYPE_ACCESS, acl, cred, l); + if (error == 0) + error = ufs_setacl_posix1e(tvp, ACL_TYPE_DEFAULT, dacl, cred, + l); + UFS_WAPBL_BEGIN(tvp->v_mount); + switch (error) { + case 0: + break; + + case EOPNOTSUPP: + /* + * XXX: This should not happen, as EOPNOTSUPP above + * was supposed to free acl. + */ + printf("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()\n"); + /* + panic("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()"); + */ + break; + + default: + goto out; + } + +out: + acl_free(acl); + acl_free(dacl); + + return (error); +} + +static int +ufs_do_posix1e_acl_inheritance_file(struct vnode *dvp, struct vnode *tvp, + mode_t mode, kauth_cred_t cred, struct lwp *l) +{ + int error; + struct inode *ip = VTOI(tvp); + struct acl *acl; + + acl = acl_alloc(KM_SLEEP); + + /* + * Retrieve default ACL for parent, if any. + */ + error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred); + switch (error) { + case 0: + /* + * Retrieved a default ACL, so merge mode and ACL if + * necessary. + */ + if (acl->acl_cnt != 0) { + /* + * Two possible ways for default ACL to not + * be present. First, the EA can be + * undefined, or second, the default ACL can + * be blank. If it's blank, fall through to + * the it's not defined case. + */ + mode = acl_posix1e_newfilemode(mode, acl); + ip->i_mode = mode; + DIP_ASSIGN(ip, mode, mode); + ufs_sync_acl_from_inode(ip, acl); + break; + } + /* FALLTHROUGH */ + + case EOPNOTSUPP: + /* + * Just use the mode as-is. + */ + ip->i_mode = mode; + DIP_ASSIGN(ip, mode, mode); + error = 0; + goto out; + + default: + goto out; + } + + UFS_WAPBL_END(tvp->v_mount); + /* + * XXX: If we abort now, will Soft Updates notify the extattr + * code that the EAs for the file need to be released? + */ + error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cred); + UFS_WAPBL_BEGIN(tvp->v_mount); + switch (error) { + case 0: + break; + + case EOPNOTSUPP: + /* + * XXX: This should not happen, as EOPNOTSUPP above was + * supposed to free acl. + */ + printf("%s: VOP_GETACL() but no VOP_SETACL()\n", __func__); + /* panic("%s: VOP_GETACL() but no VOP_SETACL()", __func__); */ + break; + + default: + goto out; + } + +out: + acl_free(acl); + + return (error); +} + +static int +ufs_do_nfs4_acl_inheritance(struct vnode *dvp, struct vnode *tvp, + mode_t child_mode, kauth_cred_t cred, struct lwp *l) +{ + int error; + struct acl *parent_aclp, *child_aclp; + + parent_aclp = acl_alloc(KM_SLEEP); + child_aclp = acl_alloc(KM_SLEEP); + + error = ufs_getacl_nfs4_internal(dvp, parent_aclp, l); + if (error) + goto out; + acl_nfs4_compute_inherited_acl(parent_aclp, child_aclp, + child_mode, VTOI(tvp)->i_uid, tvp->v_type == VDIR); + error = ufs_setacl_nfs4_internal(tvp, child_aclp, l, false); + if (error) + goto out; +out: + acl_free(parent_aclp); + acl_free(child_aclp); + + return (error); +} +#endif + int ufs_mkdir(void *v) { @@ -979,6 +1279,23 @@ ufs_mkdir(void *v) if ((error = UFS_UPDATE(dvp, NULL, NULL, UPDATE_DIROP)) != 0) goto bad; +#ifdef UFS_ACL + mode_t dmode = (vap->va_mode & 0777) | IFDIR; + struct lwp *l = curlwp; + if (dvp->v_mount->mnt_flag & MNT_POSIX1EACLS) { + + error = ufs_do_posix1e_acl_inheritance_dir(dvp, tvp, dmode, + cnp->cn_cred, l); + if (error) + goto bad; + } else if (dvp->v_mount->mnt_flag & MNT_ACLS) { + error = ufs_do_nfs4_acl_inheritance(dvp, tvp, dmode, + cnp->cn_cred, l); + if (error) + goto bad; + } +#endif /* !UFS_ACL */ + /* * Initialize directory with "." and ".." from static template. */ @@ -1071,6 +1388,17 @@ ufs_rmdir(void *v) ip = VTOI(vp); dp = VTOI(dvp); +#ifdef UFS_ACL +#ifdef notyet + /* We don't do this because if the filesystem is mounted without ACLs + * this goes through vfs_unixify_accmode() and we get EPERM. + */ + error = VOP_ACCESSX(vp, VDELETE, cnp->cn_cred); + if (error) + goto err; +#endif +#endif + /* XXX should handle this material another way */ ulr = &dp->i_crap; UFS_CHECK_CRAPCOUNTER(dp); @@ -1079,11 +1407,8 @@ ufs_rmdir(void *v) * No rmdir "." or of mounted directories please. */ if (dp == ip || vp->v_mountedhere != NULL) { - if (dp == ip) - vrele(vp); - else - vput(vp); - return (EINVAL); + error = EINVAL; + goto err; } /* @@ -1144,7 +1469,13 @@ ufs_rmdir(void *v) out: VN_KNOTE(vp, NOTE_DELETE); vput(vp); - return (error); + return error; + err: + if (dp == ip) + vrele(vp); + else + vput(vp); + return error; } /* @@ -1766,6 +2097,30 @@ ufs_pathconf(void *v) case _PC_NO_TRUNC: *ap->a_retval = 1; return (0); +#ifdef UFS_ACL + case _PC_ACL_EXTENDED: + if (ap->a_vp->v_mount->mnt_flag & MNT_POSIX1EACLS) + *ap->a_retval = 1; + else + *ap->a_retval = 0; + return 0; + case _PC_ACL_NFS4: + if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS) + *ap->a_retval = 1; + else + *ap->a_retval = 0; + return 0; +#endif + case _PC_ACL_PATH_MAX: +#ifdef UFS_ACL + if (ap->a_vp->v_mount->mnt_flag & (MNT_POSIX1EACLS | MNT_ACLS)) + *ap->a_retval = ACL_MAX_ENTRIES; + else + *ap->a_retval = 3; +#else + *ap->a_retval = 3; +#endif + return 0; case _PC_SYNC_IO: *ap->a_retval = 1; return (0); @@ -1890,8 +2245,9 @@ ufs_makeinode(struct vattr *vap, struct /* Authorize setting SGID if needed. */ if (ip->i_mode & ISGID) { - error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY, - tvp, NULL, genfs_can_chmod(tvp->v_type, cnp->cn_cred, ip->i_uid, + error = kauth_authorize_vnode(cnp->cn_cred, + KAUTH_VNODE_WRITE_SECURITY, + tvp, NULL, genfs_can_chmod(tvp, cnp->cn_cred, ip->i_uid, ip->i_gid, MAKEIMODE(vap->va_type, vap->va_mode))); if (error) { ip->i_mode &= ~ISGID; @@ -1909,6 +2265,20 @@ ufs_makeinode(struct vattr *vap, struct */ 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);