Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.32-rc7 557 lines 14 kB view raw
1#include <linux/capability.h> 2#include <linux/fs.h> 3#include <linux/posix_acl.h> 4#include <linux/reiserfs_fs.h> 5#include <linux/errno.h> 6#include <linux/pagemap.h> 7#include <linux/xattr.h> 8#include <linux/posix_acl_xattr.h> 9#include <linux/reiserfs_xattr.h> 10#include <linux/reiserfs_acl.h> 11#include <asm/uaccess.h> 12 13static int reiserfs_set_acl(struct reiserfs_transaction_handle *th, 14 struct inode *inode, int type, 15 struct posix_acl *acl); 16 17static int 18xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) 19{ 20 struct posix_acl *acl; 21 int error, error2; 22 struct reiserfs_transaction_handle th; 23 size_t jcreate_blocks; 24 if (!reiserfs_posixacl(inode->i_sb)) 25 return -EOPNOTSUPP; 26 if (!is_owner_or_cap(inode)) 27 return -EPERM; 28 29 if (value) { 30 acl = posix_acl_from_xattr(value, size); 31 if (IS_ERR(acl)) { 32 return PTR_ERR(acl); 33 } else if (acl) { 34 error = posix_acl_valid(acl); 35 if (error) 36 goto release_and_out; 37 } 38 } else 39 acl = NULL; 40 41 /* Pessimism: We can't assume that anything from the xattr root up 42 * has been created. */ 43 44 jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) + 45 reiserfs_xattr_nblocks(inode, size) * 2; 46 47 reiserfs_write_lock(inode->i_sb); 48 error = journal_begin(&th, inode->i_sb, jcreate_blocks); 49 if (error == 0) { 50 error = reiserfs_set_acl(&th, inode, type, acl); 51 error2 = journal_end(&th, inode->i_sb, jcreate_blocks); 52 if (error2) 53 error = error2; 54 } 55 reiserfs_write_unlock(inode->i_sb); 56 57 release_and_out: 58 posix_acl_release(acl); 59 return error; 60} 61 62static int 63xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size) 64{ 65 struct posix_acl *acl; 66 int error; 67 68 if (!reiserfs_posixacl(inode->i_sb)) 69 return -EOPNOTSUPP; 70 71 acl = reiserfs_get_acl(inode, type); 72 if (IS_ERR(acl)) 73 return PTR_ERR(acl); 74 if (acl == NULL) 75 return -ENODATA; 76 error = posix_acl_to_xattr(acl, buffer, size); 77 posix_acl_release(acl); 78 79 return error; 80} 81 82/* 83 * Convert from filesystem to in-memory representation. 84 */ 85static struct posix_acl *posix_acl_from_disk(const void *value, size_t size) 86{ 87 const char *end = (char *)value + size; 88 int n, count; 89 struct posix_acl *acl; 90 91 if (!value) 92 return NULL; 93 if (size < sizeof(reiserfs_acl_header)) 94 return ERR_PTR(-EINVAL); 95 if (((reiserfs_acl_header *) value)->a_version != 96 cpu_to_le32(REISERFS_ACL_VERSION)) 97 return ERR_PTR(-EINVAL); 98 value = (char *)value + sizeof(reiserfs_acl_header); 99 count = reiserfs_acl_count(size); 100 if (count < 0) 101 return ERR_PTR(-EINVAL); 102 if (count == 0) 103 return NULL; 104 acl = posix_acl_alloc(count, GFP_NOFS); 105 if (!acl) 106 return ERR_PTR(-ENOMEM); 107 for (n = 0; n < count; n++) { 108 reiserfs_acl_entry *entry = (reiserfs_acl_entry *) value; 109 if ((char *)value + sizeof(reiserfs_acl_entry_short) > end) 110 goto fail; 111 acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); 112 acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); 113 switch (acl->a_entries[n].e_tag) { 114 case ACL_USER_OBJ: 115 case ACL_GROUP_OBJ: 116 case ACL_MASK: 117 case ACL_OTHER: 118 value = (char *)value + 119 sizeof(reiserfs_acl_entry_short); 120 acl->a_entries[n].e_id = ACL_UNDEFINED_ID; 121 break; 122 123 case ACL_USER: 124 case ACL_GROUP: 125 value = (char *)value + sizeof(reiserfs_acl_entry); 126 if ((char *)value > end) 127 goto fail; 128 acl->a_entries[n].e_id = le32_to_cpu(entry->e_id); 129 break; 130 131 default: 132 goto fail; 133 } 134 } 135 if (value != end) 136 goto fail; 137 return acl; 138 139 fail: 140 posix_acl_release(acl); 141 return ERR_PTR(-EINVAL); 142} 143 144/* 145 * Convert from in-memory to filesystem representation. 146 */ 147static void *posix_acl_to_disk(const struct posix_acl *acl, size_t * size) 148{ 149 reiserfs_acl_header *ext_acl; 150 char *e; 151 int n; 152 153 *size = reiserfs_acl_size(acl->a_count); 154 ext_acl = kmalloc(sizeof(reiserfs_acl_header) + 155 acl->a_count * 156 sizeof(reiserfs_acl_entry), 157 GFP_NOFS); 158 if (!ext_acl) 159 return ERR_PTR(-ENOMEM); 160 ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION); 161 e = (char *)ext_acl + sizeof(reiserfs_acl_header); 162 for (n = 0; n < acl->a_count; n++) { 163 reiserfs_acl_entry *entry = (reiserfs_acl_entry *) e; 164 entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); 165 entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); 166 switch (acl->a_entries[n].e_tag) { 167 case ACL_USER: 168 case ACL_GROUP: 169 entry->e_id = cpu_to_le32(acl->a_entries[n].e_id); 170 e += sizeof(reiserfs_acl_entry); 171 break; 172 173 case ACL_USER_OBJ: 174 case ACL_GROUP_OBJ: 175 case ACL_MASK: 176 case ACL_OTHER: 177 e += sizeof(reiserfs_acl_entry_short); 178 break; 179 180 default: 181 goto fail; 182 } 183 } 184 return (char *)ext_acl; 185 186 fail: 187 kfree(ext_acl); 188 return ERR_PTR(-EINVAL); 189} 190 191/* 192 * Inode operation get_posix_acl(). 193 * 194 * inode->i_mutex: down 195 * BKL held [before 2.5.x] 196 */ 197struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) 198{ 199 char *name, *value; 200 struct posix_acl *acl; 201 int size; 202 int retval; 203 204 acl = get_cached_acl(inode, type); 205 if (acl != ACL_NOT_CACHED) 206 return acl; 207 208 switch (type) { 209 case ACL_TYPE_ACCESS: 210 name = POSIX_ACL_XATTR_ACCESS; 211 break; 212 case ACL_TYPE_DEFAULT: 213 name = POSIX_ACL_XATTR_DEFAULT; 214 break; 215 default: 216 BUG(); 217 } 218 219 size = reiserfs_xattr_get(inode, name, NULL, 0); 220 if (size < 0) { 221 if (size == -ENODATA || size == -ENOSYS) { 222 set_cached_acl(inode, type, NULL); 223 return NULL; 224 } 225 return ERR_PTR(size); 226 } 227 228 value = kmalloc(size, GFP_NOFS); 229 if (!value) 230 return ERR_PTR(-ENOMEM); 231 232 retval = reiserfs_xattr_get(inode, name, value, size); 233 if (retval == -ENODATA || retval == -ENOSYS) { 234 /* This shouldn't actually happen as it should have 235 been caught above.. but just in case */ 236 acl = NULL; 237 } else if (retval < 0) { 238 acl = ERR_PTR(retval); 239 } else { 240 acl = posix_acl_from_disk(value, retval); 241 } 242 if (!IS_ERR(acl)) 243 set_cached_acl(inode, type, acl); 244 245 kfree(value); 246 return acl; 247} 248 249/* 250 * Inode operation set_posix_acl(). 251 * 252 * inode->i_mutex: down 253 * BKL held [before 2.5.x] 254 */ 255static int 256reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, 257 int type, struct posix_acl *acl) 258{ 259 char *name; 260 void *value = NULL; 261 size_t size = 0; 262 int error; 263 264 if (S_ISLNK(inode->i_mode)) 265 return -EOPNOTSUPP; 266 267 switch (type) { 268 case ACL_TYPE_ACCESS: 269 name = POSIX_ACL_XATTR_ACCESS; 270 if (acl) { 271 mode_t mode = inode->i_mode; 272 error = posix_acl_equiv_mode(acl, &mode); 273 if (error < 0) 274 return error; 275 else { 276 inode->i_mode = mode; 277 if (error == 0) 278 acl = NULL; 279 } 280 } 281 break; 282 case ACL_TYPE_DEFAULT: 283 name = POSIX_ACL_XATTR_DEFAULT; 284 if (!S_ISDIR(inode->i_mode)) 285 return acl ? -EACCES : 0; 286 break; 287 default: 288 return -EINVAL; 289 } 290 291 if (acl) { 292 value = posix_acl_to_disk(acl, &size); 293 if (IS_ERR(value)) 294 return (int)PTR_ERR(value); 295 } 296 297 error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0); 298 299 /* 300 * Ensure that the inode gets dirtied if we're only using 301 * the mode bits and an old ACL didn't exist. We don't need 302 * to check if the inode is hashed here since we won't get 303 * called by reiserfs_inherit_default_acl(). 304 */ 305 if (error == -ENODATA) { 306 error = 0; 307 if (type == ACL_TYPE_ACCESS) { 308 inode->i_ctime = CURRENT_TIME_SEC; 309 mark_inode_dirty(inode); 310 } 311 } 312 313 kfree(value); 314 315 if (!error) 316 set_cached_acl(inode, type, acl); 317 318 return error; 319} 320 321/* dir->i_mutex: locked, 322 * inode is new and not released into the wild yet */ 323int 324reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th, 325 struct inode *dir, struct dentry *dentry, 326 struct inode *inode) 327{ 328 struct posix_acl *acl; 329 int err = 0; 330 331 /* ACLs only get applied to files and directories */ 332 if (S_ISLNK(inode->i_mode)) 333 return 0; 334 335 /* ACLs can only be used on "new" objects, so if it's an old object 336 * there is nothing to inherit from */ 337 if (get_inode_sd_version(dir) == STAT_DATA_V1) 338 goto apply_umask; 339 340 /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This 341 * would be useless since permissions are ignored, and a pain because 342 * it introduces locking cycles */ 343 if (IS_PRIVATE(dir)) { 344 inode->i_flags |= S_PRIVATE; 345 goto apply_umask; 346 } 347 348 acl = reiserfs_get_acl(dir, ACL_TYPE_DEFAULT); 349 if (IS_ERR(acl)) 350 return PTR_ERR(acl); 351 352 if (acl) { 353 struct posix_acl *acl_copy; 354 mode_t mode = inode->i_mode; 355 int need_acl; 356 357 /* Copy the default ACL to the default ACL of a new directory */ 358 if (S_ISDIR(inode->i_mode)) { 359 err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT, 360 acl); 361 if (err) 362 goto cleanup; 363 } 364 365 /* Now we reconcile the new ACL and the mode, 366 potentially modifying both */ 367 acl_copy = posix_acl_clone(acl, GFP_NOFS); 368 if (!acl_copy) { 369 err = -ENOMEM; 370 goto cleanup; 371 } 372 373 need_acl = posix_acl_create_masq(acl_copy, &mode); 374 if (need_acl >= 0) { 375 if (mode != inode->i_mode) { 376 inode->i_mode = mode; 377 } 378 379 /* If we need an ACL.. */ 380 if (need_acl > 0) { 381 err = reiserfs_set_acl(th, inode, 382 ACL_TYPE_ACCESS, 383 acl_copy); 384 if (err) 385 goto cleanup_copy; 386 } 387 } 388 cleanup_copy: 389 posix_acl_release(acl_copy); 390 cleanup: 391 posix_acl_release(acl); 392 } else { 393 apply_umask: 394 /* no ACL, apply umask */ 395 inode->i_mode &= ~current_umask(); 396 } 397 398 return err; 399} 400 401/* This is used to cache the default acl before a new object is created. 402 * The biggest reason for this is to get an idea of how many blocks will 403 * actually be required for the create operation if we must inherit an ACL. 404 * An ACL write can add up to 3 object creations and an additional file write 405 * so we'd prefer not to reserve that many blocks in the journal if we can. 406 * It also has the advantage of not loading the ACL with a transaction open, 407 * this may seem silly, but if the owner of the directory is doing the 408 * creation, the ACL may not be loaded since the permissions wouldn't require 409 * it. 410 * We return the number of blocks required for the transaction. 411 */ 412int reiserfs_cache_default_acl(struct inode *inode) 413{ 414 struct posix_acl *acl; 415 int nblocks = 0; 416 417 if (IS_PRIVATE(inode)) 418 return 0; 419 420 acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); 421 422 if (acl && !IS_ERR(acl)) { 423 int size = reiserfs_acl_size(acl->a_count); 424 425 /* Other xattrs can be created during inode creation. We don't 426 * want to claim too many blocks, so we check to see if we 427 * we need to create the tree to the xattrs, and then we 428 * just want two files. */ 429 nblocks = reiserfs_xattr_jcreate_nblocks(inode); 430 nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb); 431 432 REISERFS_I(inode)->i_flags |= i_has_xattr_dir; 433 434 /* We need to account for writes + bitmaps for two files */ 435 nblocks += reiserfs_xattr_nblocks(inode, size) * 4; 436 posix_acl_release(acl); 437 } 438 439 return nblocks; 440} 441 442int reiserfs_acl_chmod(struct inode *inode) 443{ 444 struct posix_acl *acl, *clone; 445 int error; 446 447 if (S_ISLNK(inode->i_mode)) 448 return -EOPNOTSUPP; 449 450 if (get_inode_sd_version(inode) == STAT_DATA_V1 || 451 !reiserfs_posixacl(inode->i_sb)) { 452 return 0; 453 } 454 455 acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); 456 if (!acl) 457 return 0; 458 if (IS_ERR(acl)) 459 return PTR_ERR(acl); 460 clone = posix_acl_clone(acl, GFP_NOFS); 461 posix_acl_release(acl); 462 if (!clone) 463 return -ENOMEM; 464 error = posix_acl_chmod_masq(clone, inode->i_mode); 465 if (!error) { 466 struct reiserfs_transaction_handle th; 467 size_t size = reiserfs_xattr_nblocks(inode, 468 reiserfs_acl_size(clone->a_count)); 469 reiserfs_write_lock(inode->i_sb); 470 error = journal_begin(&th, inode->i_sb, size * 2); 471 if (!error) { 472 int error2; 473 error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, 474 clone); 475 error2 = journal_end(&th, inode->i_sb, size * 2); 476 if (error2) 477 error = error2; 478 } 479 reiserfs_write_unlock(inode->i_sb); 480 } 481 posix_acl_release(clone); 482 return error; 483} 484 485static int 486posix_acl_access_get(struct inode *inode, const char *name, 487 void *buffer, size_t size) 488{ 489 if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1) 490 return -EINVAL; 491 return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size); 492} 493 494static int 495posix_acl_access_set(struct inode *inode, const char *name, 496 const void *value, size_t size, int flags) 497{ 498 if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1) 499 return -EINVAL; 500 return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size); 501} 502 503static size_t posix_acl_access_list(struct inode *inode, char *list, 504 size_t list_size, const char *name, 505 size_t name_len) 506{ 507 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS); 508 if (!reiserfs_posixacl(inode->i_sb)) 509 return 0; 510 if (list && size <= list_size) 511 memcpy(list, POSIX_ACL_XATTR_ACCESS, size); 512 return size; 513} 514 515struct xattr_handler reiserfs_posix_acl_access_handler = { 516 .prefix = POSIX_ACL_XATTR_ACCESS, 517 .get = posix_acl_access_get, 518 .set = posix_acl_access_set, 519 .list = posix_acl_access_list, 520}; 521 522static int 523posix_acl_default_get(struct inode *inode, const char *name, 524 void *buffer, size_t size) 525{ 526 if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1) 527 return -EINVAL; 528 return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size); 529} 530 531static int 532posix_acl_default_set(struct inode *inode, const char *name, 533 const void *value, size_t size, int flags) 534{ 535 if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1) 536 return -EINVAL; 537 return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size); 538} 539 540static size_t posix_acl_default_list(struct inode *inode, char *list, 541 size_t list_size, const char *name, 542 size_t name_len) 543{ 544 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT); 545 if (!reiserfs_posixacl(inode->i_sb)) 546 return 0; 547 if (list && size <= list_size) 548 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size); 549 return size; 550} 551 552struct xattr_handler reiserfs_posix_acl_default_handler = { 553 .prefix = POSIX_ACL_XATTR_DEFAULT, 554 .get = posix_acl_default_get, 555 .set = posix_acl_default_set, 556 .list = posix_acl_default_list, 557};