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