1 /* 2 * linux/fs/ext4/acl.c 3 * 4 * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> 5 */ 6 7 #include <linux/init.h> 8 #include <linux/sched.h> 9 #include <linux/slab.h> 10 #include <linux/capability.h> 11 #include <linux/fs.h> 12 #include <linux/ext4_jbd2.h> 13 #include <linux/ext4_fs.h> 14 #include "xattr.h" 15 #include "acl.h" 16 17 /* 18 * Convert from filesystem to in-memory representation. 19 */ 20 static struct posix_acl * 21 ext4_acl_from_disk(const void *value, size_t size) 22 { 23 const char *end = (char *)value + size; 24 int n, count; 25 struct posix_acl *acl; 26 27 if (!value) 28 return NULL; 29 if (size < sizeof(ext4_acl_header)) 30 return ERR_PTR(-EINVAL); 31 if (((ext4_acl_header *)value)->a_version != 32 cpu_to_le32(EXT4_ACL_VERSION)) 33 return ERR_PTR(-EINVAL); 34 value = (char *)value + sizeof(ext4_acl_header); 35 count = ext4_acl_count(size); 36 if (count < 0) 37 return ERR_PTR(-EINVAL); 38 if (count == 0) 39 return NULL; 40 acl = posix_acl_alloc(count, GFP_KERNEL); 41 if (!acl) 42 return ERR_PTR(-ENOMEM); 43 for (n=0; n < count; n++) { 44 ext4_acl_entry *entry = 45 (ext4_acl_entry *)value; 46 if ((char *)value + sizeof(ext4_acl_entry_short) > end) 47 goto fail; 48 acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); 49 acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); 50 switch(acl->a_entries[n].e_tag) { 51 case ACL_USER_OBJ: 52 case ACL_GROUP_OBJ: 53 case ACL_MASK: 54 case ACL_OTHER: 55 value = (char *)value + 56 sizeof(ext4_acl_entry_short); 57 acl->a_entries[n].e_id = ACL_UNDEFINED_ID; 58 break; 59 60 case ACL_USER: 61 case ACL_GROUP: 62 value = (char *)value + sizeof(ext4_acl_entry); 63 if ((char *)value > end) 64 goto fail; 65 acl->a_entries[n].e_id = 66 le32_to_cpu(entry->e_id); 67 break; 68 69 default: 70 goto fail; 71 } 72 } 73 if (value != end) 74 goto fail; 75 return acl; 76 77 fail: 78 posix_acl_release(acl); 79 return ERR_PTR(-EINVAL); 80 } 81 82 /* 83 * Convert from in-memory to filesystem representation. 84 */ 85 static void * 86 ext4_acl_to_disk(const struct posix_acl *acl, size_t *size) 87 { 88 ext4_acl_header *ext_acl; 89 char *e; 90 size_t n; 91 92 *size = ext4_acl_size(acl->a_count); 93 ext_acl = kmalloc(sizeof(ext4_acl_header) + acl->a_count * 94 sizeof(ext4_acl_entry), GFP_KERNEL); 95 if (!ext_acl) 96 return ERR_PTR(-ENOMEM); 97 ext_acl->a_version = cpu_to_le32(EXT4_ACL_VERSION); 98 e = (char *)ext_acl + sizeof(ext4_acl_header); 99 for (n=0; n < acl->a_count; n++) { 100 ext4_acl_entry *entry = (ext4_acl_entry *)e; 101 entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); 102 entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); 103 switch(acl->a_entries[n].e_tag) { 104 case ACL_USER: 105 case ACL_GROUP: 106 entry->e_id = 107 cpu_to_le32(acl->a_entries[n].e_id); 108 e += sizeof(ext4_acl_entry); 109 break; 110 111 case ACL_USER_OBJ: 112 case ACL_GROUP_OBJ: 113 case ACL_MASK: 114 case ACL_OTHER: 115 e += sizeof(ext4_acl_entry_short); 116 break; 117 118 default: 119 goto fail; 120 } 121 } 122 return (char *)ext_acl; 123 124 fail: 125 kfree(ext_acl); 126 return ERR_PTR(-EINVAL); 127 } 128 129 static inline struct posix_acl * 130 ext4_iget_acl(struct inode *inode, struct posix_acl **i_acl) 131 { 132 struct posix_acl *acl = EXT4_ACL_NOT_CACHED; 133 134 spin_lock(&inode->i_lock); 135 if (*i_acl != EXT4_ACL_NOT_CACHED) 136 acl = posix_acl_dup(*i_acl); 137 spin_unlock(&inode->i_lock); 138 139 return acl; 140 } 141 142 static inline void 143 ext4_iset_acl(struct inode *inode, struct posix_acl **i_acl, 144 struct posix_acl *acl) 145 { 146 spin_lock(&inode->i_lock); 147 if (*i_acl != EXT4_ACL_NOT_CACHED) 148 posix_acl_release(*i_acl); 149 *i_acl = posix_acl_dup(acl); 150 spin_unlock(&inode->i_lock); 151 } 152 153 /* 154 * Inode operation get_posix_acl(). 155 * 156 * inode->i_mutex: don't care 157 */ 158 static struct posix_acl * 159 ext4_get_acl(struct inode *inode, int type) 160 { 161 struct ext4_inode_info *ei = EXT4_I(inode); 162 int name_index; 163 char *value = NULL; 164 struct posix_acl *acl; 165 int retval; 166 167 if (!test_opt(inode->i_sb, POSIX_ACL)) 168 return NULL; 169 170 switch(type) { 171 case ACL_TYPE_ACCESS: 172 acl = ext4_iget_acl(inode, &ei->i_acl); 173 if (acl != EXT4_ACL_NOT_CACHED) 174 return acl; 175 name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; 176 break; 177 178 case ACL_TYPE_DEFAULT: 179 acl = ext4_iget_acl(inode, &ei->i_default_acl); 180 if (acl != EXT4_ACL_NOT_CACHED) 181 return acl; 182 name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT; 183 break; 184 185 default: 186 return ERR_PTR(-EINVAL); 187 } 188 retval = ext4_xattr_get(inode, name_index, "", NULL, 0); 189 if (retval > 0) { 190 value = kmalloc(retval, GFP_KERNEL); 191 if (!value) 192 return ERR_PTR(-ENOMEM); 193 retval = ext4_xattr_get(inode, name_index, "", value, retval); 194 } 195 if (retval > 0) 196 acl = ext4_acl_from_disk(value, retval); 197 else if (retval == -ENODATA || retval == -ENOSYS) 198 acl = NULL; 199 else 200 acl = ERR_PTR(retval); 201 kfree(value); 202 203 if (!IS_ERR(acl)) { 204 switch(type) { 205 case ACL_TYPE_ACCESS: 206 ext4_iset_acl(inode, &ei->i_acl, acl); 207 break; 208 209 case ACL_TYPE_DEFAULT: 210 ext4_iset_acl(inode, &ei->i_default_acl, acl); 211 break; 212 } 213 } 214 return acl; 215 } 216 217 /* 218 * Set the access or default ACL of an inode. 219 * 220 * inode->i_mutex: down unless called from ext4_new_inode 221 */ 222 static int 223 ext4_set_acl(handle_t *handle, struct inode *inode, int type, 224 struct posix_acl *acl) 225 { 226 struct ext4_inode_info *ei = EXT4_I(inode); 227 int name_index; 228 void *value = NULL; 229 size_t size = 0; 230 int error; 231 232 if (S_ISLNK(inode->i_mode)) 233 return -EOPNOTSUPP; 234 235 switch(type) { 236 case ACL_TYPE_ACCESS: 237 name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; 238 if (acl) { 239 mode_t mode = inode->i_mode; 240 error = posix_acl_equiv_mode(acl, &mode); 241 if (error < 0) 242 return error; 243 else { 244 inode->i_mode = mode; 245 ext4_mark_inode_dirty(handle, inode); 246 if (error == 0) 247 acl = NULL; 248 } 249 } 250 break; 251 252 case ACL_TYPE_DEFAULT: 253 name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT; 254 if (!S_ISDIR(inode->i_mode)) 255 return acl ? -EACCES : 0; 256 break; 257 258 default: 259 return -EINVAL; 260 } 261 if (acl) { 262 value = ext4_acl_to_disk(acl, &size); 263 if (IS_ERR(value)) 264 return (int)PTR_ERR(value); 265 } 266 267 error = ext4_xattr_set_handle(handle, inode, name_index, "", 268 value, size, 0); 269 270 kfree(value); 271 if (!error) { 272 switch(type) { 273 case ACL_TYPE_ACCESS: 274 ext4_iset_acl(inode, &ei->i_acl, acl); 275 break; 276 277 case ACL_TYPE_DEFAULT: 278 ext4_iset_acl(inode, &ei->i_default_acl, acl); 279 break; 280 } 281 } 282 return error; 283 } 284 285 static int 286 ext4_check_acl(struct inode *inode, int mask) 287 { 288 struct posix_acl *acl = ext4_get_acl(inode, ACL_TYPE_ACCESS); 289 290 if (IS_ERR(acl)) 291 return PTR_ERR(acl); 292 if (acl) { 293 int error = posix_acl_permission(inode, acl, mask); 294 posix_acl_release(acl); 295 return error; 296 } 297 298 return -EAGAIN; 299 } 300 301 int 302 ext4_permission(struct inode *inode, int mask, struct nameidata *nd) 303 { 304 return generic_permission(inode, mask, ext4_check_acl); 305 } 306 307 /* 308 * Initialize the ACLs of a new inode. Called from ext4_new_inode. 309 * 310 * dir->i_mutex: down 311 * inode->i_mutex: up (access to inode is still exclusive) 312 */ 313 int 314 ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) 315 { 316 struct posix_acl *acl = NULL; 317 int error = 0; 318 319 if (!S_ISLNK(inode->i_mode)) { 320 if (test_opt(dir->i_sb, POSIX_ACL)) { 321 acl = ext4_get_acl(dir, ACL_TYPE_DEFAULT); 322 if (IS_ERR(acl)) 323 return PTR_ERR(acl); 324 } 325 if (!acl) 326 inode->i_mode &= ~current->fs->umask; 327 } 328 if (test_opt(inode->i_sb, POSIX_ACL) && acl) { 329 struct posix_acl *clone; 330 mode_t mode; 331 332 if (S_ISDIR(inode->i_mode)) { 333 error = ext4_set_acl(handle, inode, 334 ACL_TYPE_DEFAULT, acl); 335 if (error) 336 goto cleanup; 337 } 338 clone = posix_acl_clone(acl, GFP_KERNEL); 339 error = -ENOMEM; 340 if (!clone) 341 goto cleanup; 342 343 mode = inode->i_mode; 344 error = posix_acl_create_masq(clone, &mode); 345 if (error >= 0) { 346 inode->i_mode = mode; 347 if (error > 0) { 348 /* This is an extended ACL */ 349 error = ext4_set_acl(handle, inode, 350 ACL_TYPE_ACCESS, clone); 351 } 352 } 353 posix_acl_release(clone); 354 } 355 cleanup: 356 posix_acl_release(acl); 357 return error; 358 } 359 360 /* 361 * Does chmod for an inode that may have an Access Control List. The 362 * inode->i_mode field must be updated to the desired value by the caller 363 * before calling this function. 364 * Returns 0 on success, or a negative error number. 365 * 366 * We change the ACL rather than storing some ACL entries in the file 367 * mode permission bits (which would be more efficient), because that 368 * would break once additional permissions (like ACL_APPEND, ACL_DELETE 369 * for directories) are added. There are no more bits available in the 370 * file mode. 371 * 372 * inode->i_mutex: down 373 */ 374 int 375 ext4_acl_chmod(struct inode *inode) 376 { 377 struct posix_acl *acl, *clone; 378 int error; 379 380 if (S_ISLNK(inode->i_mode)) 381 return -EOPNOTSUPP; 382 if (!test_opt(inode->i_sb, POSIX_ACL)) 383 return 0; 384 acl = ext4_get_acl(inode, ACL_TYPE_ACCESS); 385 if (IS_ERR(acl) || !acl) 386 return PTR_ERR(acl); 387 clone = posix_acl_clone(acl, GFP_KERNEL); 388 posix_acl_release(acl); 389 if (!clone) 390 return -ENOMEM; 391 error = posix_acl_chmod_masq(clone, inode->i_mode); 392 if (!error) { 393 handle_t *handle; 394 int retries = 0; 395 396 retry: 397 handle = ext4_journal_start(inode, 398 EXT4_DATA_TRANS_BLOCKS(inode->i_sb)); 399 if (IS_ERR(handle)) { 400 error = PTR_ERR(handle); 401 ext4_std_error(inode->i_sb, error); 402 goto out; 403 } 404 error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, clone); 405 ext4_journal_stop(handle); 406 if (error == -ENOSPC && 407 ext4_should_retry_alloc(inode->i_sb, &retries)) 408 goto retry; 409 } 410 out: 411 posix_acl_release(clone); 412 return error; 413 } 414 415 /* 416 * Extended attribute handlers 417 */ 418 static size_t 419 ext4_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len, 420 const char *name, size_t name_len) 421 { 422 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS); 423 424 if (!test_opt(inode->i_sb, POSIX_ACL)) 425 return 0; 426 if (list && size <= list_len) 427 memcpy(list, POSIX_ACL_XATTR_ACCESS, size); 428 return size; 429 } 430 431 static size_t 432 ext4_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len, 433 const char *name, size_t name_len) 434 { 435 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT); 436 437 if (!test_opt(inode->i_sb, POSIX_ACL)) 438 return 0; 439 if (list && size <= list_len) 440 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size); 441 return size; 442 } 443 444 static int 445 ext4_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size) 446 { 447 struct posix_acl *acl; 448 int error; 449 450 if (!test_opt(inode->i_sb, POSIX_ACL)) 451 return -EOPNOTSUPP; 452 453 acl = ext4_get_acl(inode, type); 454 if (IS_ERR(acl)) 455 return PTR_ERR(acl); 456 if (acl == NULL) 457 return -ENODATA; 458 error = posix_acl_to_xattr(acl, buffer, size); 459 posix_acl_release(acl); 460 461 return error; 462 } 463 464 static int 465 ext4_xattr_get_acl_access(struct inode *inode, const char *name, 466 void *buffer, size_t size) 467 { 468 if (strcmp(name, "") != 0) 469 return -EINVAL; 470 return ext4_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size); 471 } 472 473 static int 474 ext4_xattr_get_acl_default(struct inode *inode, const char *name, 475 void *buffer, size_t size) 476 { 477 if (strcmp(name, "") != 0) 478 return -EINVAL; 479 return ext4_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size); 480 } 481 482 static int 483 ext4_xattr_set_acl(struct inode *inode, int type, const void *value, 484 size_t size) 485 { 486 handle_t *handle; 487 struct posix_acl *acl; 488 int error, retries = 0; 489 490 if (!test_opt(inode->i_sb, POSIX_ACL)) 491 return -EOPNOTSUPP; 492 if (!is_owner_or_cap(inode)) 493 return -EPERM; 494 495 if (value) { 496 acl = posix_acl_from_xattr(value, size); 497 if (IS_ERR(acl)) 498 return PTR_ERR(acl); 499 else if (acl) { 500 error = posix_acl_valid(acl); 501 if (error) 502 goto release_and_out; 503 } 504 } else 505 acl = NULL; 506 507 retry: 508 handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb)); 509 if (IS_ERR(handle)) 510 return PTR_ERR(handle); 511 error = ext4_set_acl(handle, inode, type, acl); 512 ext4_journal_stop(handle); 513 if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) 514 goto retry; 515 516 release_and_out: 517 posix_acl_release(acl); 518 return error; 519 } 520 521 static int 522 ext4_xattr_set_acl_access(struct inode *inode, const char *name, 523 const void *value, size_t size, int flags) 524 { 525 if (strcmp(name, "") != 0) 526 return -EINVAL; 527 return ext4_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size); 528 } 529 530 static int 531 ext4_xattr_set_acl_default(struct inode *inode, const char *name, 532 const void *value, size_t size, int flags) 533 { 534 if (strcmp(name, "") != 0) 535 return -EINVAL; 536 return ext4_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size); 537 } 538 539 struct xattr_handler ext4_xattr_acl_access_handler = { 540 .prefix = POSIX_ACL_XATTR_ACCESS, 541 .list = ext4_xattr_list_acl_access, 542 .get = ext4_xattr_get_acl_access, 543 .set = ext4_xattr_set_acl_access, 544 }; 545 546 struct xattr_handler ext4_xattr_acl_default_handler = { 547 .prefix = POSIX_ACL_XATTR_DEFAULT, 548 .list = ext4_xattr_list_acl_default, 549 .get = ext4_xattr_get_acl_default, 550 .set = ext4_xattr_set_acl_default, 551 }; 552