1 /* 2 * linux/fs/posix_acl.c 3 * 4 * Copyright (C) 2002 by Andreas Gruenbacher <a.gruenbacher@computer.org> 5 * 6 * Fixes from William Schumacher incorporated on 15 March 2001. 7 * (Reported by Charles Bertsch, <CBertsch@microtest.com>). 8 */ 9 10 /* 11 * This file contains generic functions for manipulating 12 * POSIX 1003.1e draft standard 17 ACLs. 13 */ 14 15 #include <linux/kernel.h> 16 #include <linux/slab.h> 17 #include <linux/atomic.h> 18 #include <linux/fs.h> 19 #include <linux/sched.h> 20 #include <linux/posix_acl.h> 21 #include <linux/export.h> 22 23 #include <linux/errno.h> 24 25 struct posix_acl **acl_by_type(struct inode *inode, int type) 26 { 27 switch (type) { 28 case ACL_TYPE_ACCESS: 29 return &inode->i_acl; 30 case ACL_TYPE_DEFAULT: 31 return &inode->i_default_acl; 32 default: 33 BUG(); 34 } 35 } 36 EXPORT_SYMBOL(acl_by_type); 37 38 struct posix_acl *get_cached_acl(struct inode *inode, int type) 39 { 40 struct posix_acl **p = acl_by_type(inode, type); 41 struct posix_acl *acl = ACCESS_ONCE(*p); 42 if (acl) { 43 spin_lock(&inode->i_lock); 44 acl = *p; 45 if (acl != ACL_NOT_CACHED) 46 acl = posix_acl_dup(acl); 47 spin_unlock(&inode->i_lock); 48 } 49 return acl; 50 } 51 EXPORT_SYMBOL(get_cached_acl); 52 53 struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type) 54 { 55 return rcu_dereference(*acl_by_type(inode, type)); 56 } 57 EXPORT_SYMBOL(get_cached_acl_rcu); 58 59 void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl) 60 { 61 struct posix_acl **p = acl_by_type(inode, type); 62 struct posix_acl *old; 63 spin_lock(&inode->i_lock); 64 old = *p; 65 rcu_assign_pointer(*p, posix_acl_dup(acl)); 66 spin_unlock(&inode->i_lock); 67 if (old != ACL_NOT_CACHED) 68 posix_acl_release(old); 69 } 70 EXPORT_SYMBOL(set_cached_acl); 71 72 void forget_cached_acl(struct inode *inode, int type) 73 { 74 struct posix_acl **p = acl_by_type(inode, type); 75 struct posix_acl *old; 76 spin_lock(&inode->i_lock); 77 old = *p; 78 *p = ACL_NOT_CACHED; 79 spin_unlock(&inode->i_lock); 80 if (old != ACL_NOT_CACHED) 81 posix_acl_release(old); 82 } 83 EXPORT_SYMBOL(forget_cached_acl); 84 85 void forget_all_cached_acls(struct inode *inode) 86 { 87 struct posix_acl *old_access, *old_default; 88 spin_lock(&inode->i_lock); 89 old_access = inode->i_acl; 90 old_default = inode->i_default_acl; 91 inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED; 92 spin_unlock(&inode->i_lock); 93 if (old_access != ACL_NOT_CACHED) 94 posix_acl_release(old_access); 95 if (old_default != ACL_NOT_CACHED) 96 posix_acl_release(old_default); 97 } 98 EXPORT_SYMBOL(forget_all_cached_acls); 99 100 /* 101 * Init a fresh posix_acl 102 */ 103 void 104 posix_acl_init(struct posix_acl *acl, int count) 105 { 106 atomic_set(&acl->a_refcount, 1); 107 acl->a_count = count; 108 } 109 EXPORT_SYMBOL(posix_acl_init); 110 111 /* 112 * Allocate a new ACL with the specified number of entries. 113 */ 114 struct posix_acl * 115 posix_acl_alloc(int count, gfp_t flags) 116 { 117 const size_t size = sizeof(struct posix_acl) + 118 count * sizeof(struct posix_acl_entry); 119 struct posix_acl *acl = kmalloc(size, flags); 120 if (acl) 121 posix_acl_init(acl, count); 122 return acl; 123 } 124 EXPORT_SYMBOL(posix_acl_alloc); 125 126 /* 127 * Clone an ACL. 128 */ 129 static struct posix_acl * 130 posix_acl_clone(const struct posix_acl *acl, gfp_t flags) 131 { 132 struct posix_acl *clone = NULL; 133 134 if (acl) { 135 int size = sizeof(struct posix_acl) + acl->a_count * 136 sizeof(struct posix_acl_entry); 137 clone = kmemdup(acl, size, flags); 138 if (clone) 139 atomic_set(&clone->a_refcount, 1); 140 } 141 return clone; 142 } 143 144 /* 145 * Check if an acl is valid. Returns 0 if it is, or -E... otherwise. 146 */ 147 int 148 posix_acl_valid(const struct posix_acl *acl) 149 { 150 const struct posix_acl_entry *pa, *pe; 151 int state = ACL_USER_OBJ; 152 int needs_mask = 0; 153 154 FOREACH_ACL_ENTRY(pa, acl, pe) { 155 if (pa->e_perm & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE)) 156 return -EINVAL; 157 switch (pa->e_tag) { 158 case ACL_USER_OBJ: 159 if (state == ACL_USER_OBJ) { 160 state = ACL_USER; 161 break; 162 } 163 return -EINVAL; 164 165 case ACL_USER: 166 if (state != ACL_USER) 167 return -EINVAL; 168 if (!uid_valid(pa->e_uid)) 169 return -EINVAL; 170 needs_mask = 1; 171 break; 172 173 case ACL_GROUP_OBJ: 174 if (state == ACL_USER) { 175 state = ACL_GROUP; 176 break; 177 } 178 return -EINVAL; 179 180 case ACL_GROUP: 181 if (state != ACL_GROUP) 182 return -EINVAL; 183 if (!gid_valid(pa->e_gid)) 184 return -EINVAL; 185 needs_mask = 1; 186 break; 187 188 case ACL_MASK: 189 if (state != ACL_GROUP) 190 return -EINVAL; 191 state = ACL_OTHER; 192 break; 193 194 case ACL_OTHER: 195 if (state == ACL_OTHER || 196 (state == ACL_GROUP && !needs_mask)) { 197 state = 0; 198 break; 199 } 200 return -EINVAL; 201 202 default: 203 return -EINVAL; 204 } 205 } 206 if (state == 0) 207 return 0; 208 return -EINVAL; 209 } 210 EXPORT_SYMBOL(posix_acl_valid); 211 212 /* 213 * Returns 0 if the acl can be exactly represented in the traditional 214 * file mode permission bits, or else 1. Returns -E... on error. 215 */ 216 int 217 posix_acl_equiv_mode(const struct posix_acl *acl, umode_t *mode_p) 218 { 219 const struct posix_acl_entry *pa, *pe; 220 umode_t mode = 0; 221 int not_equiv = 0; 222 223 FOREACH_ACL_ENTRY(pa, acl, pe) { 224 switch (pa->e_tag) { 225 case ACL_USER_OBJ: 226 mode |= (pa->e_perm & S_IRWXO) << 6; 227 break; 228 case ACL_GROUP_OBJ: 229 mode |= (pa->e_perm & S_IRWXO) << 3; 230 break; 231 case ACL_OTHER: 232 mode |= pa->e_perm & S_IRWXO; 233 break; 234 case ACL_MASK: 235 mode = (mode & ~S_IRWXG) | 236 ((pa->e_perm & S_IRWXO) << 3); 237 not_equiv = 1; 238 break; 239 case ACL_USER: 240 case ACL_GROUP: 241 not_equiv = 1; 242 break; 243 default: 244 return -EINVAL; 245 } 246 } 247 if (mode_p) 248 *mode_p = (*mode_p & ~S_IRWXUGO) | mode; 249 return not_equiv; 250 } 251 EXPORT_SYMBOL(posix_acl_equiv_mode); 252 253 /* 254 * Create an ACL representing the file mode permission bits of an inode. 255 */ 256 struct posix_acl * 257 posix_acl_from_mode(umode_t mode, gfp_t flags) 258 { 259 struct posix_acl *acl = posix_acl_alloc(3, flags); 260 if (!acl) 261 return ERR_PTR(-ENOMEM); 262 263 acl->a_entries[0].e_tag = ACL_USER_OBJ; 264 acl->a_entries[0].e_perm = (mode & S_IRWXU) >> 6; 265 266 acl->a_entries[1].e_tag = ACL_GROUP_OBJ; 267 acl->a_entries[1].e_perm = (mode & S_IRWXG) >> 3; 268 269 acl->a_entries[2].e_tag = ACL_OTHER; 270 acl->a_entries[2].e_perm = (mode & S_IRWXO); 271 return acl; 272 } 273 EXPORT_SYMBOL(posix_acl_from_mode); 274 275 /* 276 * Return 0 if current is granted want access to the inode 277 * by the acl. Returns -E... otherwise. 278 */ 279 int 280 posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want) 281 { 282 const struct posix_acl_entry *pa, *pe, *mask_obj; 283 int found = 0; 284 285 want &= MAY_READ | MAY_WRITE | MAY_EXEC | MAY_NOT_BLOCK; 286 287 FOREACH_ACL_ENTRY(pa, acl, pe) { 288 switch(pa->e_tag) { 289 case ACL_USER_OBJ: 290 /* (May have been checked already) */ 291 if (uid_eq(inode->i_uid, current_fsuid())) 292 goto check_perm; 293 break; 294 case ACL_USER: 295 if (uid_eq(pa->e_uid, current_fsuid())) 296 goto mask; 297 break; 298 case ACL_GROUP_OBJ: 299 if (in_group_p(inode->i_gid)) { 300 found = 1; 301 if ((pa->e_perm & want) == want) 302 goto mask; 303 } 304 break; 305 case ACL_GROUP: 306 if (in_group_p(pa->e_gid)) { 307 found = 1; 308 if ((pa->e_perm & want) == want) 309 goto mask; 310 } 311 break; 312 case ACL_MASK: 313 break; 314 case ACL_OTHER: 315 if (found) 316 return -EACCES; 317 else 318 goto check_perm; 319 default: 320 return -EIO; 321 } 322 } 323 return -EIO; 324 325 mask: 326 for (mask_obj = pa+1; mask_obj != pe; mask_obj++) { 327 if (mask_obj->e_tag == ACL_MASK) { 328 if ((pa->e_perm & mask_obj->e_perm & want) == want) 329 return 0; 330 return -EACCES; 331 } 332 } 333 334 check_perm: 335 if ((pa->e_perm & want) == want) 336 return 0; 337 return -EACCES; 338 } 339 340 /* 341 * Modify acl when creating a new inode. The caller must ensure the acl is 342 * only referenced once. 343 * 344 * mode_p initially must contain the mode parameter to the open() / creat() 345 * system calls. All permissions that are not granted by the acl are removed. 346 * The permissions in the acl are changed to reflect the mode_p parameter. 347 */ 348 static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) 349 { 350 struct posix_acl_entry *pa, *pe; 351 struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL; 352 umode_t mode = *mode_p; 353 int not_equiv = 0; 354 355 /* assert(atomic_read(acl->a_refcount) == 1); */ 356 357 FOREACH_ACL_ENTRY(pa, acl, pe) { 358 switch(pa->e_tag) { 359 case ACL_USER_OBJ: 360 pa->e_perm &= (mode >> 6) | ~S_IRWXO; 361 mode &= (pa->e_perm << 6) | ~S_IRWXU; 362 break; 363 364 case ACL_USER: 365 case ACL_GROUP: 366 not_equiv = 1; 367 break; 368 369 case ACL_GROUP_OBJ: 370 group_obj = pa; 371 break; 372 373 case ACL_OTHER: 374 pa->e_perm &= mode | ~S_IRWXO; 375 mode &= pa->e_perm | ~S_IRWXO; 376 break; 377 378 case ACL_MASK: 379 mask_obj = pa; 380 not_equiv = 1; 381 break; 382 383 default: 384 return -EIO; 385 } 386 } 387 388 if (mask_obj) { 389 mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO; 390 mode &= (mask_obj->e_perm << 3) | ~S_IRWXG; 391 } else { 392 if (!group_obj) 393 return -EIO; 394 group_obj->e_perm &= (mode >> 3) | ~S_IRWXO; 395 mode &= (group_obj->e_perm << 3) | ~S_IRWXG; 396 } 397 398 *mode_p = (*mode_p & ~S_IRWXUGO) | mode; 399 return not_equiv; 400 } 401 402 /* 403 * Modify the ACL for the chmod syscall. 404 */ 405 static int posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode) 406 { 407 struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL; 408 struct posix_acl_entry *pa, *pe; 409 410 /* assert(atomic_read(acl->a_refcount) == 1); */ 411 412 FOREACH_ACL_ENTRY(pa, acl, pe) { 413 switch(pa->e_tag) { 414 case ACL_USER_OBJ: 415 pa->e_perm = (mode & S_IRWXU) >> 6; 416 break; 417 418 case ACL_USER: 419 case ACL_GROUP: 420 break; 421 422 case ACL_GROUP_OBJ: 423 group_obj = pa; 424 break; 425 426 case ACL_MASK: 427 mask_obj = pa; 428 break; 429 430 case ACL_OTHER: 431 pa->e_perm = (mode & S_IRWXO); 432 break; 433 434 default: 435 return -EIO; 436 } 437 } 438 439 if (mask_obj) { 440 mask_obj->e_perm = (mode & S_IRWXG) >> 3; 441 } else { 442 if (!group_obj) 443 return -EIO; 444 group_obj->e_perm = (mode & S_IRWXG) >> 3; 445 } 446 447 return 0; 448 } 449 450 int 451 posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p) 452 { 453 struct posix_acl *clone = posix_acl_clone(*acl, gfp); 454 int err = -ENOMEM; 455 if (clone) { 456 err = posix_acl_create_masq(clone, mode_p); 457 if (err < 0) { 458 posix_acl_release(clone); 459 clone = NULL; 460 } 461 } 462 posix_acl_release(*acl); 463 *acl = clone; 464 return err; 465 } 466 EXPORT_SYMBOL(posix_acl_create); 467 468 int 469 posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode) 470 { 471 struct posix_acl *clone = posix_acl_clone(*acl, gfp); 472 int err = -ENOMEM; 473 if (clone) { 474 err = posix_acl_chmod_masq(clone, mode); 475 if (err) { 476 posix_acl_release(clone); 477 clone = NULL; 478 } 479 } 480 posix_acl_release(*acl); 481 *acl = clone; 482 return err; 483 } 484 EXPORT_SYMBOL(posix_acl_chmod); 485