1*aa693e99SJason King /* 2*aa693e99SJason King * Copyright 2016 Chris Torek <torek@ixsystems.com> 3*aa693e99SJason King * All rights reserved 4*aa693e99SJason King * 5*aa693e99SJason King * Redistribution and use in source and binary forms, with or without 6*aa693e99SJason King * modification, are permitted providing that the following conditions 7*aa693e99SJason King * are met: 8*aa693e99SJason King * 1. Redistributions of source code must retain the above copyright 9*aa693e99SJason King * notice, this list of conditions and the following disclaimer. 10*aa693e99SJason King * 2. Redistributions in binary form must reproduce the above copyright 11*aa693e99SJason King * notice, this list of conditions and the following disclaimer in the 12*aa693e99SJason King * documentation and/or other materials provided with the distribution. 13*aa693e99SJason King * 14*aa693e99SJason King * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15*aa693e99SJason King * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16*aa693e99SJason King * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*aa693e99SJason King * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 18*aa693e99SJason King * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*aa693e99SJason King * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*aa693e99SJason King * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*aa693e99SJason King * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22*aa693e99SJason King * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23*aa693e99SJason King * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24*aa693e99SJason King * POSSIBILITY OF SUCH DAMAGE. 25*aa693e99SJason King */ 26*aa693e99SJason King 27*aa693e99SJason King /* 28*aa693e99SJason King * General ACL support for 9P2000.L. 29*aa693e99SJason King * 30*aa693e99SJason King * We mostly use Linux's xattr name space and nfs4 ACL bits, as 31*aa693e99SJason King * these are the most general forms available. 32*aa693e99SJason King * 33*aa693e99SJason King * Linux requests attributes named 34*aa693e99SJason King * 35*aa693e99SJason King * "system.posix_acl_default" 36*aa693e99SJason King * "system.posix_acl_access" 37*aa693e99SJason King * 38*aa693e99SJason King * to get POSIX style ACLs, and: 39*aa693e99SJason King * 40*aa693e99SJason King * "system.nfs4_acl" 41*aa693e99SJason King * 42*aa693e99SJason King * to get NFSv4 style ACLs. The v9fs client does not explicitly 43*aa693e99SJason King * ask for the latter, but if you use the Ubuntu nfs4-acl-tools 44*aa693e99SJason King * package, it should be able to read and write these. 45*aa693e99SJason King * 46*aa693e99SJason King * For the record, the Linux kernel source code also shows: 47*aa693e99SJason King * 48*aa693e99SJason King * - Lustre uses "trusted.*", with "*" matching "lov", "lma", 49*aa693e99SJason King * "lmv", "dmv", "link", "fid", "version", "som", "hsm", and 50*aa693e99SJason King * "lfsck_namespace". 51*aa693e99SJason King * 52*aa693e99SJason King * - ceph has a name tree of the form "ceph.<type>.<name>" with 53*aa693e99SJason King * <type,name> pairs like <"dir","entries">, <"dir","files>, 54*aa693e99SJason King * <"file","layout">, and so on. 55*aa693e99SJason King * 56*aa693e99SJason King * - ext4 uses the POSIX names, plus some special ext4-specific 57*aa693e99SJason King * goop that might not get externalized. 58*aa693e99SJason King * 59*aa693e99SJason King * - NFS uses both the POSIX names and the NFSv4 ACLs. However, 60*aa693e99SJason King * what it mainly does is have nfsd generate fake NFSv4 ACLs 61*aa693e99SJason King * from POSIX ACLs. If you run an NFS client, the client 62*aa693e99SJason King * relies on the server actually implementing the ACLs, and 63*aa693e99SJason King * lets nfs4-acl-tools read and write the system.nfs4_acl xattr 64*aa693e99SJason King * data. If you run an NFS server off, e.g., an ext4 file system, 65*aa693e99SJason King * the server looks for the system.nfs4_acl xattr, serves that 66*aa693e99SJason King * out if found, and otherwise just generates the fakes. 67*aa693e99SJason King * 68*aa693e99SJason King * - "security.*" and "selinux.*" are reserved. 69*aa693e99SJason King * 70*aa693e99SJason King * - "security.capability" is the name for capabilities. 71*aa693e99SJason King * 72*aa693e99SJason King * - sockets use "system.sockprotoname". 73*aa693e99SJason King */ 74*aa693e99SJason King 75*aa693e99SJason King #if defined(__APPLE__) 76*aa693e99SJason King #define HAVE_POSIX_ACLS 77*aa693e99SJason King #define HAVE_DARWIN_ACLS 78*aa693e99SJason King #endif 79*aa693e99SJason King 80*aa693e99SJason King #if defined(__FreeBSD__) 81*aa693e99SJason King #define HAVE_POSIX_ACLS 82*aa693e99SJason King #define HAVE_FREEBSD_ACLS 83*aa693e99SJason King #endif 84*aa693e99SJason King 85*aa693e99SJason King #if defined (__illumos__) 86*aa693e99SJason King #define HAVE_POSIX_ACLS 87*aa693e99SJason King #define HAVE__ILLUMOS_ACLS 88*aa693e99SJason King #endif 89*aa693e99SJason King 90*aa693e99SJason King #include <sys/types.h> 91*aa693e99SJason King #include <sys/acl.h> /* XXX assumes existence of sys/acl.h */ 92*aa693e99SJason King 93*aa693e99SJason King /* 94*aa693e99SJason King * An ACL consists of a number of ACEs that grant some kind of 95*aa693e99SJason King * "allow" or "deny" to some specific entity. 96*aa693e99SJason King * 97*aa693e99SJason King * The number of ACEs is potentially unlimited, although in practice 98*aa693e99SJason King * they tend not to be that long. 99*aa693e99SJason King * 100*aa693e99SJason King * It's the responsibility of the back-end to supply the ACL 101*aa693e99SJason King * for each test. However, the ACL may be in some sort of 102*aa693e99SJason King * system-specific form. It's the responsibility of some 103*aa693e99SJason King * (system-specific) code to translate it to *this* form, after 104*aa693e99SJason King * which the backend may use l9p_acl_check_access() to get 105*aa693e99SJason King * access granted or denied (and, eventually, audits and alarms 106*aa693e99SJason King * recorded and raises, although that's yet to be designed). 107*aa693e99SJason King * 108*aa693e99SJason King * The reason for all this faffing-about with formats is so that 109*aa693e99SJason King * we can *report* the ACLs using Linux 9p style xattrs. 110*aa693e99SJason King */ 111*aa693e99SJason King 112*aa693e99SJason King struct l9p_acl; 113*aa693e99SJason King struct l9p_fid; 114*aa693e99SJason King 115*aa693e99SJason King void l9p_acl_free(struct l9p_acl *); 116*aa693e99SJason King 117*aa693e99SJason King /* 118*aa693e99SJason King * An ACL is made up of ACEs. 119*aa693e99SJason King * 120*aa693e99SJason King * Each ACE has: 121*aa693e99SJason King * 122*aa693e99SJason King * - a type: allow, deny, audit, alarm 123*aa693e99SJason King * - a set of flags 124*aa693e99SJason King * - permissions bits: a "mask" 125*aa693e99SJason King * - an optional, nominally-variable-length identity 126*aa693e99SJason King * 127*aa693e99SJason King * The last part is especially tricky and currently has limited 128*aa693e99SJason King * support here: it's always a 16 byte field on Darwin, and just 129*aa693e99SJason King * a uint32_t on BSD (should be larger, really). Linux supports 130*aa693e99SJason King * very large, actually-variable-size values; we'll deal with 131*aa693e99SJason King * this later, maybe. 132*aa693e99SJason King * 133*aa693e99SJason King * We will define the mask first, below, since these are also the bits 134*aa693e99SJason King * passed in for the accmask argument to l9p_acl_check_access(). 135*aa693e99SJason King */ 136*aa693e99SJason King 137*aa693e99SJason King /* 138*aa693e99SJason King * ACL entry mask, and accmask argument flags. 139*aa693e99SJason King * 140*aa693e99SJason King * NB: not every bit is implemented, but they are all here because 141*aa693e99SJason King * they are all defined as part of an NFSv4 ACL entry, which is 142*aa693e99SJason King * more or less a superset of a POSIX ACL entry. This means you 143*aa693e99SJason King * can put a complete NFSv4 ACL in and we can reproduce it. 144*aa693e99SJason King * 145*aa693e99SJason King * Note that the LIST_DIRECTORY, ADD_FILE, and ADD_SUBDIRECTORY bits 146*aa693e99SJason King * apply only to a directory, while the READ_DATA, WRITE_DATA, and 147*aa693e99SJason King * APPEND_DATA bits apply only to a file. See aca_parent/aca_child 148*aa693e99SJason King * below. 149*aa693e99SJason King */ 150*aa693e99SJason King #define L9P_ACE_READ_DATA 0x00001 151*aa693e99SJason King #define L9P_ACE_LIST_DIRECTORY 0x00001 /* same as READ_DATA */ 152*aa693e99SJason King #define L9P_ACE_WRITE_DATA 0x00002 153*aa693e99SJason King #define L9P_ACE_ADD_FILE 0x00002 /* same as WRITE_DATA */ 154*aa693e99SJason King #define L9P_ACE_APPEND_DATA 0x00004 155*aa693e99SJason King #define L9P_ACE_ADD_SUBDIRECTORY 0x00004 /* same as APPEND_DATA */ 156*aa693e99SJason King #define L9P_ACE_READ_NAMED_ATTRS 0x00008 157*aa693e99SJason King #define L9P_ACE_WRITE_NAMED_ATTRS 0x00010 158*aa693e99SJason King #define L9P_ACE_EXECUTE 0x00020 159*aa693e99SJason King #define L9P_ACE_DELETE_CHILD 0x00040 160*aa693e99SJason King #define L9P_ACE_READ_ATTRIBUTES 0x00080 161*aa693e99SJason King #define L9P_ACE_WRITE_ATTRIBUTES 0x00100 162*aa693e99SJason King #define L9P_ACE_WRITE_RETENTION 0x00200 /* not used here */ 163*aa693e99SJason King #define L9P_ACE_WRITE_RETENTION_HOLD 0x00400 /* not used here */ 164*aa693e99SJason King /* 0x00800 unused? */ 165*aa693e99SJason King #define L9P_ACE_DELETE 0x01000 166*aa693e99SJason King #define L9P_ACE_READ_ACL 0x02000 167*aa693e99SJason King #define L9P_ACE_WRITE_ACL 0x04000 168*aa693e99SJason King #define L9P_ACE_WRITE_OWNER 0x08000 169*aa693e99SJason King #define L9P_ACE_SYNCHRONIZE 0x10000 /* not used here */ 170*aa693e99SJason King 171*aa693e99SJason King /* 172*aa693e99SJason King * This is not an ACE bit, but is used with the access checking 173*aa693e99SJason King * below. It represents a request to unlink (delete child / 174*aa693e99SJason King * delete) an entity, and is equivalent to asking for *either* 175*aa693e99SJason King * (not both) permission. 176*aa693e99SJason King */ 177*aa693e99SJason King #define L9P_ACOP_UNLINK (L9P_ACE_DELETE_CHILD | L9P_ACE_DELETE) 178*aa693e99SJason King 179*aa693e99SJason King /* 180*aa693e99SJason King * Access checking takes a lot of arguments, so they are 181*aa693e99SJason King * collected into a "struct" here. 182*aa693e99SJason King * 183*aa693e99SJason King * The aca_parent and aca_pstat fields may/must be NULL if the 184*aa693e99SJason King * operation itself does not involve "directory" permissions. 185*aa693e99SJason King * The aca_child and aca_cstat fields may/must be NULL if the 186*aa693e99SJason King * operation does not involve anything *but* a directory. This 187*aa693e99SJason King * is how we decide whether you're interested in L9P_ACE_READ_DATA 188*aa693e99SJason King * vs L9P_ACE_LIST_DIRECTORY, for instance. 189*aa693e99SJason King * 190*aa693e99SJason King * Note that it's OK for both parent and child to be directories 191*aa693e99SJason King * (as is the case when we're adding or deleting a subdirectory). 192*aa693e99SJason King */ 193*aa693e99SJason King struct l9p_acl_check_args { 194*aa693e99SJason King uid_t aca_uid; /* the uid that is requesting access */ 195*aa693e99SJason King gid_t aca_gid; /* the gid that is requesting access */ 196*aa693e99SJason King gid_t *aca_groups; /* the additional group-set, if any */ 197*aa693e99SJason King size_t aca_ngroups; /* number of groups in group-set */ 198*aa693e99SJason King struct l9p_acl *aca_parent; /* ACLs associated with parent/dir */ 199*aa693e99SJason King struct stat *aca_pstat; /* stat data for parent/dir */ 200*aa693e99SJason King struct l9p_acl *aca_child; /* ACLs associated with file */ 201*aa693e99SJason King struct stat *aca_cstat; /* stat data for file */ 202*aa693e99SJason King int aca_aclmode; /* mode checking bits, see below */ 203*aa693e99SJason King bool aca_superuser; /* alway allow uid==0 in STAT_MODE */ 204*aa693e99SJason King }; 205*aa693e99SJason King 206*aa693e99SJason King /* 207*aa693e99SJason King * Access checking mode bits in aca_checkmode. If you enable 208*aa693e99SJason King * ACLs, they are used first, optionally with ZFS style ACLs. 209*aa693e99SJason King * This means that even if aca_superuser is set, if an ACL denies 210*aa693e99SJason King * permission to uid 0, permission is really denied. 211*aa693e99SJason King * 212*aa693e99SJason King * NFS style ACLs run before POSIX style ACLs (though POSIX 213*aa693e99SJason King * ACLs aren't done yet anyway). 214*aa693e99SJason King * 215*aa693e99SJason King * N.B.: you probably want L9P_ACL_ZFS, especially when operating 216*aa693e99SJason King * with a ZFS file system on FreeBSD. 217*aa693e99SJason King */ 218*aa693e99SJason King #define L9P_ACM_NFS_ACL 0x0001 /* enable NFS ACL checking */ 219*aa693e99SJason King #define L9P_ACM_ZFS_ACL 0x0002 /* use ZFS ACL unlink semantics */ 220*aa693e99SJason King #define L9P_ACM_POSIX_ACL 0x0004 /* enable POSIX ACL checking (notyet) */ 221*aa693e99SJason King #define L9P_ACM_STAT_MODE 0x0008 /* enable st_mode bits */ 222*aa693e99SJason King 223*aa693e99SJason King /* 224*aa693e99SJason King * Requests to access some file or directory must provide: 225*aa693e99SJason King * 226*aa693e99SJason King * - An operation. This should usually be just one bit from the 227*aa693e99SJason King * L9P_ACE_* bit-sets above, or our special L9P_ACOP_UNLINK. 228*aa693e99SJason King * For a few file-open operations it may be multiple bits, 229*aa693e99SJason King * e.g., both read and write data. 230*aa693e99SJason King * - The identity of the accessor: uid + gid + gid-set. 231*aa693e99SJason King * - The type of access desired: this may be multiple bits. 232*aa693e99SJason King * - The parent directory, if applicable. 233*aa693e99SJason King * - The child file/dir being accessed, if applicable. 234*aa693e99SJason King * - stat data for parent and/or child, if applicable. 235*aa693e99SJason King * 236*aa693e99SJason King * The ACLs and/or stat data of the parent and/or child get used 237*aa693e99SJason King * here, so the caller must provide them. We should have a way to 238*aa693e99SJason King * cache these on fids, but not yet. The parent and child 239*aa693e99SJason King * arguments are a bit tricky; see the code in genacl.c. 240*aa693e99SJason King */ 241*aa693e99SJason King int l9p_acl_check_access(int32_t op, struct l9p_acl_check_args *args); 242*aa693e99SJason King 243*aa693e99SJason King /* 244*aa693e99SJason King * When falling back to POSIX ACL or Unix-style permissions 245*aa693e99SJason King * testing, it's nice to collapse the above detailed permissions 246*aa693e99SJason King * into simple read/write/execute bits (value 0..7). We provide 247*aa693e99SJason King * a small utility function that does this. 248*aa693e99SJason King */ 249*aa693e99SJason King int l9p_ace_mask_to_rwx(int32_t); 250*aa693e99SJason King 251*aa693e99SJason King /* 252*aa693e99SJason King * The rest of the data in an ACE. 253*aa693e99SJason King */ 254*aa693e99SJason King 255*aa693e99SJason King /* type in ace_type */ 256*aa693e99SJason King #define L9P_ACET_ACCESS_ALLOWED 0 257*aa693e99SJason King #define L9P_ACET_ACCESS_DENIED 1 258*aa693e99SJason King #define L9P_ACET_SYSTEM_AUDIT 2 259*aa693e99SJason King #define L9P_ACET_SYSTEM_ALARM 3 260*aa693e99SJason King 261*aa693e99SJason King /* flags in ace_flags */ 262*aa693e99SJason King #define L9P_ACEF_FILE_INHERIT_ACE 0x001 263*aa693e99SJason King #define L9P_ACEF_DIRECTORY_INHERIT_ACE 0x002 264*aa693e99SJason King #define L9P_ACEF_NO_PROPAGATE_INHERIT_ACE 0x004 265*aa693e99SJason King #define L9P_ACEF_INHERIT_ONLY_ACE 0x008 266*aa693e99SJason King #define L9P_ACEF_SUCCESSFUL_ACCESS_ACE_FLAG 0x010 267*aa693e99SJason King #define L9P_ACEF_FAILED_ACCESS_ACE_FLAG 0x020 268*aa693e99SJason King #define L9P_ACEF_IDENTIFIER_GROUP 0x040 269*aa693e99SJason King #define L9P_ACEF_OWNER 0x080 270*aa693e99SJason King #define L9P_ACEF_GROUP 0x100 271*aa693e99SJason King #define L9P_ACEF_EVERYONE 0x200 272*aa693e99SJason King 273*aa693e99SJason King #if defined(__APPLE__) 274*aa693e99SJason King # define L9P_ACE_IDSIZE 16 /* but, how do we map Darwin uuid? */ 275*aa693e99SJason King #else 276*aa693e99SJason King # define L9P_ACE_IDSIZE 4 277*aa693e99SJason King #endif 278*aa693e99SJason King 279*aa693e99SJason King struct l9p_ace { 280*aa693e99SJason King uint16_t ace_type; /* ACL entry type */ 281*aa693e99SJason King uint16_t ace_flags; /* ACL entry flags */ 282*aa693e99SJason King uint32_t ace_mask; /* ACL entry mask */ 283*aa693e99SJason King uint32_t ace_idsize; /* length of ace_idbytes */ 284*aa693e99SJason King unsigned char ace_idbytes[L9P_ACE_IDSIZE]; 285*aa693e99SJason King }; 286*aa693e99SJason King 287*aa693e99SJason King #define L9P_ACLTYPE_NFSv4 1 /* currently the only valid type */ 288*aa693e99SJason King struct l9p_acl { 289*aa693e99SJason King uint32_t acl_acetype; /* reserved for future expansion */ 290*aa693e99SJason King uint32_t acl_nace; /* number of occupied ACEs */ 291*aa693e99SJason King uint32_t acl_aceasize; /* actual size of ACE array */ 292*aa693e99SJason King struct l9p_ace acl_aces[]; /* variable length ACE array */ 293*aa693e99SJason King }; 294*aa693e99SJason King 295*aa693e99SJason King /* 296*aa693e99SJason King * These are the system-specific converters. 297*aa693e99SJason King * 298*aa693e99SJason King * Right now the backend needs to just find BSD NFSv4 ACLs 299*aa693e99SJason King * and convert them before each operation that needs to be 300*aa693e99SJason King * tested. 301*aa693e99SJason King */ 302*aa693e99SJason King #if defined(HAVE_DARWIN_ACLS) 303*aa693e99SJason King struct l9p_acl *l9p_darwin_nfsv4acl_to_acl(acl_t acl); 304*aa693e99SJason King #endif 305*aa693e99SJason King 306*aa693e99SJason King #if defined(HAVE_FREEBSD_ACLS) 307*aa693e99SJason King struct l9p_acl *l9p_freebsd_nfsv4acl_to_acl(acl_t acl); 308*aa693e99SJason King #endif 309*aa693e99SJason King 310*aa693e99SJason King #if defined(HAVE__ILLUMOS_ACLS) 311*aa693e99SJason King struct l9p_acl *l9p_illumos_nfsv4acl_to_acl(acl_t *acl); 312*aa693e99SJason King #endif 313*aa693e99SJason King 314*aa693e99SJason King #if defined(HAVE_POSIX_ACLS) && 0 /* not yet */ 315*aa693e99SJason King struct l9p_acl *l9p_posix_acl_to_acl(acl_t acl); 316*aa693e99SJason King #endif 317