Unified · Split
| @@ -127,14 +127,15 @@ This is because process A's keyrings can't simply be attached to · 126 unmodified lines | ||
| 127 | 127 | of them, and (b) it requires the same UID/GID/Groups all the way through. |
| 128 | 128 | |
| 129 | 129 | |
| 130 | −====================== | |
| 131 | −NEGATIVE INSTANTIATION | |
| 132 | −====================== | |
| 130 | +==================================== | |
| 131 | +NEGATIVE INSTANTIATION AND REJECTION | |
| 132 | +==================================== | |
| 133 | 133 | |
| 134 | 134 | Rather than instantiating a key, it is possible for the possessor of an |
| 135 | 135 | authorisation key to negatively instantiate a key that's under construction. |
| 136 | 136 | This is a short duration placeholder that causes any attempt at re-requesting |
| 137 | −the key whilst it exists to fail with error ENOKEY. | |
| 137 | +the key whilst it exists to fail with error ENOKEY if negated or the specified | |
| 138 | +error if rejected. | |
| 138 | 139 | |
| 139 | 140 | This is provided to prevent excessive repeated spawning of /sbin/request-key |
| 140 | 141 | processes for a key that will never be obtainable. |
| @@ -637,6 +637,9 @@ The keyctl syscall functions are: · 636 unmodified lines | ||
| 637 | 637 | long keyctl(KEYCTL_INSTANTIATE, key_serial_t key, |
| 638 | 638 | const void *payload, size_t plen, |
| 639 | 639 | key_serial_t keyring); |
| 640 | + long keyctl(KEYCTL_INSTANTIATE_IOV, key_serial_t key, | |
| 641 | + const struct iovec *payload_iov, unsigned ioc, | |
| 642 | + key_serial_t keyring); | |
| 640 | 643 | |
| 641 | 644 | If the kernel calls back to userspace to complete the instantiation of a |
| 642 | 645 | key, userspace should use this call to supply data for the key before the |
| @@ -652,11 +655,16 @@ The keyctl syscall functions are: · 9 unmodified lines | ||
| 652 | 655 | |
| 653 | 656 | The payload and plen arguments describe the payload data as for add_key(). |
| 654 | 657 | |
| 658 | + The payload_iov and ioc arguments describe the payload data in an iovec | |
| 659 | + array instead of a single buffer. | |
| 660 | + | |
| 655 | 661 | |
| 656 | 662 | (*) Negatively instantiate a partially constructed key. |
| 657 | 663 | |
| 658 | 664 | long keyctl(KEYCTL_NEGATE, key_serial_t key, |
| 659 | 665 | unsigned timeout, key_serial_t keyring); |
| 666 | + long keyctl(KEYCTL_REJECT, key_serial_t key, | |
| 667 | + unsigned timeout, unsigned error, key_serial_t keyring); | |
| 660 | 668 | |
| 661 | 669 | If the kernel calls back to userspace to complete the instantiation of a |
| 662 | 670 | key, userspace should use this call mark the key as negative before the |
| @@ -669,6 +677,10 @@ The keyctl syscall functions are: · 6 unmodified lines | ||
| 669 | 677 | that keyring, however all the constraints applying in KEYCTL_LINK apply in |
| 670 | 678 | this case too. |
| 671 | 679 | |
| 680 | + If the key is rejected, future searches for it will return the specified | |
| 681 | + error code until the rejected key expires. Negating the key is the same | |
| 682 | + as rejecting the key with ENOKEY as the error code. | |
| 683 | + | |
| 672 | 684 | |
| 673 | 685 | (*) Set the default request-key destination keyring. |
| 674 | 686 | |
| @@ -1062,6 +1074,13 @@ The structure has a number of fields, some of which are mandatory: · 387 unmodified lines | ||
| 1062 | 1074 | viable. |
| 1063 | 1075 | |
| 1064 | 1076 | |
| 1077 | + (*) int (*vet_description)(const char *description); | |
| 1078 | + | |
| 1079 | + This optional method is called to vet a key description. If the key type | |
| 1080 | + doesn't approve of the key description, it may return an error, otherwise | |
| 1081 | + it should return 0. | |
| 1082 | + | |
| 1083 | + | |
| 1065 | 1084 | (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); |
| 1066 | 1085 | |
| 1067 | 1086 | This method is called to attach a payload to a key during construction. |
| @@ -1231,10 +1250,11 @@ hand the request off to (perhaps a path held in placed in another key by, for · 163 unmodified lines | ||
| 1231 | 1250 | example, the KDE desktop manager). |
| 1232 | 1251 | |
| 1233 | 1252 | The program (or whatever it calls) should finish construction of the key by |
| 1234 | −calling KEYCTL_INSTANTIATE, which also permits it to cache the key in one of | |
| 1235 | −the keyrings (probably the session ring) before returning. Alternatively, the | |
| 1236 | −key can be marked as negative with KEYCTL_NEGATE; this also permits the key to | |
| 1237 | −be cached in one of the keyrings. | |
| 1253 | +calling KEYCTL_INSTANTIATE or KEYCTL_INSTANTIATE_IOV, which also permits it to | |
| 1254 | +cache the key in one of the keyrings (probably the session ring) before | |
| 1255 | +returning. Alternatively, the key can be marked as negative with KEYCTL_NEGATE | |
| 1256 | +or KEYCTL_REJECT; this also permits the key to be cached in one of the | |
| 1257 | +keyrings. | |
| 1238 | 1258 | |
| 1239 | 1259 | If it returns with the key remaining in the unconstructed state, the key will |
| 1240 | 1260 | be marked as being negative, it will be added to the session keyring, and an |
| @@ -2138,6 +2138,11 @@ config SYSVIPC_COMPAT · 2137 unmodified lines | ||
| 2138 | 2138 | def_bool y |
| 2139 | 2139 | depends on COMPAT && SYSVIPC |
| 2140 | 2140 | |
| 2141 | +config KEYS_COMPAT | |
| 2142 | + bool | |
| 2143 | + depends on COMPAT && KEYS | |
| 2144 | + default y | |
| 2145 | + | |
| 2141 | 2146 | endmenu |
| 2142 | 2147 | |
| 2143 | 2148 | |
| @@ -90,13 +90,14 @@ static noinline int cow_file_range(struct inode *inode, · 89 unmodified lines | ||
| 90 | 90 | unsigned long *nr_written, int unlock); |
| 91 | 91 | |
| 92 | 92 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, |
| 93 | − struct inode *inode, struct inode *dir) | |
| 93 | + struct inode *inode, struct inode *dir, | |
| 94 | + const struct qstr *qstr) | |
| 94 | 95 | { |
| 95 | 96 | int err; |
| 96 | 97 | |
| 97 | 98 | err = btrfs_init_acl(trans, inode, dir); |
| 98 | 99 | if (!err) |
| 99 | − err = btrfs_xattr_security_init(trans, inode, dir); | |
| 100 | + err = btrfs_xattr_security_init(trans, inode, dir, qstr); | |
| 100 | 101 | return err; |
| 101 | 102 | } |
| 102 | 103 | |
| @@ -4704,7 +4705,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, · 4601 unmodified lines | ||
| 4704 | 4705 | if (IS_ERR(inode)) |
| 4705 | 4706 | goto out_unlock; |
| 4706 | 4707 | |
| 4707 | − err = btrfs_init_inode_security(trans, inode, dir); | |
| 4708 | + err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); | |
| 4708 | 4709 | if (err) { |
| 4709 | 4710 | drop_inode = 1; |
| 4710 | 4711 | goto out_unlock; |
| @@ -4765,7 +4766,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, · 54 unmodified lines | ||
| 4765 | 4766 | if (IS_ERR(inode)) |
| 4766 | 4767 | goto out_unlock; |
| 4767 | 4768 | |
| 4768 | − err = btrfs_init_inode_security(trans, inode, dir); | |
| 4769 | + err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); | |
| 4769 | 4770 | if (err) { |
| 4770 | 4771 | drop_inode = 1; |
| 4771 | 4772 | goto out_unlock; |
| @@ -4894,7 +4895,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) · 122 unmodified lines | ||
| 4894 | 4895 | |
| 4895 | 4896 | drop_on_err = 1; |
| 4896 | 4897 | |
| 4897 | − err = btrfs_init_inode_security(trans, inode, dir); | |
| 4898 | + err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); | |
| 4898 | 4899 | if (err) |
| 4899 | 4900 | goto out_fail; |
| 4900 | 4901 | |
| @@ -7106,7 +7107,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, · 2205 unmodified lines | ||
| 7106 | 7107 | if (IS_ERR(inode)) |
| 7107 | 7108 | goto out_unlock; |
| 7108 | 7109 | |
| 7109 | − err = btrfs_init_inode_security(trans, inode, dir); | |
| 7110 | + err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); | |
| 7110 | 7111 | if (err) { |
| 7111 | 7112 | drop_inode = 1; |
| 7112 | 7113 | goto out_unlock; |
| @@ -370,7 +370,8 @@ int btrfs_removexattr(struct dentry *dentry, const char *name) · 369 unmodified lines | ||
| 370 | 370 | } |
| 371 | 371 | |
| 372 | 372 | int btrfs_xattr_security_init(struct btrfs_trans_handle *trans, |
| 373 | − struct inode *inode, struct inode *dir) | |
| 373 | + struct inode *inode, struct inode *dir, | |
| 374 | + const struct qstr *qstr) | |
| 374 | 375 | { |
| 375 | 376 | int err; |
| 376 | 377 | size_t len; |
| @@ -378,7 +379,8 @@ int btrfs_xattr_security_init(struct btrfs_trans_handle *trans, · 1 unmodified line | ||
| 378 | 379 | char *suffix; |
| 379 | 380 | char *name; |
| 380 | 381 | |
| 381 | − err = security_inode_init_security(inode, dir, &suffix, &value, &len); | |
| 382 | + err = security_inode_init_security(inode, dir, qstr, &suffix, &value, | |
| 383 | + &len); | |
| 382 | 384 | if (err) { |
| 383 | 385 | if (err == -EOPNOTSUPP) |
| 384 | 386 | return 0; |
| @@ -37,6 +37,7 @@ extern int btrfs_setxattr(struct dentry *dentry, const char *name, · 36 unmodified lines | ||
| 37 | 37 | extern int btrfs_removexattr(struct dentry *dentry, const char *name); |
| 38 | 38 | |
| 39 | 39 | extern int btrfs_xattr_security_init(struct btrfs_trans_handle *trans, |
| 40 | − struct inode *inode, struct inode *dir); | |
| 40 | + struct inode *inode, struct inode *dir, | |
| 41 | + const struct qstr *qstr); | |
| 41 | 42 | |
| 42 | 43 | #endif /* __XATTR__ */ |
| @@ -275,6 +275,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, · 274 unmodified lines | ||
| 275 | 275 | bool preemptive) |
| 276 | 276 | { |
| 277 | 277 | struct dentry *grave, *trap; |
| 278 | + struct path path, path_to_graveyard; | |
| 278 | 279 | char nbuffer[8 + 8 + 1]; |
| 279 | 280 | int ret; |
| 280 | 281 | |
| @@ -287,10 +288,18 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, · 6 unmodified lines | ||
| 287 | 288 | /* non-directories can just be unlinked */ |
| 288 | 289 | if (!S_ISDIR(rep->d_inode->i_mode)) { |
| 289 | 290 | _debug("unlink stale object"); |
| 290 | − ret = vfs_unlink(dir->d_inode, rep); | |
| 291 | 291 | |
| 292 | − if (preemptive) | |
| 293 | − cachefiles_mark_object_buried(cache, rep); | |
| 292 | + path.mnt = cache->mnt; | |
| 293 | + path.dentry = dir; | |
| 294 | + ret = security_path_unlink(&path, rep); | |
| 295 | + if (ret < 0) { | |
| 296 | + cachefiles_io_error(cache, "Unlink security error"); | |
| 297 | + } else { | |
| 298 | + ret = vfs_unlink(dir->d_inode, rep); | |
| 299 | + | |
| 300 | + if (preemptive) | |
| 301 | + cachefiles_mark_object_buried(cache, rep); | |
| 302 | + } | |
| 294 | 303 | |
| 295 | 304 | mutex_unlock(&dir->d_inode->i_mutex); |
| 296 | 305 | |
| @@ -379,12 +388,23 @@ try_again: · 82 unmodified lines | ||
| 379 | 388 | } |
| 380 | 389 | |
| 381 | 390 | /* attempt the rename */ |
| 382 | − ret = vfs_rename(dir->d_inode, rep, cache->graveyard->d_inode, grave); | |
| 383 | − if (ret != 0 && ret != -ENOMEM) | |
| 384 | − cachefiles_io_error(cache, "Rename failed with error %d", ret); | |
| 391 | + path.mnt = cache->mnt; | |
| 392 | + path.dentry = dir; | |
| 393 | + path_to_graveyard.mnt = cache->mnt; | |
| 394 | + path_to_graveyard.dentry = cache->graveyard; | |
| 395 | + ret = security_path_rename(&path, rep, &path_to_graveyard, grave); | |
| 396 | + if (ret < 0) { | |
| 397 | + cachefiles_io_error(cache, "Rename security error %d", ret); | |
| 398 | + } else { | |
| 399 | + ret = vfs_rename(dir->d_inode, rep, | |
| 400 | + cache->graveyard->d_inode, grave); | |
| 401 | + if (ret != 0 && ret != -ENOMEM) | |
| 402 | + cachefiles_io_error(cache, | |
| 403 | + "Rename failed with error %d", ret); | |
| 385 | 404 | |
| 386 | − if (preemptive) | |
| 387 | − cachefiles_mark_object_buried(cache, rep); | |
| 405 | + if (preemptive) | |
| 406 | + cachefiles_mark_object_buried(cache, rep); | |
| 407 | + } | |
| 388 | 408 | |
| 389 | 409 | unlock_rename(cache->graveyard, dir); |
| 390 | 410 | dput(grave); |
| @@ -448,6 +468,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, · 57 unmodified lines | ||
| 448 | 468 | { |
| 449 | 469 | struct cachefiles_cache *cache; |
| 450 | 470 | struct dentry *dir, *next = NULL; |
| 471 | + struct path path; | |
| 451 | 472 | unsigned long start; |
| 452 | 473 | const char *name; |
| 453 | 474 | int ret, nlen; |
| @@ -458,6 +479,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, · 4 unmodified lines | ||
| 458 | 479 | |
| 459 | 480 | cache = container_of(parent->fscache.cache, |
| 460 | 481 | struct cachefiles_cache, cache); |
| 482 | + path.mnt = cache->mnt; | |
| 461 | 483 | |
| 462 | 484 | ASSERT(parent->dentry); |
| 463 | 485 | ASSERT(parent->dentry->d_inode); |
| @@ -511,6 +533,10 @@ lookup_again: · 47 unmodified lines | ||
| 511 | 533 | if (ret < 0) |
| 512 | 534 | goto create_error; |
| 513 | 535 | |
| 536 | + path.dentry = dir; | |
| 537 | + ret = security_path_mkdir(&path, next, 0); | |
| 538 | + if (ret < 0) | |
| 539 | + goto create_error; | |
| 514 | 540 | start = jiffies; |
| 515 | 541 | ret = vfs_mkdir(dir->d_inode, next, 0); |
| 516 | 542 | cachefiles_hist(cachefiles_mkdir_histogram, start); |
| @@ -536,6 +562,10 @@ lookup_again: · 19 unmodified lines | ||
| 536 | 562 | if (ret < 0) |
| 537 | 563 | goto create_error; |
| 538 | 564 | |
| 565 | + path.dentry = dir; | |
| 566 | + ret = security_path_mknod(&path, next, S_IFREG, 0); | |
| 567 | + if (ret < 0) | |
| 568 | + goto create_error; | |
| 539 | 569 | start = jiffies; |
| 540 | 570 | ret = vfs_create(dir->d_inode, next, S_IFREG, NULL); |
| 541 | 571 | cachefiles_hist(cachefiles_create_histogram, start); |
| @@ -692,6 +722,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, · 150 unmodified lines | ||
| 692 | 722 | { |
| 693 | 723 | struct dentry *subdir; |
| 694 | 724 | unsigned long start; |
| 725 | + struct path path; | |
| 695 | 726 | int ret; |
| 696 | 727 | |
| 697 | 728 | _enter(",,%s", dirname); |
| @@ -719,6 +750,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, · 21 unmodified lines | ||
| 719 | 750 | |
| 720 | 751 | _debug("attempt mkdir"); |
| 721 | 752 | |
| 753 | + path.mnt = cache->mnt; | |
| 754 | + path.dentry = dir; | |
| 755 | + ret = security_path_mkdir(&path, subdir, 0700); | |
| 756 | + if (ret < 0) | |
| 757 | + goto mkdir_error; | |
| 722 | 758 | ret = vfs_mkdir(dir->d_inode, subdir, 0700); |
| 723 | 759 | if (ret < 0) |
| 724 | 760 | goto mkdir_error; |
| @@ -110,7 +110,7 @@ extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **); · 109 unmodified lines | ||
| 110 | 110 | extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *, int); |
| 111 | 111 | |
| 112 | 112 | /* ialloc.c */ |
| 113 | −extern struct inode * ext2_new_inode (struct inode *, int); | |
| 113 | +extern struct inode * ext2_new_inode (struct inode *, int, const struct qstr *); | |
| 114 | 114 | extern void ext2_free_inode (struct inode *); |
| 115 | 115 | extern unsigned long ext2_count_free_inodes (struct super_block *); |
| 116 | 116 | extern void ext2_check_inodes_bitmap (struct super_block *); |
| @@ -429,7 +429,8 @@ found: · 428 unmodified lines | ||
| 429 | 429 | return group; |
| 430 | 430 | } |
| 431 | 431 | |
| 432 | −struct inode *ext2_new_inode(struct inode *dir, int mode) | |
| 432 | +struct inode *ext2_new_inode(struct inode *dir, int mode, | |
| 433 | + const struct qstr *qstr) | |
| 433 | 434 | { |
| 434 | 435 | struct super_block *sb; |
| 435 | 436 | struct buffer_head *bitmap_bh = NULL; |
| @@ -585,7 +586,7 @@ got: · 149 unmodified lines | ||
| 585 | 586 | if (err) |
| 586 | 587 | goto fail_free_drop; |
| 587 | 588 | |
| 588 | − err = ext2_init_security(inode,dir); | |
| 589 | + err = ext2_init_security(inode, dir, qstr); | |
| 589 | 590 | if (err) |
| 590 | 591 | goto fail_free_drop; |
| 591 | 592 | |
| @@ -104,7 +104,7 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st · 103 unmodified lines | ||
| 104 | 104 | |
| 105 | 105 | dquot_initialize(dir); |
| 106 | 106 | |
| 107 | − inode = ext2_new_inode(dir, mode); | |
| 107 | + inode = ext2_new_inode(dir, mode, &dentry->d_name); | |
| 108 | 108 | if (IS_ERR(inode)) |
| 109 | 109 | return PTR_ERR(inode); |
| 110 | 110 | |
| @@ -133,7 +133,7 @@ static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_ · 22 unmodified lines | ||
| 133 | 133 | |
| 134 | 134 | dquot_initialize(dir); |
| 135 | 135 | |
| 136 | − inode = ext2_new_inode (dir, mode); | |
| 136 | + inode = ext2_new_inode (dir, mode, &dentry->d_name); | |
| 137 | 137 | err = PTR_ERR(inode); |
| 138 | 138 | if (!IS_ERR(inode)) { |
| 139 | 139 | init_special_inode(inode, inode->i_mode, rdev); |
| @@ -159,7 +159,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry, · 19 unmodified lines | ||
| 159 | 159 | |
| 160 | 160 | dquot_initialize(dir); |
| 161 | 161 | |
| 162 | − inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO); | |
| 162 | + inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO, &dentry->d_name); | |
| 163 | 163 | err = PTR_ERR(inode); |
| 164 | 164 | if (IS_ERR(inode)) |
| 165 | 165 | goto out; |
| @@ -230,7 +230,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) · 64 unmodified lines | ||
| 230 | 230 | |
| 231 | 231 | inode_inc_link_count(dir); |
| 232 | 232 | |
| 233 | − inode = ext2_new_inode (dir, S_IFDIR | mode); | |
| 233 | + inode = ext2_new_inode(dir, S_IFDIR | mode, &dentry->d_name); | |
| 234 | 234 | err = PTR_ERR(inode); |
| 235 | 235 | if (IS_ERR(inode)) |
| 236 | 236 | goto out_dir; |
| @@ -116,9 +116,11 @@ exit_ext2_xattr(void) · 115 unmodified lines | ||
| 116 | 116 | # endif /* CONFIG_EXT2_FS_XATTR */ |
| 117 | 117 | |
| 118 | 118 | #ifdef CONFIG_EXT2_FS_SECURITY |
| 119 | −extern int ext2_init_security(struct inode *inode, struct inode *dir); | |
| 119 | +extern int ext2_init_security(struct inode *inode, struct inode *dir, | |
| 120 | + const struct qstr *qstr); | |
| 120 | 121 | #else |
| 121 | −static inline int ext2_init_security(struct inode *inode, struct inode *dir) | |
| 122 | +static inline int ext2_init_security(struct inode *inode, struct inode *dir, | |
| 123 | + const struct qstr *qstr) | |
| 122 | 124 | { |
| 123 | 125 | return 0; |
| 124 | 126 | } |
| @@ -47,14 +47,15 @@ ext2_xattr_security_set(struct dentry *dentry, const char *name, · 46 unmodified lines | ||
| 47 | 47 | } |
| 48 | 48 | |
| 49 | 49 | int |
| 50 | −ext2_init_security(struct inode *inode, struct inode *dir) | |
| 50 | +ext2_init_security(struct inode *inode, struct inode *dir, | |
| 51 | + const struct qstr *qstr) | |
| 51 | 52 | { |
| 52 | 53 | int err; |
| 53 | 54 | size_t len; |
| 54 | 55 | void *value; |
| 55 | 56 | char *name; |
| 56 | 57 | |
| 57 | − err = security_inode_init_security(inode, dir, &name, &value, &len); | |
| 58 | + err = security_inode_init_security(inode, dir, qstr, &name, &value, &len); | |
| 58 | 59 | if (err) { |
| 59 | 60 | if (err == -EOPNOTSUPP) |
| 60 | 61 | return 0; |
| @@ -404,7 +404,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent) · 403 unmodified lines | ||
| 404 | 404 | * For other inodes, search forward from the parent directory's block |
| 405 | 405 | * group to find a free inode. |
| 406 | 406 | */ |
| 407 | −struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode) | |
| 407 | +struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, | |
| 408 | + const struct qstr *qstr, int mode) | |
| 408 | 409 | { |
| 409 | 410 | struct super_block *sb; |
| 410 | 411 | struct buffer_head *bitmap_bh = NULL; |
| @@ -589,7 +590,7 @@ got: · 178 unmodified lines | ||
| 589 | 590 | if (err) |
| 590 | 591 | goto fail_free_drop; |
| 591 | 592 | |
| 592 | − err = ext3_init_security(handle,inode, dir); | |
| 593 | + err = ext3_init_security(handle, inode, dir, qstr); | |
| 593 | 594 | if (err) |
| 594 | 595 | goto fail_free_drop; |
| 595 | 596 | |
| @@ -1710,7 +1710,7 @@ retry: · 1709 unmodified lines | ||
| 1710 | 1710 | if (IS_DIRSYNC(dir)) |
| 1711 | 1711 | handle->h_sync = 1; |
| 1712 | 1712 | |
| 1713 | − inode = ext3_new_inode (handle, dir, mode); | |
| 1713 | + inode = ext3_new_inode (handle, dir, &dentry->d_name, mode); | |
| 1714 | 1714 | err = PTR_ERR(inode); |
| 1715 | 1715 | if (!IS_ERR(inode)) { |
| 1716 | 1716 | inode->i_op = &ext3_file_inode_operations; |
| @@ -1746,7 +1746,7 @@ retry: · 29 unmodified lines | ||
| 1746 | 1746 | if (IS_DIRSYNC(dir)) |
| 1747 | 1747 | handle->h_sync = 1; |
| 1748 | 1748 | |
| 1749 | − inode = ext3_new_inode (handle, dir, mode); | |
| 1749 | + inode = ext3_new_inode (handle, dir, &dentry->d_name, mode); | |
| 1750 | 1750 | err = PTR_ERR(inode); |
| 1751 | 1751 | if (!IS_ERR(inode)) { |
| 1752 | 1752 | init_special_inode(inode, inode->i_mode, rdev); |
| @@ -1784,7 +1784,7 @@ retry: · 31 unmodified lines | ||
| 1784 | 1784 | if (IS_DIRSYNC(dir)) |
| 1785 | 1785 | handle->h_sync = 1; |
| 1786 | 1786 | |
| 1787 | − inode = ext3_new_inode (handle, dir, S_IFDIR | mode); | |
| 1787 | + inode = ext3_new_inode (handle, dir, &dentry->d_name, S_IFDIR | mode); | |
| 1788 | 1788 | err = PTR_ERR(inode); |
| 1789 | 1789 | if (IS_ERR(inode)) |
| 1790 | 1790 | goto out_stop; |
| @@ -2206,7 +2206,7 @@ retry: · 415 unmodified lines | ||
| 2206 | 2206 | if (IS_DIRSYNC(dir)) |
| 2207 | 2207 | handle->h_sync = 1; |
| 2208 | 2208 | |
| 2209 | − inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO); | |
| 2209 | + inode = ext3_new_inode (handle, dir, &dentry->d_name, S_IFLNK|S_IRWXUGO); | |
| 2210 | 2210 | err = PTR_ERR(inode); |
| 2211 | 2211 | if (IS_ERR(inode)) |
| 2212 | 2212 | goto out_stop; |
| @@ -128,10 +128,10 @@ exit_ext3_xattr(void) · 127 unmodified lines | ||
| 128 | 128 | |
| 129 | 129 | #ifdef CONFIG_EXT3_FS_SECURITY |
| 130 | 130 | extern int ext3_init_security(handle_t *handle, struct inode *inode, |
| 131 | − struct inode *dir); | |
| 131 | + struct inode *dir, const struct qstr *qstr); | |
| 132 | 132 | #else |
| 133 | 133 | static inline int ext3_init_security(handle_t *handle, struct inode *inode, |
| 134 | − struct inode *dir) | |
| 134 | + struct inode *dir, const struct qstr *qstr) | |
| 135 | 135 | { |
| 136 | 136 | return 0; |
| 137 | 137 | } |
| @@ -49,14 +49,15 @@ ext3_xattr_security_set(struct dentry *dentry, const char *name, · 48 unmodified lines | ||
| 49 | 49 | } |
| 50 | 50 | |
| 51 | 51 | int |
| 52 | −ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir) | |
| 52 | +ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir, | |
| 53 | + const struct qstr *qstr) | |
| 53 | 54 | { |
| 54 | 55 | int err; |
| 55 | 56 | size_t len; |
| 56 | 57 | void *value; |
| 57 | 58 | char *name; |
| 58 | 59 | |
| 59 | − err = security_inode_init_security(inode, dir, &name, &value, &len); | |
| 60 | + err = security_inode_init_security(inode, dir, qstr, &name, &value, &len); | |
| 60 | 61 | if (err) { |
| 61 | 62 | if (err == -EOPNOTSUPP) |
| 62 | 63 | return 0; |
| @@ -1042,7 +1042,7 @@ got: · 1041 unmodified lines | ||
| 1042 | 1042 | if (err) |
| 1043 | 1043 | goto fail_free_drop; |
| 1044 | 1044 | |
| 1045 | − err = ext4_init_security(handle, inode, dir); | |
| 1045 | + err = ext4_init_security(handle, inode, dir, qstr); | |
| 1046 | 1046 | if (err) |
| 1047 | 1047 | goto fail_free_drop; |
| 1048 | 1048 | |
| @@ -145,10 +145,10 @@ ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, · 144 unmodified lines | ||
| 145 | 145 | |
| 146 | 146 | #ifdef CONFIG_EXT4_FS_SECURITY |
| 147 | 147 | extern int ext4_init_security(handle_t *handle, struct inode *inode, |
| 148 | − struct inode *dir); | |
| 148 | + struct inode *dir, const struct qstr *qstr); | |
| 149 | 149 | #else |
| 150 | 150 | static inline int ext4_init_security(handle_t *handle, struct inode *inode, |
| 151 | − struct inode *dir) | |
| 151 | + struct inode *dir, const struct qstr *qstr) | |
| 152 | 152 | { |
| 153 | 153 | return 0; |
| 154 | 154 | } |
| @@ -49,14 +49,15 @@ ext4_xattr_security_set(struct dentry *dentry, const char *name, · 48 unmodified lines | ||
| 49 | 49 | } |
| 50 | 50 | |
| 51 | 51 | int |
| 52 | −ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir) | |
| 52 | +ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir, | |
| 53 | + const struct qstr *qstr) | |
| 53 | 54 | { |
| 54 | 55 | int err; |
| 55 | 56 | size_t len; |
| 56 | 57 | void *value; |
| 57 | 58 | char *name; |
| 58 | 59 | |
| 59 | − err = security_inode_init_security(inode, dir, &name, &value, &len); | |
| 60 | + err = security_inode_init_security(inode, dir, qstr, &name, &value, &len); | |
| 60 | 61 | if (err) { |
| 61 | 62 | if (err == -EOPNOTSUPP) |
| 62 | 63 | return 0; |
| @@ -190,7 +190,8 @@ struct file *alloc_file(struct path *path, fmode_t mode, · 189 unmodified lines | ||
| 190 | 190 | file_take_write(file); |
| 191 | 191 | WARN_ON(mnt_clone_write(path->mnt)); |
| 192 | 192 | } |
| 193 | − ima_counts_get(file); | |
| 193 | + if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | |
| 194 | + i_readcount_inc(path->dentry->d_inode); | |
| 194 | 195 | return file; |
| 195 | 196 | } |
| 196 | 197 | EXPORT_SYMBOL(alloc_file); |
| @@ -251,6 +252,8 @@ static void __fput(struct file *file) · 54 unmodified lines | ||
| 251 | 252 | fops_put(file->f_op); |
| 252 | 253 | put_pid(file->f_owner.pid); |
| 253 | 254 | file_sb_list_del(file); |
| 255 | + if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | |
| 256 | + i_readcount_dec(inode); | |
| 254 | 257 | if (file->f_mode & FMODE_WRITE) |
| 255 | 258 | drop_file_write_access(file); |
| 256 | 259 | file->f_path.dentry = NULL; |
| @@ -763,14 +763,15 @@ fail: · 762 unmodified lines | ||
| 763 | 763 | return error; |
| 764 | 764 | } |
| 765 | 765 | |
| 766 | −static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip) | |
| 766 | +static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip, | |
| 767 | + const struct qstr *qstr) | |
| 767 | 768 | { |
| 768 | 769 | int err; |
| 769 | 770 | size_t len; |
| 770 | 771 | void *value; |
| 771 | 772 | char *name; |
| 772 | 773 | |
| 773 | − err = security_inode_init_security(&ip->i_inode, &dip->i_inode, | |
| 774 | + err = security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr, | |
| 774 | 775 | &name, &value, &len); |
| 775 | 776 | |
| 776 | 777 | if (err) { |
| @@ -854,7 +855,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, · 77 unmodified lines | ||
| 854 | 855 | if (error) |
| 855 | 856 | goto fail_gunlock2; |
| 856 | 857 | |
| 857 | − error = gfs2_security_init(dip, GFS2_I(inode)); | |
| 858 | + error = gfs2_security_init(dip, GFS2_I(inode), name); | |
| 858 | 859 | if (error) |
| 859 | 860 | goto fail_gunlock2; |
| 860 | 861 | |
| @@ -215,8 +215,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, · 214 unmodified lines | ||
| 215 | 215 | no chance of AB-BA deadlock involving its f->sem). */ |
| 216 | 216 | mutex_unlock(&f->sem); |
| 217 | 217 | |
| 218 | − ret = jffs2_do_create(c, dir_f, f, ri, | |
| 219 | − dentry->d_name.name, dentry->d_name.len); | |
| 218 | + ret = jffs2_do_create(c, dir_f, f, ri, &dentry->d_name); | |
| 220 | 219 | if (ret) |
| 221 | 220 | goto fail; |
| 222 | 221 | |
| @@ -386,7 +385,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char · 163 unmodified lines | ||
| 386 | 385 | |
| 387 | 386 | jffs2_complete_reservation(c); |
| 388 | 387 | |
| 389 | − ret = jffs2_init_security(inode, dir_i); | |
| 388 | + ret = jffs2_init_security(inode, dir_i, &dentry->d_name); | |
| 390 | 389 | if (ret) |
| 391 | 390 | goto fail; |
| 392 | 391 | |
| @@ -530,7 +529,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) · 137 unmodified lines | ||
| 530 | 529 | |
| 531 | 530 | jffs2_complete_reservation(c); |
| 532 | 531 | |
| 533 | − ret = jffs2_init_security(inode, dir_i); | |
| 532 | + ret = jffs2_init_security(inode, dir_i, &dentry->d_name); | |
| 534 | 533 | if (ret) |
| 535 | 534 | goto fail; |
| 536 | 535 | |
| @@ -703,7 +702,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de · 166 unmodified lines | ||
| 703 | 702 | |
| 704 | 703 | jffs2_complete_reservation(c); |
| 705 | 704 | |
| 706 | − ret = jffs2_init_security(inode, dir_i); | |
| 705 | + ret = jffs2_init_security(inode, dir_i, &dentry->d_name); | |
| 707 | 706 | if (ret) |
| 708 | 707 | goto fail; |
| 709 | 708 | |
| @@ -401,7 +401,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, · 400 unmodified lines | ||
| 401 | 401 | struct jffs2_raw_inode *ri, unsigned char *buf, |
| 402 | 402 | uint32_t offset, uint32_t writelen, uint32_t *retlen); |
| 403 | 403 | int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, |
| 404 | − struct jffs2_raw_inode *ri, const char *name, int namelen); | |
| 404 | + struct jffs2_raw_inode *ri, const struct qstr *qstr); | |
| 405 | 405 | int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, |
| 406 | 406 | int namelen, struct jffs2_inode_info *dead_f, uint32_t time); |
| 407 | 407 | int jffs2_do_link(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, |
| @@ -23,14 +23,15 @@ · 22 unmodified lines | ||
| 23 | 23 | #include "nodelist.h" |
| 24 | 24 | |
| 25 | 25 | /* ---- Initial Security Label Attachment -------------- */ |
| 26 | −int jffs2_init_security(struct inode *inode, struct inode *dir) | |
| 26 | +int jffs2_init_security(struct inode *inode, struct inode *dir, | |
| 27 | + const struct qstr *qstr) | |
| 27 | 28 | { |
| 28 | 29 | int rc; |
| 29 | 30 | size_t len; |
| 30 | 31 | void *value; |
| 31 | 32 | char *name; |
| 32 | 33 | |
| 33 | − rc = security_inode_init_security(inode, dir, &name, &value, &len); | |
| 34 | + rc = security_inode_init_security(inode, dir, qstr, &name, &value, &len); | |
| 34 | 35 | if (rc) { |
| 35 | 36 | if (rc == -EOPNOTSUPP) |
| 36 | 37 | return 0; |
| @@ -424,7 +424,9 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, · 423 unmodified lines | ||
| 424 | 424 | return ret; |
| 425 | 425 | } |
| 426 | 426 | |
| 427 | −int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen) | |
| 427 | +int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, | |
| 428 | + struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, | |
| 429 | + const struct qstr *qstr) | |
| 428 | 430 | { |
| 429 | 431 | struct jffs2_raw_dirent *rd; |
| 430 | 432 | struct jffs2_full_dnode *fn; |
| @@ -466,15 +468,15 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str · 35 unmodified lines | ||
| 466 | 468 | mutex_unlock(&f->sem); |
| 467 | 469 | jffs2_complete_reservation(c); |
| 468 | 470 | |
| 469 | − ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode); | |
| 471 | + ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode, qstr); | |
| 470 | 472 | if (ret) |
| 471 | 473 | return ret; |
| 472 | 474 | ret = jffs2_init_acl_post(&f->vfs_inode); |
| 473 | 475 | if (ret) |
| 474 | 476 | return ret; |
| 475 | 477 | |
| 476 | − ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, | |
| 477 | − ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | |
| 478 | + ret = jffs2_reserve_space(c, sizeof(*rd)+qstr->len, &alloclen, | |
| 479 | + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(qstr->len)); | |
| 478 | 480 | |
| 479 | 481 | if (ret) { |
| 480 | 482 | /* Eep. */ |
| @@ -493,19 +495,19 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str · 12 unmodified lines | ||
| 493 | 495 | |
| 494 | 496 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| 495 | 497 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); |
| 496 | − rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); | |
| 498 | + rd->totlen = cpu_to_je32(sizeof(*rd) + qstr->len); | |
| 497 | 499 | rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); |
| 498 | 500 | |
| 499 | 501 | rd->pino = cpu_to_je32(dir_f->inocache->ino); |
| 500 | 502 | rd->version = cpu_to_je32(++dir_f->highest_version); |
| 501 | 503 | rd->ino = ri->ino; |
| 502 | 504 | rd->mctime = ri->ctime; |
| 503 | − rd->nsize = namelen; | |
| 505 | + rd->nsize = qstr->len; | |
| 504 | 506 | rd->type = DT_REG; |
| 505 | 507 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
| 506 | − rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); | |
| 508 | + rd->name_crc = cpu_to_je32(crc32(0, qstr->name, qstr->len)); | |
| 507 | 509 | |
| 508 | − fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL); | |
| 510 | + fd = jffs2_write_dirent(c, dir_f, rd, qstr->name, qstr->len, ALLOC_NORMAL); | |
| 509 | 511 | |
| 510 | 512 | jffs2_free_raw_dirent(rd); |
| 511 | 513 | |
| @@ -121,10 +121,11 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); · 120 unmodified lines | ||
| 121 | 121 | #endif /* CONFIG_JFFS2_FS_XATTR */ |
| 122 | 122 | |
| 123 | 123 | #ifdef CONFIG_JFFS2_FS_SECURITY |
| 124 | −extern int jffs2_init_security(struct inode *inode, struct inode *dir); | |
| 124 | +extern int jffs2_init_security(struct inode *inode, struct inode *dir, | |
| 125 | + const struct qstr *qstr); | |
| 125 | 126 | extern const struct xattr_handler jffs2_security_xattr_handler; |
| 126 | 127 | #else |
| 127 | −#define jffs2_init_security(inode,dir) (0) | |
| 128 | +#define jffs2_init_security(inode,dir,qstr) (0) | |
| 128 | 129 | #endif /* CONFIG_JFFS2_FS_SECURITY */ |
| 129 | 130 | |
| 130 | 131 | #endif /* _JFFS2_FS_XATTR_H_ */ |
| @@ -62,10 +62,11 @@ extern ssize_t jfs_listxattr(struct dentry *, char *, size_t); · 61 unmodified lines | ||
| 62 | 62 | extern int jfs_removexattr(struct dentry *, const char *); |
| 63 | 63 | |
| 64 | 64 | #ifdef CONFIG_JFS_SECURITY |
| 65 | −extern int jfs_init_security(tid_t, struct inode *, struct inode *); | |
| 65 | +extern int jfs_init_security(tid_t, struct inode *, struct inode *, | |
| 66 | + const struct qstr *); | |
| 66 | 67 | #else |
| 67 | 68 | static inline int jfs_init_security(tid_t tid, struct inode *inode, |
| 68 | − struct inode *dir) | |
| 69 | + struct inode *dir, const struct qstr *qstr) | |
| 69 | 70 | { |
| 70 | 71 | return 0; |
| 71 | 72 | } |
| @@ -115,7 +115,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, · 114 unmodified lines | ||
| 115 | 115 | if (rc) |
| 116 | 116 | goto out3; |
| 117 | 117 | |
| 118 | − rc = jfs_init_security(tid, ip, dip); | |
| 118 | + rc = jfs_init_security(tid, ip, dip, &dentry->d_name); | |
| 119 | 119 | if (rc) { |
| 120 | 120 | txAbort(tid, 0); |
| 121 | 121 | goto out3; |
| @@ -253,7 +253,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) · 131 unmodified lines | ||
| 253 | 253 | if (rc) |
| 254 | 254 | goto out3; |
| 255 | 255 | |
| 256 | − rc = jfs_init_security(tid, ip, dip); | |
| 256 | + rc = jfs_init_security(tid, ip, dip, &dentry->d_name); | |
| 257 | 257 | if (rc) { |
| 258 | 258 | txAbort(tid, 0); |
| 259 | 259 | goto out3; |
| @@ -932,7 +932,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, · 672 unmodified lines | ||
| 932 | 932 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); |
| 933 | 933 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); |
| 934 | 934 | |
| 935 | − rc = jfs_init_security(tid, ip, dip); | |
| 935 | + rc = jfs_init_security(tid, ip, dip, &dentry->d_name); | |
| 936 | 936 | if (rc) |
| 937 | 937 | goto out3; |
| 938 | 938 | |
| @@ -1395,7 +1395,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, · 456 unmodified lines | ||
| 1395 | 1395 | if (rc) |
| 1396 | 1396 | goto out3; |
| 1397 | 1397 | |
| 1398 | − rc = jfs_init_security(tid, ip, dir); | |
| 1398 | + rc = jfs_init_security(tid, ip, dir, &dentry->d_name); | |
| 1399 | 1399 | if (rc) { |
| 1400 | 1400 | txAbort(tid, 0); |
| 1401 | 1401 | goto out3; |
| @@ -1091,7 +1091,8 @@ int jfs_removexattr(struct dentry *dentry, const char *name) · 1090 unmodified lines | ||
| 1091 | 1091 | } |
| 1092 | 1092 | |
| 1093 | 1093 | #ifdef CONFIG_JFS_SECURITY |
| 1094 | −int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir) | |
| 1094 | +int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir, | |
| 1095 | + const struct qstr *qstr) | |
| 1095 | 1096 | { |
| 1096 | 1097 | int rc; |
| 1097 | 1098 | size_t len; |
| @@ -1099,7 +1100,8 @@ int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir) · 1 unmodified line | ||
| 1099 | 1100 | char *suffix; |
| 1100 | 1101 | char *name; |
| 1101 | 1102 | |
| 1102 | − rc = security_inode_init_security(inode, dir, &suffix, &value, &len); | |
| 1103 | + rc = security_inode_init_security(inode, dir, qstr, &suffix, &value, | |
| 1104 | + &len); | |
| 1103 | 1105 | if (rc) { |
| 1104 | 1106 | if (rc == -EOPNOTSUPP) |
| 1105 | 1107 | return 0; |
| @@ -1767,6 +1767,10 @@ static int do_remount(struct path *path, int flags, int mnt_flags, · 1766 unmodified lines | ||
| 1767 | 1767 | if (path->dentry != path->mnt->mnt_root) |
| 1768 | 1768 | return -EINVAL; |
| 1769 | 1769 | |
| 1770 | + err = security_sb_remount(sb, data); | |
| 1771 | + if (err) | |
| 1772 | + return err; | |
| 1773 | + | |
| 1770 | 1774 | down_write(&sb->s_umount); |
| 1771 | 1775 | if (flags & MS_BIND) |
| 1772 | 1776 | err = change_mount_flags(path->mnt, flags); |
| @@ -293,7 +293,7 @@ static int ocfs2_mknod(struct inode *dir, · 292 unmodified lines | ||
| 293 | 293 | } |
| 294 | 294 | |
| 295 | 295 | /* get security xattr */ |
| 296 | − status = ocfs2_init_security_get(inode, dir, &si); | |
| 296 | + status = ocfs2_init_security_get(inode, dir, &dentry->d_name, &si); | |
| 297 | 297 | if (status) { |
| 298 | 298 | if (status == -EOPNOTSUPP) |
| 299 | 299 | si.enable = 0; |
| @@ -1665,7 +1665,7 @@ static int ocfs2_symlink(struct inode *dir, · 1365 unmodified lines | ||
| 1665 | 1665 | } |
| 1666 | 1666 | |
| 1667 | 1667 | /* get security xattr */ |
| 1668 | − status = ocfs2_init_security_get(inode, dir, &si); | |
| 1668 | + status = ocfs2_init_security_get(inode, dir, &dentry->d_name, &si); | |
| 1669 | 1669 | if (status) { |
| 1670 | 1670 | if (status == -EOPNOTSUPP) |
| 1671 | 1671 | si.enable = 0; |
| @@ -4328,7 +4328,8 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir, · 4327 unmodified lines | ||
| 4328 | 4328 | |
| 4329 | 4329 | /* If the security isn't preserved, we need to re-initialize them. */ |
| 4330 | 4330 | if (!preserve) { |
| 4331 | − error = ocfs2_init_security_and_acl(dir, new_orphan_inode); | |
| 4331 | + error = ocfs2_init_security_and_acl(dir, new_orphan_inode, | |
| 4332 | + &new_dentry->d_name); | |
| 4332 | 4333 | if (error) |
| 4333 | 4334 | mlog_errno(error); |
| 4334 | 4335 | } |
| @@ -7185,7 +7185,8 @@ out: · 7184 unmodified lines | ||
| 7185 | 7185 | * must not hold any lock expect i_mutex. |
| 7186 | 7186 | */ |
| 7187 | 7187 | int ocfs2_init_security_and_acl(struct inode *dir, |
| 7188 | − struct inode *inode) | |
| 7188 | + struct inode *inode, | |
| 7189 | + const struct qstr *qstr) | |
| 7189 | 7190 | { |
| 7190 | 7191 | int ret = 0; |
| 7191 | 7192 | struct buffer_head *dir_bh = NULL; |
| @@ -7193,7 +7194,7 @@ int ocfs2_init_security_and_acl(struct inode *dir, · 1 unmodified line | ||
| 7193 | 7194 | .enable = 1, |
| 7194 | 7195 | }; |
| 7195 | 7196 | |
| 7196 | − ret = ocfs2_init_security_get(inode, dir, &si); | |
| 7197 | + ret = ocfs2_init_security_get(inode, dir, qstr, &si); | |
| 7197 | 7198 | if (!ret) { |
| 7198 | 7199 | ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY, |
| 7199 | 7200 | si.name, si.value, si.value_len, |
| @@ -7261,13 +7262,14 @@ static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name, · 61 unmodified lines | ||
| 7261 | 7262 | |
| 7262 | 7263 | int ocfs2_init_security_get(struct inode *inode, |
| 7263 | 7264 | struct inode *dir, |
| 7265 | + const struct qstr *qstr, | |
| 7264 | 7266 | struct ocfs2_security_xattr_info *si) |
| 7265 | 7267 | { |
| 7266 | 7268 | /* check whether ocfs2 support feature xattr */ |
| 7267 | 7269 | if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb))) |
| 7268 | 7270 | return -EOPNOTSUPP; |
| 7269 | − return security_inode_init_security(inode, dir, &si->name, &si->value, | |
| 7270 | − &si->value_len); | |
| 7271 | + return security_inode_init_security(inode, dir, qstr, &si->name, | |
| 7272 | + &si->value, &si->value_len); | |
| 7271 | 7273 | } |
| 7272 | 7274 | |
| 7273 | 7275 | int ocfs2_init_security_set(handle_t *handle, |
| @@ -57,6 +57,7 @@ int ocfs2_has_inline_xattr_value_outside(struct inode *inode, · 56 unmodified lines | ||
| 57 | 57 | struct ocfs2_dinode *di); |
| 58 | 58 | int ocfs2_xattr_remove(struct inode *, struct buffer_head *); |
| 59 | 59 | int ocfs2_init_security_get(struct inode *, struct inode *, |
| 60 | + const struct qstr *, | |
| 60 | 61 | struct ocfs2_security_xattr_info *); |
| 61 | 62 | int ocfs2_init_security_set(handle_t *, struct inode *, |
| 62 | 63 | struct buffer_head *, |
| @@ -94,5 +95,6 @@ int ocfs2_reflink_xattrs(struct inode *old_inode, · 31 unmodified lines | ||
| 94 | 95 | struct buffer_head *new_bh, |
| 95 | 96 | bool preserve_security); |
| 96 | 97 | int ocfs2_init_security_and_acl(struct inode *dir, |
| 97 | − struct inode *inode); | |
| 98 | + struct inode *inode, | |
| 99 | + const struct qstr *qstr); | |
| 98 | 100 | #endif /* OCFS2_XATTR_H */ |
| @@ -701,7 +701,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, · 700 unmodified lines | ||
| 701 | 701 | if (error) |
| 702 | 702 | goto cleanup_all; |
| 703 | 703 | } |
| 704 | − ima_counts_get(f); | |
| 704 | + if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | |
| 705 | + i_readcount_inc(inode); | |
| 705 | 706 | |
| 706 | 707 | f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); |
| 707 | 708 | |
| @@ -32,7 +32,6 @@ static struct inode *proc_sys_make_inode(struct super_block *sb, · 31 unmodified lines | ||
| 32 | 32 | ei->sysctl_entry = table; |
| 33 | 33 | |
| 34 | 34 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
| 35 | − inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */ | |
| 36 | 35 | inode->i_mode = table->mode; |
| 37 | 36 | if (!table->child) { |
| 38 | 37 | inode->i_mode |= S_IFREG; |
| @@ -593,7 +593,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, · 592 unmodified lines | ||
| 593 | 593 | new_inode_init(inode, dir, mode); |
| 594 | 594 | |
| 595 | 595 | jbegin_count += reiserfs_cache_default_acl(dir); |
| 596 | − retval = reiserfs_security_init(dir, inode, &security); | |
| 596 | + retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); | |
| 597 | 597 | if (retval < 0) { |
| 598 | 598 | drop_new_inode(inode); |
| 599 | 599 | return retval; |
| @@ -667,7 +667,7 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode, · 67 unmodified lines | ||
| 667 | 667 | new_inode_init(inode, dir, mode); |
| 668 | 668 | |
| 669 | 669 | jbegin_count += reiserfs_cache_default_acl(dir); |
| 670 | − retval = reiserfs_security_init(dir, inode, &security); | |
| 670 | + retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); | |
| 671 | 671 | if (retval < 0) { |
| 672 | 672 | drop_new_inode(inode); |
| 673 | 673 | return retval; |
| @@ -747,7 +747,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) · 73 unmodified lines | ||
| 747 | 747 | new_inode_init(inode, dir, mode); |
| 748 | 748 | |
| 749 | 749 | jbegin_count += reiserfs_cache_default_acl(dir); |
| 750 | − retval = reiserfs_security_init(dir, inode, &security); | |
| 750 | + retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); | |
| 751 | 751 | if (retval < 0) { |
| 752 | 752 | drop_new_inode(inode); |
| 753 | 753 | return retval; |
| @@ -1032,7 +1032,8 @@ static int reiserfs_symlink(struct inode *parent_dir, · 278 unmodified lines | ||
| 1032 | 1032 | } |
| 1033 | 1033 | new_inode_init(inode, parent_dir, mode); |
| 1034 | 1034 | |
| 1035 | − retval = reiserfs_security_init(parent_dir, inode, &security); | |
| 1035 | + retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name, | |
| 1036 | + &security); | |
| 1036 | 1037 | if (retval < 0) { |
| 1037 | 1038 | drop_new_inode(inode); |
| 1038 | 1039 | return retval; |
| @@ -54,6 +54,7 @@ static size_t security_list(struct dentry *dentry, char *list, size_t list_len, · 53 unmodified lines | ||
| 54 | 54 | * of blocks needed for the transaction. If successful, reiserfs_security |
| 55 | 55 | * must be released using reiserfs_security_free when the caller is done. */ |
| 56 | 56 | int reiserfs_security_init(struct inode *dir, struct inode *inode, |
| 57 | + const struct qstr *qstr, | |
| 57 | 58 | struct reiserfs_security_handle *sec) |
| 58 | 59 | { |
| 59 | 60 | int blocks = 0; |
| @@ -65,7 +66,7 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode, · 5 unmodified lines | ||
| 65 | 66 | if (IS_PRIVATE(dir)) |
| 66 | 67 | return 0; |
| 67 | 68 | |
| 68 | − error = security_inode_init_security(inode, dir, &sec->name, | |
| 69 | + error = security_inode_init_security(inode, dir, qstr, &sec->name, | |
| 69 | 70 | &sec->value, &sec->length); |
| 70 | 71 | if (error) { |
| 71 | 72 | if (error == -EOPNOTSUPP) |
| @@ -102,7 +102,8 @@ xfs_mark_inode_dirty( · 101 unmodified lines | ||
| 102 | 102 | STATIC int |
| 103 | 103 | xfs_init_security( |
| 104 | 104 | struct inode *inode, |
| 105 | − struct inode *dir) | |
| 105 | + struct inode *dir, | |
| 106 | + const struct qstr *qstr) | |
| 106 | 107 | { |
| 107 | 108 | struct xfs_inode *ip = XFS_I(inode); |
| 108 | 109 | size_t length; |
| @@ -110,7 +111,7 @@ xfs_init_security( · 1 unmodified line | ||
| 110 | 111 | unsigned char *name; |
| 111 | 112 | int error; |
| 112 | 113 | |
| 113 | − error = security_inode_init_security(inode, dir, (char **)&name, | |
| 114 | + error = security_inode_init_security(inode, dir, qstr, (char **)&name, | |
| 114 | 115 | &value, &length); |
| 115 | 116 | if (error) { |
| 116 | 117 | if (error == -EOPNOTSUPP) |
| @@ -194,7 +195,7 @@ xfs_vn_mknod( · 77 unmodified lines | ||
| 194 | 195 | |
| 195 | 196 | inode = VFS_I(ip); |
| 196 | 197 | |
| 197 | − error = xfs_init_security(inode, dir); | |
| 198 | + error = xfs_init_security(inode, dir, &dentry->d_name); | |
| 198 | 199 | if (unlikely(error)) |
| 199 | 200 | goto out_cleanup_inode; |
| 200 | 201 | |
| @@ -367,7 +368,7 @@ xfs_vn_symlink( · 166 unmodified lines | ||
| 367 | 368 | |
| 368 | 369 | inode = VFS_I(cip); |
| 369 | 370 | |
| 370 | − error = xfs_init_security(inode, dir); | |
| 371 | + error = xfs_init_security(inode, dir, &dentry->d_name); | |
| 371 | 372 | if (unlikely(error)) |
| 372 | 373 | goto out_cleanup_inode; |
| 373 | 374 | |
| @@ -884,7 +884,8 @@ extern int ext3fs_dirhash(const char *name, int len, struct · 883 unmodified lines | ||
| 884 | 884 | dx_hash_info *hinfo); |
| 885 | 885 | |
| 886 | 886 | /* ialloc.c */ |
| 887 | −extern struct inode * ext3_new_inode (handle_t *, struct inode *, int); | |
| 887 | +extern struct inode * ext3_new_inode (handle_t *, struct inode *, | |
| 888 | + const struct qstr *, int); | |
| 888 | 889 | extern void ext3_free_inode (handle_t *, struct inode *); |
| 889 | 890 | extern struct inode * ext3_orphan_get (struct super_block *, unsigned long); |
| 890 | 891 | extern unsigned long ext3_count_free_inodes (struct super_block *); |
| @@ -798,8 +798,7 @@ struct inode { · 797 unmodified lines | ||
| 798 | 798 | #endif |
| 799 | 799 | |
| 800 | 800 | #ifdef CONFIG_IMA |
| 801 | − /* protected by i_lock */ | |
| 802 | − unsigned int i_readcount; /* struct files open RO */ | |
| 801 | + atomic_t i_readcount; /* struct files open RO */ | |
| 803 | 802 | #endif |
| 804 | 803 | atomic_t i_writecount; |
| 805 | 804 | #ifdef CONFIG_SECURITY |
| @@ -2200,6 +2199,26 @@ static inline void allow_write_access(struct file *file) · 1394 unmodified lines | ||
| 2200 | 2199 | if (file) |
| 2201 | 2200 | atomic_inc(&file->f_path.dentry->d_inode->i_writecount); |
| 2202 | 2201 | } |
| 2202 | +#ifdef CONFIG_IMA | |
| 2203 | +static inline void i_readcount_dec(struct inode *inode) | |
| 2204 | +{ | |
| 2205 | + BUG_ON(!atomic_read(&inode->i_readcount)); | |
| 2206 | + atomic_dec(&inode->i_readcount); | |
| 2207 | +} | |
| 2208 | +static inline void i_readcount_inc(struct inode *inode) | |
| 2209 | +{ | |
| 2210 | + atomic_inc(&inode->i_readcount); | |
| 2211 | +} | |
| 2212 | +#else | |
| 2213 | +static inline void i_readcount_dec(struct inode *inode) | |
| 2214 | +{ | |
| 2215 | + return; | |
| 2216 | +} | |
| 2217 | +static inline void i_readcount_inc(struct inode *inode) | |
| 2218 | +{ | |
| 2219 | + return; | |
| 2220 | +} | |
| 2221 | +#endif | |
| 2203 | 2222 | extern int do_pipe_flags(int *, int); |
| 2204 | 2223 | extern struct file *create_read_pipe(struct file *f, int flags); |
| 2205 | 2224 | extern struct file *create_write_pipe(int flags); |
| @@ -20,7 +20,6 @@ extern void ima_inode_free(struct inode *inode); · 19 unmodified lines | ||
| 20 | 20 | extern int ima_file_check(struct file *file, int mask); |
| 21 | 21 | extern void ima_file_free(struct file *file); |
| 22 | 22 | extern int ima_file_mmap(struct file *file, unsigned long prot); |
| 23 | −extern void ima_counts_get(struct file *file); | |
| 24 | 23 | |
| 25 | 24 | #else |
| 26 | 25 | static inline int ima_bprm_check(struct linux_binprm *bprm) |
| @@ -53,10 +52,5 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot) · 26 unmodified lines | ||
| 53 | 52 | return 0; |
| 54 | 53 | } |
| 55 | 54 | |
| 56 | −static inline void ima_counts_get(struct file *file) | |
| 57 | −{ | |
| 58 | − return; | |
| 59 | −} | |
| 60 | − | |
| 61 | 55 | #endif /* CONFIG_IMA_H */ |
| 62 | 56 | #endif /* _LINUX_IMA_H */ |
| @@ -41,6 +41,9 @@ struct key_type { · 40 unmodified lines | ||
| 41 | 41 | */ |
| 42 | 42 | size_t def_datalen; |
| 43 | 43 | |
| 44 | + /* vet a description */ | |
| 45 | + int (*vet_description)(const char *description); | |
| 46 | + | |
| 44 | 47 | /* instantiate a key of this type |
| 45 | 48 | * - this method should call key_payload_reserve() to determine if the |
| 46 | 49 | * user's quota will hold the payload |
| @@ -102,11 +105,20 @@ extern int key_instantiate_and_link(struct key *key, · 55 unmodified lines | ||
| 102 | 105 | size_t datalen, |
| 103 | 106 | struct key *keyring, |
| 104 | 107 | struct key *instkey); |
| 105 | −extern int key_negate_and_link(struct key *key, | |
| 108 | +extern int key_reject_and_link(struct key *key, | |
| 106 | 109 | unsigned timeout, |
| 110 | + unsigned error, | |
| 107 | 111 | struct key *keyring, |
| 108 | 112 | struct key *instkey); |
| 109 | 113 | extern void complete_request_key(struct key_construction *cons, int error); |
| 110 | 114 | |
| 115 | +static inline int key_negate_and_link(struct key *key, | |
| 116 | + unsigned timeout, | |
| 117 | + struct key *keyring, | |
| 118 | + struct key *instkey) | |
| 119 | +{ | |
| 120 | + return key_reject_and_link(key, timeout, ENOKEY, keyring, instkey); | |
| 121 | +} | |
| 122 | + | |
| 111 | 123 | #endif /* CONFIG_KEYS */ |
| 112 | 124 | #endif /* _LINUX_KEY_TYPE_H */ |
| @@ -170,6 +170,7 @@ struct key { · 169 unmodified lines | ||
| 170 | 170 | struct list_head link; |
| 171 | 171 | unsigned long x[2]; |
| 172 | 172 | void *p[2]; |
| 173 | + int reject_error; | |
| 173 | 174 | } type_data; |
| 174 | 175 | |
| 175 | 176 | /* key data |
| @@ -275,6 +276,10 @@ static inline key_serial_t key_serial(struct key *key) · 99 unmodified lines | ||
| 275 | 276 | return key ? key->serial : 0; |
| 276 | 277 | } |
| 277 | 278 | |
| 279 | +#define rcu_dereference_key(KEY) \ | |
| 280 | + (rcu_dereference_protected((KEY)->payload.rcudata, \ | |
| 281 | + rwsem_is_locked(&((struct key *)(KEY))->sem))) | |
| 282 | + | |
| 278 | 283 | #ifdef CONFIG_SYSCTL |
| 279 | 284 | extern ctl_table key_sysctls[]; |
| 280 | 285 | #endif |
| @@ -53,5 +53,7 @@ · 52 unmodified lines | ||
| 53 | 53 | #define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */ |
| 54 | 54 | #define KEYCTL_GET_SECURITY 17 /* get key security label */ |
| 55 | 55 | #define KEYCTL_SESSION_TO_PARENT 18 /* apply session keyring to parent process */ |
| 56 | +#define KEYCTL_REJECT 19 /* reject a partially constructed key */ | |
| 57 | +#define KEYCTL_INSTANTIATE_IOV 20 /* instantiate a partially constructed key */ | |
| 56 | 58 | |
| 57 | 59 | #endif /* _LINUX_KEYCTL_H */ |
| @@ -63,6 +63,7 @@ extern const struct xattr_handler reiserfs_xattr_trusted_handler; · 62 unmodified lines | ||
| 63 | 63 | extern const struct xattr_handler reiserfs_xattr_security_handler; |
| 64 | 64 | #ifdef CONFIG_REISERFS_FS_SECURITY |
| 65 | 65 | int reiserfs_security_init(struct inode *dir, struct inode *inode, |
| 66 | + const struct qstr *qstr, | |
| 66 | 67 | struct reiserfs_security_handle *sec); |
| 67 | 68 | int reiserfs_security_write(struct reiserfs_transaction_handle *th, |
| 68 | 69 | struct inode *inode, |
| @@ -130,6 +131,7 @@ static inline void reiserfs_init_xattr_rwsem(struct inode *inode) · 61 unmodified lines | ||
| 130 | 131 | #ifndef CONFIG_REISERFS_FS_SECURITY |
| 131 | 132 | static inline int reiserfs_security_init(struct inode *dir, |
| 132 | 133 | struct inode *inode, |
| 134 | + const struct qstr *qstr, | |
| 133 | 135 | struct reiserfs_security_handle *sec) |
| 134 | 136 | { |
| 135 | 137 | return 0; |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/fs.h> |
| 26 | 26 | #include <linux/fsnotify.h> |
| 27 | 27 | #include <linux/binfmts.h> |
| 28 | +#include <linux/dcache.h> | |
| 28 | 29 | #include <linux/signal.h> |
| 29 | 30 | #include <linux/resource.h> |
| 30 | 31 | #include <linux/sem.h> |
| @@ -267,6 +268,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) · 236 unmodified lines | ||
| 267 | 268 | * @orig the original mount data copied from userspace. |
| 268 | 269 | * @copy copied data which will be passed to the security module. |
| 269 | 270 | * Returns 0 if the copy was successful. |
| 271 | + * @sb_remount: | |
| 272 | + * Extracts security system specifc mount options and verifys no changes | |
| 273 | + * are being made to those options. | |
| 274 | + * @sb superblock being remounted | |
| 275 | + * @data contains the filesystem-specific data. | |
| 276 | + * Return 0 if permission is granted. | |
| 270 | 277 | * @sb_umount: |
| 271 | 278 | * Check permission before the @mnt file system is unmounted. |
| 272 | 279 | * @mnt contains the mounted file system. |
| @@ -315,6 +322,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) · 42 unmodified lines | ||
| 315 | 322 | * then it should return -EOPNOTSUPP to skip this processing. |
| 316 | 323 | * @inode contains the inode structure of the newly created inode. |
| 317 | 324 | * @dir contains the inode structure of the parent directory. |
| 325 | + * @qstr contains the last path component of the new object | |
| 318 | 326 | * @name will be set to the allocated name suffix (e.g. selinux). |
| 319 | 327 | * @value will be set to the allocated attribute value. |
| 320 | 328 | * @len will be set to the length of the value. |
| @@ -1257,12 +1265,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) · 936 unmodified lines | ||
| 1257 | 1265 | * @cap contains the capability <include/linux/capability.h>. |
| 1258 | 1266 | * @audit: Whether to write an audit message or not |
| 1259 | 1267 | * Return 0 if the capability is granted for @tsk. |
| 1260 | − * @sysctl: | |
| 1261 | − * Check permission before accessing the @table sysctl variable in the | |
| 1262 | − * manner specified by @op. | |
| 1263 | − * @table contains the ctl_table structure for the sysctl variable. | |
| 1264 | − * @op contains the operation (001 = search, 002 = write, 004 = read). | |
| 1265 | − * Return 0 if permission is granted. | |
| 1266 | 1268 | * @syslog: |
| 1267 | 1269 | * Check permission before accessing the kernel message ring or changing |
| 1268 | 1270 | * logging to the console. |
| @@ -1383,7 +1385,6 @@ struct security_operations { · 114 unmodified lines | ||
| 1383 | 1385 | const kernel_cap_t *permitted); |
| 1384 | 1386 | int (*capable) (struct task_struct *tsk, const struct cred *cred, |
| 1385 | 1387 | int cap, int audit); |
| 1386 | − int (*sysctl) (struct ctl_table *table, int op); | |
| 1387 | 1388 | int (*quotactl) (int cmds, int type, int id, struct super_block *sb); |
| 1388 | 1389 | int (*quota_on) (struct dentry *dentry); |
| 1389 | 1390 | int (*syslog) (int type); |
| @@ -1399,6 +1400,7 @@ struct security_operations { · 9 unmodified lines | ||
| 1399 | 1400 | int (*sb_alloc_security) (struct super_block *sb); |
| 1400 | 1401 | void (*sb_free_security) (struct super_block *sb); |
| 1401 | 1402 | int (*sb_copy_data) (char *orig, char *copy); |
| 1403 | + int (*sb_remount) (struct super_block *sb, void *data); | |
| 1402 | 1404 | int (*sb_kern_mount) (struct super_block *sb, int flags, void *data); |
| 1403 | 1405 | int (*sb_show_options) (struct seq_file *m, struct super_block *sb); |
| 1404 | 1406 | int (*sb_statfs) (struct dentry *dentry); |
| @@ -1435,7 +1437,8 @@ struct security_operations { · 30 unmodified lines | ||
| 1435 | 1437 | int (*inode_alloc_security) (struct inode *inode); |
| 1436 | 1438 | void (*inode_free_security) (struct inode *inode); |
| 1437 | 1439 | int (*inode_init_security) (struct inode *inode, struct inode *dir, |
| 1438 | − char **name, void **value, size_t *len); | |
| 1440 | + const struct qstr *qstr, char **name, | |
| 1441 | + void **value, size_t *len); | |
| 1439 | 1442 | int (*inode_create) (struct inode *dir, |
| 1440 | 1443 | struct dentry *dentry, int mode); |
| 1441 | 1444 | int (*inode_link) (struct dentry *old_dentry, |
| @@ -1665,7 +1668,6 @@ int security_capset(struct cred *new, const struct cred *old, · 223 unmodified lines | ||
| 1665 | 1668 | int security_capable(const struct cred *cred, int cap); |
| 1666 | 1669 | int security_real_capable(struct task_struct *tsk, int cap); |
| 1667 | 1670 | int security_real_capable_noaudit(struct task_struct *tsk, int cap); |
| 1668 | −int security_sysctl(struct ctl_table *table, int op); | |
| 1669 | 1671 | int security_quotactl(int cmds, int type, int id, struct super_block *sb); |
| 1670 | 1672 | int security_quota_on(struct dentry *dentry); |
| 1671 | 1673 | int security_syslog(int type); |
| @@ -1681,6 +1683,7 @@ int security_bprm_secureexec(struct linux_binprm *bprm); · 9 unmodified lines | ||
| 1681 | 1683 | int security_sb_alloc(struct super_block *sb); |
| 1682 | 1684 | void security_sb_free(struct super_block *sb); |
| 1683 | 1685 | int security_sb_copy_data(char *orig, char *copy); |
| 1686 | +int security_sb_remount(struct super_block *sb, void *data); | |
| 1684 | 1687 | int security_sb_kern_mount(struct super_block *sb, int flags, void *data); |
| 1685 | 1688 | int security_sb_show_options(struct seq_file *m, struct super_block *sb); |
| 1686 | 1689 | int security_sb_statfs(struct dentry *dentry); |
| @@ -1696,7 +1699,8 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); · 9 unmodified lines | ||
| 1696 | 1699 | int security_inode_alloc(struct inode *inode); |
| 1697 | 1700 | void security_inode_free(struct inode *inode); |
| 1698 | 1701 | int security_inode_init_security(struct inode *inode, struct inode *dir, |
| 1699 | − char **name, void **value, size_t *len); | |
| 1702 | + const struct qstr *qstr, char **name, | |
| 1703 | + void **value, size_t *len); | |
| 1700 | 1704 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode); |
| 1701 | 1705 | int security_inode_link(struct dentry *old_dentry, struct inode *dir, |
| 1702 | 1706 | struct dentry *new_dentry); |
| @@ -1883,11 +1887,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap) · 180 unmodified lines | ||
| 1883 | 1887 | return ret; |
| 1884 | 1888 | } |
| 1885 | 1889 | |
| 1886 | −static inline int security_sysctl(struct ctl_table *table, int op) | |
| 1887 | −{ | |
| 1888 | − return 0; | |
| 1889 | −} | |
| 1890 | − | |
| 1891 | 1890 | static inline int security_quotactl(int cmds, int type, int id, |
| 1892 | 1891 | struct super_block *sb) |
| 1893 | 1892 | { |
| @@ -1964,6 +1963,11 @@ static inline int security_sb_copy_data(char *orig, char *copy) · 70 unmodified lines | ||
| 1964 | 1963 | return 0; |
| 1965 | 1964 | } |
| 1966 | 1965 | |
| 1966 | +static inline int security_sb_remount(struct super_block *sb, void *data) | |
| 1967 | +{ | |
| 1968 | + return 0; | |
| 1969 | +} | |
| 1970 | + | |
| 1967 | 1971 | static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data) |
| 1968 | 1972 | { |
| 1969 | 1973 | return 0; |
| @@ -2023,6 +2027,7 @@ static inline void security_inode_free(struct inode *inode) · 53 unmodified lines | ||
| 2023 | 2027 | |
| 2024 | 2028 | static inline int security_inode_init_security(struct inode *inode, |
| 2025 | 2029 | struct inode *dir, |
| 2030 | + const struct qstr *qstr, | |
| 2026 | 2031 | char **name, |
| 2027 | 2032 | void **value, |
| 2028 | 2033 | size_t *len) |
| @@ -42,11 +42,13 @@ · 41 unmodified lines | ||
| 42 | 42 | #define XATTR_SMACK_IPOUT "SMACK64IPOUT" |
| 43 | 43 | #define XATTR_SMACK_EXEC "SMACK64EXEC" |
| 44 | 44 | #define XATTR_SMACK_TRANSMUTE "SMACK64TRANSMUTE" |
| 45 | +#define XATTR_SMACK_MMAP "SMACK64MMAP" | |
| 45 | 46 | #define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX |
| 46 | 47 | #define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN |
| 47 | 48 | #define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT |
| 48 | 49 | #define XATTR_NAME_SMACKEXEC XATTR_SECURITY_PREFIX XATTR_SMACK_EXEC |
| 49 | 50 | #define XATTR_NAME_SMACKTRANSMUTE XATTR_SECURITY_PREFIX XATTR_SMACK_TRANSMUTE |
| 51 | +#define XATTR_NAME_SMACKMMAP XATTR_SECURITY_PREFIX XATTR_SMACK_MMAP | |
| 50 | 52 | |
| 51 | 53 | #define XATTR_CAPS_SUFFIX "capability" |
| 52 | 54 | #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX |
| @@ -1690,13 +1690,8 @@ static int test_perm(int mode, int op) · 1689 unmodified lines | ||
| 1690 | 1690 | |
| 1691 | 1691 | int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op) |
| 1692 | 1692 | { |
| 1693 | − int error; | |
| 1694 | 1693 | int mode; |
| 1695 | 1694 | |
| 1696 | − error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC)); | |
| 1697 | − if (error) | |
| 1698 | − return error; | |
| 1699 | − | |
| 1700 | 1695 | if (root->permissions) |
| 1701 | 1696 | mode = root->permissions(root, current->nsproxy, table); |
| 1702 | 1697 | else |
| @@ -1843,8 +1843,9 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) · 1842 unmodified lines | ||
| 1843 | 1843 | |
| 1844 | 1844 | inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE); |
| 1845 | 1845 | if (inode) { |
| 1846 | − error = security_inode_init_security(inode, dir, NULL, NULL, | |
| 1847 | − NULL); | |
| 1846 | + error = security_inode_init_security(inode, dir, | |
| 1847 | + &dentry->d_name, NULL, | |
| 1848 | + NULL, NULL); | |
| 1848 | 1849 | if (error) { |
| 1849 | 1850 | if (error != -EOPNOTSUPP) { |
| 1850 | 1851 | iput(inode); |
| @@ -1983,8 +1984,8 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s · 132 unmodified lines | ||
| 1983 | 1984 | if (!inode) |
| 1984 | 1985 | return -ENOSPC; |
| 1985 | 1986 | |
| 1986 | − error = security_inode_init_security(inode, dir, NULL, NULL, | |
| 1987 | − NULL); | |
| 1987 | + error = security_inode_init_security(inode, dir, &dentry->d_name, NULL, | |
| 1988 | + NULL, NULL); | |
| 1988 | 1989 | if (error) { |
| 1989 | 1990 | if (error != -EOPNOTSUPP) { |
| 1990 | 1991 | iput(inode); |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <keys/user-type.h> |
| 26 | 26 | #include "ar-internal.h" |
| 27 | 27 | |
| 28 | +static int rxrpc_vet_description_s(const char *); | |
| 28 | 29 | static int rxrpc_instantiate(struct key *, const void *, size_t); |
| 29 | 30 | static int rxrpc_instantiate_s(struct key *, const void *, size_t); |
| 30 | 31 | static void rxrpc_destroy(struct key *); |
| @@ -52,12 +53,30 @@ EXPORT_SYMBOL(key_type_rxrpc); · 21 unmodified lines | ||
| 52 | 53 | */ |
| 53 | 54 | struct key_type key_type_rxrpc_s = { |
| 54 | 55 | .name = "rxrpc_s", |
| 56 | + .vet_description = rxrpc_vet_description_s, | |
| 55 | 57 | .instantiate = rxrpc_instantiate_s, |
| 56 | 58 | .match = user_match, |
| 57 | 59 | .destroy = rxrpc_destroy_s, |
| 58 | 60 | .describe = rxrpc_describe, |
| 59 | 61 | }; |
| 60 | 62 | |
| 63 | +/* | |
| 64 | + * Vet the description for an RxRPC server key | |
| 65 | + */ | |
| 66 | +static int rxrpc_vet_description_s(const char *desc) | |
| 67 | +{ | |
| 68 | + unsigned long num; | |
| 69 | + char *p; | |
| 70 | + | |
| 71 | + num = simple_strtoul(desc, &p, 10); | |
| 72 | + if (*p != ':' || num > 65535) | |
| 73 | + return -EINVAL; | |
| 74 | + num = simple_strtoul(p + 1, &p, 10); | |
| 75 | + if (*p || num < 1 || num > 255) | |
| 76 | + return -EINVAL; | |
| 77 | + return 0; | |
| 78 | +} | |
| 79 | + | |
| 61 | 80 | /* |
| 62 | 81 | * parse an RxKAD type XDR format token |
| 63 | 82 | * - the caller guarantees we have at least 4 words |
| @@ -43,6 +43,8 @@ int main(int argc, char *argv[]) · 42 unmodified lines | ||
| 43 | 43 | int i, j, k; |
| 44 | 44 | int isids_len; |
| 45 | 45 | FILE *fout; |
| 46 | + const char *needle = "SOCKET"; | |
| 47 | + char *substr; | |
| 46 | 48 | |
| 47 | 49 | progname = argv[0]; |
| 48 | 50 | |
| @@ -88,6 +90,24 @@ int main(int argc, char *argv[]) · 39 unmodified lines | ||
| 88 | 90 | fprintf(fout, "%2d\n", i); |
| 89 | 91 | } |
| 90 | 92 | fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1); |
| 93 | + fprintf(fout, "\nstatic inline bool security_is_socket_class(u16 kern_tclass)\n"); | |
| 94 | + fprintf(fout, "{\n"); | |
| 95 | + fprintf(fout, "\tbool sock = false;\n\n"); | |
| 96 | + fprintf(fout, "\tswitch (kern_tclass) {\n"); | |
| 97 | + for (i = 0; secclass_map[i].name; i++) { | |
| 98 | + struct security_class_mapping *map = &secclass_map[i]; | |
| 99 | + substr = strstr(map->name, needle); | |
| 100 | + if (substr && strcmp(substr, needle) == 0) | |
| 101 | + fprintf(fout, "\tcase SECCLASS_%s:\n", map->name); | |
| 102 | + } | |
| 103 | + fprintf(fout, "\t\tsock = true;\n"); | |
| 104 | + fprintf(fout, "\t\tbreak;\n"); | |
| 105 | + fprintf(fout, "\tdefault:\n"); | |
| 106 | + fprintf(fout, "\t\tbreak;\n"); | |
| 107 | + fprintf(fout, "\t}\n\n"); | |
| 108 | + fprintf(fout, "\treturn sock;\n"); | |
| 109 | + fprintf(fout, "}\n"); | |
| 110 | + | |
| 91 | 111 | fprintf(fout, "\n#endif\n"); |
| 92 | 112 | fclose(fout); |
| 93 | 113 | |
| @@ -6,19 +6,47 @@ apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ · 5 unmodified lines | ||
| 6 | 6 | path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ |
| 7 | 7 | resource.o sid.o file.o |
| 8 | 8 | |
| 9 | −clean-files: capability_names.h af_names.h | |
| 9 | +clean-files := capability_names.h rlim_names.h | |
| 10 | 10 | |
| 11 | + | |
| 12 | +# Build a lower case string table of capability names | |
| 13 | +# Transforms lines from | |
| 14 | +# #define CAP_DAC_OVERRIDE 1 | |
| 15 | +# to | |
| 16 | +# [1] = "dac_override", | |
| 11 | 17 | quiet_cmd_make-caps = GEN $@ |
| 12 | −cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ | |
| 18 | +cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ;\ | |
| 19 | + sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \ | |
| 20 | + -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\ | |
| 21 | + echo "};" >> $@ | |
| 22 | + | |
| 13 | 23 | |
| 24 | +# Build a lower case string table of rlimit names. | |
| 25 | +# Transforms lines from | |
| 26 | +# #define RLIMIT_STACK 3 /* max stack size */ | |
| 27 | +# to | |
| 28 | +# [RLIMIT_STACK] = "stack", | |
| 29 | +# | |
| 30 | +# and build a second integer table (with the second sed cmd), that maps | |
| 31 | +# RLIMIT defines to the order defined in asm-generic/resource.h Thi is | |
| 32 | +# required by policy load to map policy ordering of RLIMITs to internal | |
| 33 | +# ordering for architectures that redefine an RLIMIT. | |
| 34 | +# Transforms lines from | |
| 35 | +# #define RLIMIT_STACK 3 /* max stack size */ | |
| 36 | +# to | |
| 37 | +# RLIMIT_STACK, | |
| 14 | 38 | quiet_cmd_make-rlim = GEN $@ |
| 15 | −cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@ | |
| 39 | +cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ;\ | |
| 40 | + sed $< >> $@ -r -n \ | |
| 41 | + -e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\ | |
| 42 | + echo "};" >> $@ ;\ | |
| 43 | + echo "static const int rlim_map[] = {" >> $@ ;\ | |
| 44 | + sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\ | |
| 45 | + echo "};" >> $@ | |
| 16 | 46 | |
| 17 | 47 | $(obj)/capability.o : $(obj)/capability_names.h |
| 18 | 48 | $(obj)/resource.o : $(obj)/rlim_names.h |
| 19 | 49 | $(obj)/capability_names.h : $(srctree)/include/linux/capability.h |
| 20 | 50 | $(call cmd,make-caps) |
| 21 | −$(obj)/af_names.h : $(srctree)/include/linux/socket.h | |
| 22 | − $(call cmd,make-af) | |
| 23 | 51 | $(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h |
| 24 | 52 | $(call cmd,make-rlim) |
| @@ -693,11 +693,9 @@ static struct kernel_param_ops param_ops_aalockpolicy = { · 692 unmodified lines | ||
| 693 | 693 | |
| 694 | 694 | static int param_set_audit(const char *val, struct kernel_param *kp); |
| 695 | 695 | static int param_get_audit(char *buffer, struct kernel_param *kp); |
| 696 | −#define param_check_audit(name, p) __param_check(name, p, int) | |
| 697 | 696 | |
| 698 | 697 | static int param_set_mode(const char *val, struct kernel_param *kp); |
| 699 | 698 | static int param_get_mode(char *buffer, struct kernel_param *kp); |
| 700 | −#define param_check_mode(name, p) __param_check(name, p, int) | |
| 701 | 699 | |
| 702 | 700 | /* Flag values, also controllable via /sys/module/apparmor/parameters |
| 703 | 701 | * We define special types as we want to do additional mediation. |
| @@ -12,11 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include <linux/security.h> |
| 14 | 14 | |
| 15 | −static int cap_sysctl(ctl_table *table, int op) | |
| 16 | −{ | |
| 17 | − return 0; | |
| 18 | −} | |
| 19 | − | |
| 20 | 15 | static int cap_syslog(int type) |
| 21 | 16 | { |
| 22 | 17 | return 0; |
| @@ -59,6 +54,11 @@ static int cap_sb_copy_data(char *orig, char *copy) · 36 unmodified lines | ||
| 59 | 54 | return 0; |
| 60 | 55 | } |
| 61 | 56 | |
| 57 | +static int cap_sb_remount(struct super_block *sb, void *data) | |
| 58 | +{ | |
| 59 | + return 0; | |
| 60 | +} | |
| 61 | + | |
| 62 | 62 | static int cap_sb_kern_mount(struct super_block *sb, int flags, void *data) |
| 63 | 63 | { |
| 64 | 64 | return 0; |
| @@ -118,7 +118,8 @@ static void cap_inode_free_security(struct inode *inode) · 53 unmodified lines | ||
| 118 | 118 | } |
| 119 | 119 | |
| 120 | 120 | static int cap_inode_init_security(struct inode *inode, struct inode *dir, |
| 121 | − char **name, void **value, size_t *len) | |
| 121 | + const struct qstr *qstr, char **name, | |
| 122 | + void **value, size_t *len) | |
| 122 | 123 | { |
| 123 | 124 | return -EOPNOTSUPP; |
| 124 | 125 | } |
| @@ -880,7 +881,6 @@ void __init security_fixup_ops(struct security_operations *ops) · 755 unmodified lines | ||
| 880 | 881 | set_to_cap_if_null(ops, capable); |
| 881 | 882 | set_to_cap_if_null(ops, quotactl); |
| 882 | 883 | set_to_cap_if_null(ops, quota_on); |
| 883 | − set_to_cap_if_null(ops, sysctl); | |
| 884 | 884 | set_to_cap_if_null(ops, syslog); |
| 885 | 885 | set_to_cap_if_null(ops, settime); |
| 886 | 886 | set_to_cap_if_null(ops, vm_enough_memory); |
| @@ -892,6 +892,7 @@ void __init security_fixup_ops(struct security_operations *ops) · 5 unmodified lines | ||
| 892 | 892 | set_to_cap_if_null(ops, sb_alloc_security); |
| 893 | 893 | set_to_cap_if_null(ops, sb_free_security); |
| 894 | 894 | set_to_cap_if_null(ops, sb_copy_data); |
| 895 | + set_to_cap_if_null(ops, sb_remount); | |
| 895 | 896 | set_to_cap_if_null(ops, sb_kern_mount); |
| 896 | 897 | set_to_cap_if_null(ops, sb_show_options); |
| 897 | 898 | set_to_cap_if_null(ops, sb_statfs); |
| @@ -110,8 +110,7 @@ struct ima_iint_cache { · 109 unmodified lines | ||
| 110 | 110 | }; |
| 111 | 111 | |
| 112 | 112 | /* LIM API function definitions */ |
| 113 | −int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode, | |
| 114 | − int mask, int function); | |
| 113 | +int ima_must_measure(struct inode *inode, int mask, int function); | |
| 115 | 114 | int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file); |
| 116 | 115 | void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, |
| 117 | 116 | const unsigned char *filename); |
| @@ -105,20 +105,13 @@ err_out: · 104 unmodified lines | ||
| 105 | 105 | * mask: contains the permission mask |
| 106 | 106 | * fsmagic: hex value |
| 107 | 107 | * |
| 108 | − * Must be called with iint->mutex held. | |
| 109 | − * | |
| 110 | − * Return 0 to measure. Return 1 if already measured. | |
| 111 | − * For matching a DONT_MEASURE policy, no policy, or other | |
| 112 | − * error, return an error code. | |
| 108 | + * Return 0 to measure. For matching a DONT_MEASURE policy, no policy, | |
| 109 | + * or other error, return an error code. | |
| 113 | 110 | */ |
| 114 | −int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode, | |
| 115 | − int mask, int function) | |
| 111 | +int ima_must_measure(struct inode *inode, int mask, int function) | |
| 116 | 112 | { |
| 117 | 113 | int must_measure; |
| 118 | 114 | |
| 119 | − if (iint && iint->flags & IMA_MEASURED) | |
| 120 | − return 1; | |
| 121 | − | |
| 122 | 115 | must_measure = ima_match_policy(inode, function, mask); |
| 123 | 116 | return must_measure ? 0 : -EACCES; |
| 124 | 117 | } |
| @@ -137,11 +137,6 @@ void ima_inode_free(struct inode *inode) · 136 unmodified lines | ||
| 137 | 137 | { |
| 138 | 138 | struct ima_iint_cache *iint; |
| 139 | 139 | |
| 140 | − if (inode->i_readcount) | |
| 141 | − printk(KERN_INFO "%s: readcount: %u\n", __func__, inode->i_readcount); | |
| 142 | − | |
| 143 | − inode->i_readcount = 0; | |
| 144 | − | |
| 145 | 140 | if (!IS_IMA(inode)) |
| 146 | 141 | return; |
| 147 | 142 | |
| @@ -36,67 +36,17 @@ static int __init hash_setup(char *str) · 35 unmodified lines | ||
| 36 | 36 | } |
| 37 | 37 | __setup("ima_hash=", hash_setup); |
| 38 | 38 | |
| 39 | −struct ima_imbalance { | |
| 40 | − struct hlist_node node; | |
| 41 | − unsigned long fsmagic; | |
| 42 | −}; | |
| 43 | − | |
| 44 | −/* | |
| 45 | − * ima_limit_imbalance - emit one imbalance message per filesystem type | |
| 46 | − * | |
| 47 | − * Maintain list of filesystem types that do not measure files properly. | |
| 48 | − * Return false if unknown, true if known. | |
| 49 | − */ | |
| 50 | −static bool ima_limit_imbalance(struct file *file) | |
| 51 | −{ | |
| 52 | − static DEFINE_SPINLOCK(ima_imbalance_lock); | |
| 53 | − static HLIST_HEAD(ima_imbalance_list); | |
| 54 | − | |
| 55 | − struct super_block *sb = file->f_dentry->d_sb; | |
| 56 | − struct ima_imbalance *entry; | |
| 57 | − struct hlist_node *node; | |
| 58 | − bool found = false; | |
| 59 | − | |
| 60 | − rcu_read_lock(); | |
| 61 | − hlist_for_each_entry_rcu(entry, node, &ima_imbalance_list, node) { | |
| 62 | − if (entry->fsmagic == sb->s_magic) { | |
| 63 | − found = true; | |
| 64 | − break; | |
| 65 | − } | |
| 66 | − } | |
| 67 | − rcu_read_unlock(); | |
| 68 | − if (found) | |
| 69 | − goto out; | |
| 70 | − | |
| 71 | − entry = kmalloc(sizeof(*entry), GFP_NOFS); | |
| 72 | − if (!entry) | |
| 73 | − goto out; | |
| 74 | − entry->fsmagic = sb->s_magic; | |
| 75 | − spin_lock(&ima_imbalance_lock); | |
| 76 | − /* | |
| 77 | − * we could have raced and something else might have added this fs | |
| 78 | − * to the list, but we don't really care | |
| 79 | − */ | |
| 80 | − hlist_add_head_rcu(&entry->node, &ima_imbalance_list); | |
| 81 | − spin_unlock(&ima_imbalance_lock); | |
| 82 | − printk(KERN_INFO "IMA: unmeasured files on fsmagic: %lX\n", | |
| 83 | − entry->fsmagic); | |
| 84 | −out: | |
| 85 | − return found; | |
| 86 | −} | |
| 87 | − | |
| 88 | 39 | /* |
| 89 | − * ima_counts_get - increment file counts | |
| 40 | + * ima_rdwr_violation_check | |
| 90 | 41 | * |
| 91 | − * Maintain read/write counters for all files, but only | |
| 92 | − * invalidate the PCR for measured files: | |
| 42 | + * Only invalidate the PCR for measured files: | |
| 93 | 43 | * - Opening a file for write when already open for read, |
| 94 | 44 | * results in a time of measure, time of use (ToMToU) error. |
| 95 | 45 | * - Opening a file for read when already open for write, |
| 96 | 46 | * could result in a file measurement error. |
| 97 | 47 | * |
| 98 | 48 | */ |
| 99 | −void ima_counts_get(struct file *file) | |
| 49 | +static void ima_rdwr_violation_check(struct file *file) | |
| 100 | 50 | { |
| 101 | 51 | struct dentry *dentry = file->f_path.dentry; |
| 102 | 52 | struct inode *inode = dentry->d_inode; |
| @@ -104,32 +54,25 @@ void ima_counts_get(struct file *file) · 1 unmodified line | ||
| 104 | 54 | int rc; |
| 105 | 55 | bool send_tomtou = false, send_writers = false; |
| 106 | 56 | |
| 107 | − if (!S_ISREG(inode->i_mode)) | |
| 57 | + if (!S_ISREG(inode->i_mode) || !ima_initialized) | |
| 108 | 58 | return; |
| 109 | 59 | |
| 110 | − spin_lock(&inode->i_lock); | |
| 111 | − | |
| 112 | − if (!ima_initialized) | |
| 113 | − goto out; | |
| 60 | + mutex_lock(&inode->i_mutex); /* file metadata: permissions, xattr */ | |
| 114 | 61 | |
| 115 | 62 | if (mode & FMODE_WRITE) { |
| 116 | − if (inode->i_readcount && IS_IMA(inode)) | |
| 63 | + if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) | |
| 117 | 64 | send_tomtou = true; |
| 118 | 65 | goto out; |
| 119 | 66 | } |
| 120 | 67 | |
| 121 | − rc = ima_must_measure(NULL, inode, MAY_READ, FILE_CHECK); | |
| 68 | + rc = ima_must_measure(inode, MAY_READ, FILE_CHECK); | |
| 122 | 69 | if (rc < 0) |
| 123 | 70 | goto out; |
| 124 | 71 | |
| 125 | 72 | if (atomic_read(&inode->i_writecount) > 0) |
| 126 | 73 | send_writers = true; |
| 127 | 74 | out: |
| 128 | − /* remember the vfs deals with i_writecount */ | |
| 129 | − if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | |
| 130 | − inode->i_readcount++; | |
| 131 | − | |
| 132 | − spin_unlock(&inode->i_lock); | |
| 75 | + mutex_unlock(&inode->i_mutex); | |
| 133 | 76 | |
| 134 | 77 | if (send_tomtou) |
| 135 | 78 | ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", |
| @@ -139,71 +82,25 @@ out: · 3 unmodified lines | ||
| 139 | 82 | "open_writers"); |
| 140 | 83 | } |
| 141 | 84 | |
| 142 | −/* | |
| 143 | − * Decrement ima counts | |
| 144 | − */ | |
| 145 | −static void ima_dec_counts(struct inode *inode, struct file *file) | |
| 146 | −{ | |
| 147 | − mode_t mode = file->f_mode; | |
| 148 | − | |
| 149 | − assert_spin_locked(&inode->i_lock); | |
| 150 | − | |
| 151 | − if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { | |
| 152 | − if (unlikely(inode->i_readcount == 0)) { | |
| 153 | − if (!ima_limit_imbalance(file)) { | |
| 154 | − printk(KERN_INFO "%s: open/free imbalance (r:%u)\n", | |
| 155 | − __func__, inode->i_readcount); | |
| 156 | − dump_stack(); | |
| 157 | − } | |
| 158 | − return; | |
| 159 | − } | |
| 160 | − inode->i_readcount--; | |
| 161 | − } | |
| 162 | −} | |
| 163 | − | |
| 164 | 85 | static void ima_check_last_writer(struct ima_iint_cache *iint, |
| 165 | 86 | struct inode *inode, |
| 166 | 87 | struct file *file) |
| 167 | 88 | { |
| 168 | 89 | mode_t mode = file->f_mode; |
| 169 | 90 | |
| 170 | − BUG_ON(!mutex_is_locked(&iint->mutex)); | |
| 171 | − assert_spin_locked(&inode->i_lock); | |
| 172 | − | |
| 91 | + mutex_lock(&iint->mutex); | |
| 173 | 92 | if (mode & FMODE_WRITE && |
| 174 | 93 | atomic_read(&inode->i_writecount) == 1 && |
| 175 | 94 | iint->version != inode->i_version) |
| 176 | 95 | iint->flags &= ~IMA_MEASURED; |
| 177 | −} | |
| 178 | − | |
| 179 | −static void ima_file_free_iint(struct ima_iint_cache *iint, struct inode *inode, | |
| 180 | − struct file *file) | |
| 181 | −{ | |
| 182 | − mutex_lock(&iint->mutex); | |
| 183 | − spin_lock(&inode->i_lock); | |
| 184 | − | |
| 185 | − ima_dec_counts(inode, file); | |
| 186 | − ima_check_last_writer(iint, inode, file); | |
| 187 | − | |
| 188 | − spin_unlock(&inode->i_lock); | |
| 189 | 96 | mutex_unlock(&iint->mutex); |
| 190 | 97 | } |
| 191 | 98 | |
| 192 | −static void ima_file_free_noiint(struct inode *inode, struct file *file) | |
| 193 | −{ | |
| 194 | − spin_lock(&inode->i_lock); | |
| 195 | − | |
| 196 | − ima_dec_counts(inode, file); | |
| 197 | − | |
| 198 | − spin_unlock(&inode->i_lock); | |
| 199 | −} | |
| 200 | − | |
| 201 | 99 | /** |
| 202 | 100 | * ima_file_free - called on __fput() |
| 203 | 101 | * @file: pointer to file structure being freed |
| 204 | 102 | * |
| 205 | − * Flag files that changed, based on i_version; | |
| 206 | − * and decrement the i_readcount. | |
| 103 | + * Flag files that changed, based on i_version | |
| 207 | 104 | */ |
| 208 | 105 | void ima_file_free(struct file *file) |
| 209 | 106 | { |
| @@ -214,12 +111,10 @@ void ima_file_free(struct file *file) · 4 unmodified lines | ||
| 214 | 111 | return; |
| 215 | 112 | |
| 216 | 113 | iint = ima_iint_find(inode); |
| 114 | + if (!iint) | |
| 115 | + return; | |
| 217 | 116 | |
| 218 | − if (iint) | |
| 219 | − ima_file_free_iint(iint, inode, file); | |
| 220 | − else | |
| 221 | − ima_file_free_noiint(inode, file); | |
| 222 | − | |
| 117 | + ima_check_last_writer(iint, inode, file); | |
| 223 | 118 | } |
| 224 | 119 | |
| 225 | 120 | static int process_measurement(struct file *file, const unsigned char *filename, |
| @@ -232,7 +127,7 @@ static int process_measurement(struct file *file, const unsigned char *filename, · 6 unmodified lines | ||
| 232 | 127 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
| 233 | 128 | return 0; |
| 234 | 129 | |
| 235 | − rc = ima_must_measure(NULL, inode, mask, function); | |
| 130 | + rc = ima_must_measure(inode, mask, function); | |
| 236 | 131 | if (rc != 0) |
| 237 | 132 | return rc; |
| 238 | 133 | retry: |
| @@ -246,7 +141,7 @@ retry: · 7 unmodified lines | ||
| 246 | 141 | |
| 247 | 142 | mutex_lock(&iint->mutex); |
| 248 | 143 | |
| 249 | − rc = ima_must_measure(iint, inode, mask, function); | |
| 144 | + rc = iint->flags & IMA_MEASURED ? 1 : 0; | |
| 250 | 145 | if (rc != 0) |
| 251 | 146 | goto out; |
| 252 | 147 | |
| @@ -317,6 +212,7 @@ int ima_file_check(struct file *file, int mask) · 64 unmodified lines | ||
| 317 | 212 | { |
| 318 | 213 | int rc; |
| 319 | 214 | |
| 215 | + ima_rdwr_violation_check(file); | |
| 320 | 216 | rc = process_measurement(file, file->f_dentry->d_name.name, |
| 321 | 217 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), |
| 322 | 218 | FILE_CHECK); |
| @@ -12,8 +12,51 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/syscalls.h> |
| 13 | 13 | #include <linux/keyctl.h> |
| 14 | 14 | #include <linux/compat.h> |
| 15 | +#include <linux/slab.h> | |
| 15 | 16 | #include "internal.h" |
| 16 | 17 | |
| 18 | +/* | |
| 19 | + * Instantiate a key with the specified compatibility multipart payload and | |
| 20 | + * link the key into the destination keyring if one is given. | |
| 21 | + * | |
| 22 | + * The caller must have the appropriate instantiation permit set for this to | |
| 23 | + * work (see keyctl_assume_authority). No other permissions are required. | |
| 24 | + * | |
| 25 | + * If successful, 0 will be returned. | |
| 26 | + */ | |
| 27 | +long compat_keyctl_instantiate_key_iov( | |
| 28 | + key_serial_t id, | |
| 29 | + const struct compat_iovec __user *_payload_iov, | |
| 30 | + unsigned ioc, | |
| 31 | + key_serial_t ringid) | |
| 32 | +{ | |
| 33 | + struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; | |
| 34 | + long ret; | |
| 35 | + | |
| 36 | + if (_payload_iov == 0 || ioc == 0) | |
| 37 | + goto no_payload; | |
| 38 | + | |
| 39 | + ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc, | |
| 40 | + ARRAY_SIZE(iovstack), | |
| 41 | + iovstack, &iov); | |
| 42 | + if (ret < 0) | |
| 43 | + return ret; | |
| 44 | + if (ret == 0) | |
| 45 | + goto no_payload_free; | |
| 46 | + | |
| 47 | + ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); | |
| 48 | + | |
| 49 | + if (iov != iovstack) | |
| 50 | + kfree(iov); | |
| 51 | + return ret; | |
| 52 | + | |
| 53 | +no_payload_free: | |
| 54 | + if (iov != iovstack) | |
| 55 | + kfree(iov); | |
| 56 | +no_payload: | |
| 57 | + return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); | |
| 58 | +} | |
| 59 | + | |
| 17 | 60 | /* |
| 18 | 61 | * The key control system call, 32-bit compatibility version for 64-bit archs |
| 19 | 62 | * |
| @@ -85,6 +128,13 @@ asmlinkage long compat_sys_keyctl(u32 option, · 65 unmodified lines | ||
| 85 | 128 | case KEYCTL_SESSION_TO_PARENT: |
| 86 | 129 | return keyctl_session_to_parent(); |
| 87 | 130 | |
| 131 | + case KEYCTL_REJECT: | |
| 132 | + return keyctl_reject_key(arg2, arg3, arg4, arg5); | |
| 133 | + | |
| 134 | + case KEYCTL_INSTANTIATE_IOV: | |
| 135 | + return compat_keyctl_instantiate_key_iov( | |
| 136 | + arg2, compat_ptr(arg3), arg4, arg5); | |
| 137 | + | |
| 88 | 138 | default: |
| 89 | 139 | return -EOPNOTSUPP; |
| 90 | 140 | } |
| @@ -765,8 +765,7 @@ static long encrypted_read(const struct key *key, char __user *buffer, · 764 unmodified lines | ||
| 765 | 765 | size_t asciiblob_len; |
| 766 | 766 | int ret; |
| 767 | 767 | |
| 768 | − epayload = rcu_dereference_protected(key->payload.data, | |
| 769 | − rwsem_is_locked(&((struct key *)key)->sem)); | |
| 768 | + epayload = rcu_dereference_key(key); | |
| 770 | 769 | |
| 771 | 770 | /* returns the hex encoded iv, encrypted-data, and hmac as ascii */ |
| 772 | 771 | asciiblob_len = epayload->datablob_len + ivsize + 1 |
| @@ -214,6 +214,14 @@ extern long keyctl_assume_authority(key_serial_t); · 213 unmodified lines | ||
| 214 | 214 | extern long keyctl_get_security(key_serial_t keyid, char __user *buffer, |
| 215 | 215 | size_t buflen); |
| 216 | 216 | extern long keyctl_session_to_parent(void); |
| 217 | +extern long keyctl_reject_key(key_serial_t, unsigned, unsigned, key_serial_t); | |
| 218 | +extern long keyctl_instantiate_key_iov(key_serial_t, | |
| 219 | + const struct iovec __user *, | |
| 220 | + unsigned, key_serial_t); | |
| 221 | + | |
| 222 | +extern long keyctl_instantiate_key_common(key_serial_t, | |
| 223 | + const struct iovec __user *, | |
| 224 | + unsigned, size_t, key_serial_t); | |
| 217 | 225 | |
| 218 | 226 | /* |
| 219 | 227 | * Debugging key validation |
| @@ -249,6 +249,14 @@ struct key *key_alloc(struct key_type *type, const char *desc, · 248 unmodified lines | ||
| 249 | 249 | if (!desc || !*desc) |
| 250 | 250 | goto error; |
| 251 | 251 | |
| 252 | + if (type->vet_description) { | |
| 253 | + ret = type->vet_description(desc); | |
| 254 | + if (ret < 0) { | |
| 255 | + key = ERR_PTR(ret); | |
| 256 | + goto error; | |
| 257 | + } | |
| 258 | + } | |
| 259 | + | |
| 252 | 260 | desclen = strlen(desc) + 1; |
| 253 | 261 | quotalen = desclen + type->def_datalen; |
| 254 | 262 | |
| @@ -503,26 +511,29 @@ int key_instantiate_and_link(struct key *key, · 248 unmodified lines | ||
| 503 | 511 | EXPORT_SYMBOL(key_instantiate_and_link); |
| 504 | 512 | |
| 505 | 513 | /** |
| 506 | − * key_negate_and_link - Negatively instantiate a key and link it into the keyring. | |
| 514 | + * key_reject_and_link - Negatively instantiate a key and link it into the keyring. | |
| 507 | 515 | * @key: The key to instantiate. |
| 508 | 516 | * @timeout: The timeout on the negative key. |
| 517 | + * @error: The error to return when the key is hit. | |
| 509 | 518 | * @keyring: Keyring to create a link in on success (or NULL). |
| 510 | 519 | * @authkey: The authorisation token permitting instantiation. |
| 511 | 520 | * |
| 512 | 521 | * Negatively instantiate a key that's in the uninstantiated state and, if |
| 513 | − * successful, set its timeout and link it in to the destination keyring if one | |
| 514 | − * is supplied. The key and any links to the key will be automatically garbage | |
| 515 | − * collected after the timeout expires. | |
| 522 | + * successful, set its timeout and stored error and link it in to the | |
| 523 | + * destination keyring if one is supplied. The key and any links to the key | |
| 524 | + * will be automatically garbage collected after the timeout expires. | |
| 516 | 525 | * |
| 517 | 526 | * Negative keys are used to rate limit repeated request_key() calls by causing |
| 518 | − * them to return -ENOKEY until the negative key expires. | |
| 527 | + * them to return the stored error code (typically ENOKEY) until the negative | |
| 528 | + * key expires. | |
| 519 | 529 | * |
| 520 | 530 | * If successful, 0 is returned, the authorisation token is revoked and anyone |
| 521 | 531 | * waiting for the key is woken up. If the key was already instantiated, |
| 522 | 532 | * -EBUSY will be returned. |
| 523 | 533 | */ |
| 524 | −int key_negate_and_link(struct key *key, | |
| 534 | +int key_reject_and_link(struct key *key, | |
| 525 | 535 | unsigned timeout, |
| 536 | + unsigned error, | |
| 526 | 537 | struct key *keyring, |
| 527 | 538 | struct key *authkey) |
| 528 | 539 | { |
| @@ -548,6 +559,7 @@ int key_negate_and_link(struct key *key, · 19 unmodified lines | ||
| 548 | 559 | atomic_inc(&key->user->nikeys); |
| 549 | 560 | set_bit(KEY_FLAG_NEGATIVE, &key->flags); |
| 550 | 561 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); |
| 562 | + key->type_data.reject_error = -error; | |
| 551 | 563 | now = current_kernel_time(); |
| 552 | 564 | key->expiry = now.tv_sec + timeout; |
| 553 | 565 | key_schedule_gc(key->expiry + key_gc_delay); |
| @@ -577,8 +589,7 @@ int key_negate_and_link(struct key *key, · 23 unmodified lines | ||
| 577 | 589 | |
| 578 | 590 | return ret == 0 ? link_ret : ret; |
| 579 | 591 | } |
| 580 | − | |
| 581 | −EXPORT_SYMBOL(key_negate_and_link); | |
| 592 | +EXPORT_SYMBOL(key_reject_and_link); | |
| 582 | 593 | |
| 583 | 594 | /* |
| 584 | 595 | * Garbage collect keys in process context so that we don't have to disable |
| @@ -912,6 +912,21 @@ static int keyctl_change_reqkey_auth(struct key *key) · 911 unmodified lines | ||
| 912 | 912 | return commit_creds(new); |
| 913 | 913 | } |
| 914 | 914 | |
| 915 | +/* | |
| 916 | + * Copy the iovec data from userspace | |
| 917 | + */ | |
| 918 | +static long copy_from_user_iovec(void *buffer, const struct iovec *iov, | |
| 919 | + unsigned ioc) | |
| 920 | +{ | |
| 921 | + for (; ioc > 0; ioc--) { | |
| 922 | + if (copy_from_user(buffer, iov->iov_base, iov->iov_len) != 0) | |
| 923 | + return -EFAULT; | |
| 924 | + buffer += iov->iov_len; | |
| 925 | + iov++; | |
| 926 | + } | |
| 927 | + return 0; | |
| 928 | +} | |
| 929 | + | |
| 915 | 930 | /* |
| 916 | 931 | * Instantiate a key with the specified payload and link the key into the |
| 917 | 932 | * destination keyring if one is given. |
| @@ -921,10 +936,11 @@ static int keyctl_change_reqkey_auth(struct key *key) · 3 unmodified lines | ||
| 921 | 936 | * |
| 922 | 937 | * If successful, 0 will be returned. |
| 923 | 938 | */ |
| 924 | −long keyctl_instantiate_key(key_serial_t id, | |
| 925 | − const void __user *_payload, | |
| 926 | − size_t plen, | |
| 927 | − key_serial_t ringid) | |
| 939 | +long keyctl_instantiate_key_common(key_serial_t id, | |
| 940 | + const struct iovec *payload_iov, | |
| 941 | + unsigned ioc, | |
| 942 | + size_t plen, | |
| 943 | + key_serial_t ringid) | |
| 928 | 944 | { |
| 929 | 945 | const struct cred *cred = current_cred(); |
| 930 | 946 | struct request_key_auth *rka; |
| @@ -953,7 +969,7 @@ long keyctl_instantiate_key(key_serial_t id, · 22 unmodified lines | ||
| 953 | 969 | /* pull the payload in if one was supplied */ |
| 954 | 970 | payload = NULL; |
| 955 | 971 | |
| 956 | − if (_payload) { | |
| 972 | + if (payload_iov) { | |
| 957 | 973 | ret = -ENOMEM; |
| 958 | 974 | payload = kmalloc(plen, GFP_KERNEL); |
| 959 | 975 | if (!payload) { |
| @@ -965,8 +981,8 @@ long keyctl_instantiate_key(key_serial_t id, · 5 unmodified lines | ||
| 965 | 981 | goto error; |
| 966 | 982 | } |
| 967 | 983 | |
| 968 | − ret = -EFAULT; | |
| 969 | − if (copy_from_user(payload, _payload, plen) != 0) | |
| 984 | + ret = copy_from_user_iovec(payload, payload_iov, ioc); | |
| 985 | + if (ret < 0) | |
| 970 | 986 | goto error2; |
| 971 | 987 | } |
| 972 | 988 | |
| @@ -996,6 +1012,72 @@ error: · 23 unmodified lines | ||
| 996 | 1012 | return ret; |
| 997 | 1013 | } |
| 998 | 1014 | |
| 1015 | +/* | |
| 1016 | + * Instantiate a key with the specified payload and link the key into the | |
| 1017 | + * destination keyring if one is given. | |
| 1018 | + * | |
| 1019 | + * The caller must have the appropriate instantiation permit set for this to | |
| 1020 | + * work (see keyctl_assume_authority). No other permissions are required. | |
| 1021 | + * | |
| 1022 | + * If successful, 0 will be returned. | |
| 1023 | + */ | |
| 1024 | +long keyctl_instantiate_key(key_serial_t id, | |
| 1025 | + const void __user *_payload, | |
| 1026 | + size_t plen, | |
| 1027 | + key_serial_t ringid) | |
| 1028 | +{ | |
| 1029 | + if (_payload && plen) { | |
| 1030 | + struct iovec iov[1] = { | |
| 1031 | + [0].iov_base = (void __user *)_payload, | |
| 1032 | + [0].iov_len = plen | |
| 1033 | + }; | |
| 1034 | + | |
| 1035 | + return keyctl_instantiate_key_common(id, iov, 1, plen, ringid); | |
| 1036 | + } | |
| 1037 | + | |
| 1038 | + return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); | |
| 1039 | +} | |
| 1040 | + | |
| 1041 | +/* | |
| 1042 | + * Instantiate a key with the specified multipart payload and link the key into | |
| 1043 | + * the destination keyring if one is given. | |
| 1044 | + * | |
| 1045 | + * The caller must have the appropriate instantiation permit set for this to | |
| 1046 | + * work (see keyctl_assume_authority). No other permissions are required. | |
| 1047 | + * | |
| 1048 | + * If successful, 0 will be returned. | |
| 1049 | + */ | |
| 1050 | +long keyctl_instantiate_key_iov(key_serial_t id, | |
| 1051 | + const struct iovec __user *_payload_iov, | |
| 1052 | + unsigned ioc, | |
| 1053 | + key_serial_t ringid) | |
| 1054 | +{ | |
| 1055 | + struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; | |
| 1056 | + long ret; | |
| 1057 | + | |
| 1058 | + if (_payload_iov == 0 || ioc == 0) | |
| 1059 | + goto no_payload; | |
| 1060 | + | |
| 1061 | + ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, | |
| 1062 | + ARRAY_SIZE(iovstack), iovstack, &iov); | |
| 1063 | + if (ret < 0) | |
| 1064 | + return ret; | |
| 1065 | + if (ret == 0) | |
| 1066 | + goto no_payload_free; | |
| 1067 | + | |
| 1068 | + ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); | |
| 1069 | + | |
| 1070 | + if (iov != iovstack) | |
| 1071 | + kfree(iov); | |
| 1072 | + return ret; | |
| 1073 | + | |
| 1074 | +no_payload_free: | |
| 1075 | + if (iov != iovstack) | |
| 1076 | + kfree(iov); | |
| 1077 | +no_payload: | |
| 1078 | + return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); | |
| 1079 | +} | |
| 1080 | + | |
| 999 | 1081 | /* |
| 1000 | 1082 | * Negatively instantiate the key with the given timeout (in seconds) and link |
| 1001 | 1083 | * the key into the destination keyring if one is given. |
| @@ -1012,13 +1094,43 @@ error: · 10 unmodified lines | ||
| 1012 | 1094 | * If successful, 0 will be returned. |
| 1013 | 1095 | */ |
| 1014 | 1096 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) |
| 1097 | +{ | |
| 1098 | + return keyctl_reject_key(id, timeout, ENOKEY, ringid); | |
| 1099 | +} | |
| 1100 | + | |
| 1101 | +/* | |
| 1102 | + * Negatively instantiate the key with the given timeout (in seconds) and error | |
| 1103 | + * code and link the key into the destination keyring if one is given. | |
| 1104 | + * | |
| 1105 | + * The caller must have the appropriate instantiation permit set for this to | |
| 1106 | + * work (see keyctl_assume_authority). No other permissions are required. | |
| 1107 | + * | |
| 1108 | + * The key and any links to the key will be automatically garbage collected | |
| 1109 | + * after the timeout expires. | |
| 1110 | + * | |
| 1111 | + * Negative keys are used to rate limit repeated request_key() calls by causing | |
| 1112 | + * them to return the specified error code until the negative key expires. | |
| 1113 | + * | |
| 1114 | + * If successful, 0 will be returned. | |
| 1115 | + */ | |
| 1116 | +long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error, | |
| 1117 | + key_serial_t ringid) | |
| 1015 | 1118 | { |
| 1016 | 1119 | const struct cred *cred = current_cred(); |
| 1017 | 1120 | struct request_key_auth *rka; |
| 1018 | 1121 | struct key *instkey, *dest_keyring; |
| 1019 | 1122 | long ret; |
| 1020 | 1123 | |
| 1021 | − kenter("%d,%u,%d", id, timeout, ringid); | |
| 1124 | + kenter("%d,%u,%u,%d", id, timeout, error, ringid); | |
| 1125 | + | |
| 1126 | + /* must be a valid error code and mustn't be a kernel special */ | |
| 1127 | + if (error <= 0 || | |
| 1128 | + error >= MAX_ERRNO || | |
| 1129 | + error == ERESTARTSYS || | |
| 1130 | + error == ERESTARTNOINTR || | |
| 1131 | + error == ERESTARTNOHAND || | |
| 1132 | + error == ERESTART_RESTARTBLOCK) | |
| 1133 | + return -EINVAL; | |
| 1022 | 1134 | |
| 1023 | 1135 | /* the appropriate instantiation authorisation key must have been |
| 1024 | 1136 | * assumed before calling this */ |
| @@ -1038,7 +1150,7 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) · 13 unmodified lines | ||
| 1038 | 1150 | goto error; |
| 1039 | 1151 | |
| 1040 | 1152 | /* instantiate the key and link it into a keyring */ |
| 1041 | − ret = key_negate_and_link(rka->target_key, timeout, | |
| 1153 | + ret = key_reject_and_link(rka->target_key, timeout, error, | |
| 1042 | 1154 | dest_keyring, instkey); |
| 1043 | 1155 | |
| 1044 | 1156 | key_put(dest_keyring); |
| @@ -1492,6 +1604,19 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, · 447 unmodified lines | ||
| 1492 | 1604 | case KEYCTL_SESSION_TO_PARENT: |
| 1493 | 1605 | return keyctl_session_to_parent(); |
| 1494 | 1606 | |
| 1607 | + case KEYCTL_REJECT: | |
| 1608 | + return keyctl_reject_key((key_serial_t) arg2, | |
| 1609 | + (unsigned) arg3, | |
| 1610 | + (unsigned) arg4, | |
| 1611 | + (key_serial_t) arg5); | |
| 1612 | + | |
| 1613 | + case KEYCTL_INSTANTIATE_IOV: | |
| 1614 | + return keyctl_instantiate_key_iov( | |
| 1615 | + (key_serial_t) arg2, | |
| 1616 | + (const struct iovec __user *) arg3, | |
| 1617 | + (unsigned) arg4, | |
| 1618 | + (key_serial_t) arg5); | |
| 1619 | + | |
| 1495 | 1620 | default: |
| 1496 | 1621 | return -EOPNOTSUPP; |
| 1497 | 1622 | } |
| @@ -352,7 +352,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, · 351 unmodified lines | ||
| 352 | 352 | goto error_2; |
| 353 | 353 | if (key->expiry && now.tv_sec >= key->expiry) |
| 354 | 354 | goto error_2; |
| 355 | − key_ref = ERR_PTR(-ENOKEY); | |
| 355 | + key_ref = ERR_PTR(key->type_data.reject_error); | |
| 356 | 356 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) |
| 357 | 357 | goto error_2; |
| 358 | 358 | goto found; |
| @@ -401,7 +401,7 @@ descend: · 42 unmodified lines | ||
| 401 | 401 | |
| 402 | 402 | /* we set a different error code if we pass a negative key */ |
| 403 | 403 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) { |
| 404 | − err = -ENOKEY; | |
| 404 | + err = key->type_data.reject_error; | |
| 405 | 405 | continue; |
| 406 | 406 | } |
| 407 | 407 | |
| @@ -585,7 +585,7 @@ int wait_for_key_construction(struct key *key, bool intr) · 584 unmodified lines | ||
| 585 | 585 | if (ret < 0) |
| 586 | 586 | return ret; |
| 587 | 587 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) |
| 588 | − return -ENOKEY; | |
| 588 | + return key->type_data.reject_error; | |
| 589 | 589 | return key_validate(key); |
| 590 | 590 | } |
| 591 | 591 | EXPORT_SYMBOL(wait_for_key_construction); |
| @@ -1076,8 +1076,7 @@ static long trusted_read(const struct key *key, char __user *buffer, · 1075 unmodified lines | ||
| 1076 | 1076 | char *bufp; |
| 1077 | 1077 | int i; |
| 1078 | 1078 | |
| 1079 | − p = rcu_dereference_protected(key->payload.data, | |
| 1080 | − rwsem_is_locked(&((struct key *)key)->sem)); | |
| 1079 | + p = rcu_dereference_key(key); | |
| 1081 | 1080 | if (!p) |
| 1082 | 1081 | return -EINVAL; |
| 1083 | 1082 | if (!buffer || buflen <= 0) |
| @@ -184,8 +184,7 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen) · 183 unmodified lines | ||
| 184 | 184 | struct user_key_payload *upayload; |
| 185 | 185 | long ret; |
| 186 | 186 | |
| 187 | − upayload = rcu_dereference_protected( | |
| 188 | − key->payload.data, rwsem_is_locked(&((struct key *)key)->sem)); | |
| 187 | + upayload = rcu_dereference_key(key); | |
| 189 | 188 | ret = upayload->datalen; |
| 190 | 189 | |
| 191 | 190 | /* we can return the data as is */ |
| @@ -181,11 +181,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap) · 180 unmodified lines | ||
| 181 | 181 | return ret; |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | −int security_sysctl(struct ctl_table *table, int op) | |
| 185 | −{ | |
| 186 | − return security_ops->sysctl(table, op); | |
| 187 | −} | |
| 188 | − | |
| 189 | 184 | int security_quotactl(int cmds, int type, int id, struct super_block *sb) |
| 190 | 185 | { |
| 191 | 186 | return security_ops->quotactl(cmds, type, id, sb); |
| @@ -271,6 +266,11 @@ int security_sb_copy_data(char *orig, char *copy) · 79 unmodified lines | ||
| 271 | 266 | } |
| 272 | 267 | EXPORT_SYMBOL(security_sb_copy_data); |
| 273 | 268 | |
| 269 | +int security_sb_remount(struct super_block *sb, void *data) | |
| 270 | +{ | |
| 271 | + return security_ops->sb_remount(sb, data); | |
| 272 | +} | |
| 273 | + | |
| 274 | 274 | int security_sb_kern_mount(struct super_block *sb, int flags, void *data) |
| 275 | 275 | { |
| 276 | 276 | return security_ops->sb_kern_mount(sb, flags, data); |
| @@ -335,11 +335,13 @@ void security_inode_free(struct inode *inode) · 58 unmodified lines | ||
| 335 | 335 | } |
| 336 | 336 | |
| 337 | 337 | int security_inode_init_security(struct inode *inode, struct inode *dir, |
| 338 | − char **name, void **value, size_t *len) | |
| 338 | + const struct qstr *qstr, char **name, | |
| 339 | + void **value, size_t *len) | |
| 339 | 340 | { |
| 340 | 341 | if (unlikely(IS_PRIVATE(inode))) |
| 341 | 342 | return -EOPNOTSUPP; |
| 342 | − return security_ops->inode_init_security(inode, dir, name, value, len); | |
| 343 | + return security_ops->inode_init_security(inode, dir, qstr, name, value, | |
| 344 | + len); | |
| 343 | 345 | } |
| 344 | 346 | EXPORT_SYMBOL(security_inode_init_security); |
| 345 | 347 | |
| @@ -359,6 +361,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode) · 13 unmodified lines | ||
| 359 | 361 | return 0; |
| 360 | 362 | return security_ops->path_mkdir(dir, dentry, mode); |
| 361 | 363 | } |
| 364 | +EXPORT_SYMBOL(security_path_mkdir); | |
| 362 | 365 | |
| 363 | 366 | int security_path_rmdir(struct path *dir, struct dentry *dentry) |
| 364 | 367 | { |
| @@ -373,6 +376,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry) · 8 unmodified lines | ||
| 373 | 376 | return 0; |
| 374 | 377 | return security_ops->path_unlink(dir, dentry); |
| 375 | 378 | } |
| 379 | +EXPORT_SYMBOL(security_path_unlink); | |
| 376 | 380 | |
| 377 | 381 | int security_path_symlink(struct path *dir, struct dentry *dentry, |
| 378 | 382 | const char *old_name) |
| @@ -399,6 +403,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry, · 20 unmodified lines | ||
| 399 | 403 | return security_ops->path_rename(old_dir, old_dentry, new_dir, |
| 400 | 404 | new_dentry); |
| 401 | 405 | } |
| 406 | +EXPORT_SYMBOL(security_path_rename); | |
| 402 | 407 | |
| 403 | 408 | int security_path_truncate(struct path *path) |
| 404 | 409 | { |
| @@ -24,9 +24,11 @@ · 23 unmodified lines | ||
| 24 | 24 | */ |
| 25 | 25 | |
| 26 | 26 | #include <linux/init.h> |
| 27 | +#include <linux/kd.h> | |
| 27 | 28 | #include <linux/kernel.h> |
| 28 | 29 | #include <linux/tracehook.h> |
| 29 | 30 | #include <linux/errno.h> |
| 31 | +#include <linux/ext2_fs.h> | |
| 30 | 32 | #include <linux/sched.h> |
| 31 | 33 | #include <linux/security.h> |
| 32 | 34 | #include <linux/xattr.h> |
| @@ -36,14 +38,15 @@ · 3 unmodified lines | ||
| 36 | 38 | #include <linux/mman.h> |
| 37 | 39 | #include <linux/slab.h> |
| 38 | 40 | #include <linux/pagemap.h> |
| 41 | +#include <linux/proc_fs.h> | |
| 39 | 42 | #include <linux/swap.h> |
| 40 | 43 | #include <linux/spinlock.h> |
| 41 | 44 | #include <linux/syscalls.h> |
| 45 | +#include <linux/dcache.h> | |
| 42 | 46 | #include <linux/file.h> |
| 43 | 47 | #include <linux/fdtable.h> |
| 44 | 48 | #include <linux/namei.h> |
| 45 | 49 | #include <linux/mount.h> |
| 46 | −#include <linux/proc_fs.h> | |
| 47 | 50 | #include <linux/netfilter_ipv4.h> |
| 48 | 51 | #include <linux/netfilter_ipv6.h> |
| 49 | 52 | #include <linux/tty.h> |
| @@ -70,7 +73,6 @@ · 20 unmodified lines | ||
| 70 | 73 | #include <net/ipv6.h> |
| 71 | 74 | #include <linux/hugetlb.h> |
| 72 | 75 | #include <linux/personality.h> |
| 73 | −#include <linux/sysctl.h> | |
| 74 | 76 | #include <linux/audit.h> |
| 75 | 77 | #include <linux/string.h> |
| 76 | 78 | #include <linux/selinux.h> |
| @@ -1120,39 +1122,35 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc · 1043 unmodified lines | ||
| 1120 | 1122 | } |
| 1121 | 1123 | |
| 1122 | 1124 | #ifdef CONFIG_PROC_FS |
| 1123 | −static int selinux_proc_get_sid(struct proc_dir_entry *de, | |
| 1125 | +static int selinux_proc_get_sid(struct dentry *dentry, | |
| 1124 | 1126 | u16 tclass, |
| 1125 | 1127 | u32 *sid) |
| 1126 | 1128 | { |
| 1127 | − int buflen, rc; | |
| 1128 | − char *buffer, *path, *end; | |
| 1129 | + int rc; | |
| 1130 | + char *buffer, *path; | |
| 1129 | 1131 | |
| 1130 | 1132 | buffer = (char *)__get_free_page(GFP_KERNEL); |
| 1131 | 1133 | if (!buffer) |
| 1132 | 1134 | return -ENOMEM; |
| 1133 | 1135 | |
| 1134 | − buflen = PAGE_SIZE; | |
| 1135 | − end = buffer+buflen; | |
| 1136 | − *--end = '\0'; | |
| 1137 | − buflen--; | |
| 1138 | − path = end-1; | |
| 1139 | − *path = '/'; | |
| 1140 | − while (de && de != de->parent) { | |
| 1141 | − buflen -= de->namelen + 1; | |
| 1142 | − if (buflen < 0) | |
| 1143 | − break; | |
| 1144 | − end -= de->namelen; | |
| 1145 | − memcpy(end, de->name, de->namelen); | |
| 1146 | − *--end = '/'; | |
| 1147 | − path = end; | |
| 1148 | − de = de->parent; | |
| 1136 | + path = dentry_path_raw(dentry, buffer, PAGE_SIZE); | |
| 1137 | + if (IS_ERR(path)) | |
| 1138 | + rc = PTR_ERR(path); | |
| 1139 | + else { | |
| 1140 | + /* each process gets a /proc/PID/ entry. Strip off the | |
| 1141 | + * PID part to get a valid selinux labeling. | |
| 1142 | + * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ | |
| 1143 | + while (path[1] >= '0' && path[1] <= '9') { | |
| 1144 | + path[1] = '/'; | |
| 1145 | + path++; | |
| 1146 | + } | |
| 1147 | + rc = security_genfs_sid("proc", path, tclass, sid); | |
| 1149 | 1148 | } |
| 1150 | − rc = security_genfs_sid("proc", path, tclass, sid); | |
| 1151 | 1149 | free_page((unsigned long)buffer); |
| 1152 | 1150 | return rc; |
| 1153 | 1151 | } |
| 1154 | 1152 | #else |
| 1155 | −static int selinux_proc_get_sid(struct proc_dir_entry *de, | |
| 1153 | +static int selinux_proc_get_sid(struct dentry *dentry, | |
| 1156 | 1154 | u16 tclass, |
| 1157 | 1155 | u32 *sid) |
| 1158 | 1156 | { |
| @@ -1300,10 +1298,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent · 141 unmodified lines | ||
| 1300 | 1298 | |
| 1301 | 1299 | /* Try to obtain a transition SID. */ |
| 1302 | 1300 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
| 1303 | − rc = security_transition_sid(isec->task_sid, | |
| 1304 | − sbsec->sid, | |
| 1305 | − isec->sclass, | |
| 1306 | − &sid); | |
| 1301 | + rc = security_transition_sid(isec->task_sid, sbsec->sid, | |
| 1302 | + isec->sclass, NULL, &sid); | |
| 1307 | 1303 | if (rc) |
| 1308 | 1304 | goto out_unlock; |
| 1309 | 1305 | isec->sid = sid; |
| @@ -1316,10 +1312,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent · 6 unmodified lines | ||
| 1316 | 1312 | isec->sid = sbsec->sid; |
| 1317 | 1313 | |
| 1318 | 1314 | if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { |
| 1319 | − struct proc_inode *proci = PROC_I(inode); | |
| 1320 | − if (proci->pde) { | |
| 1315 | + if (opt_dentry) { | |
| 1321 | 1316 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
| 1322 | − rc = selinux_proc_get_sid(proci->pde, | |
| 1317 | + rc = selinux_proc_get_sid(opt_dentry, | |
| 1323 | 1318 | isec->sclass, |
| 1324 | 1319 | &sid); |
| 1325 | 1320 | if (rc) |
| @@ -1578,7 +1573,7 @@ static int may_create(struct inode *dir, · 252 unmodified lines | ||
| 1578 | 1573 | return rc; |
| 1579 | 1574 | |
| 1580 | 1575 | if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { |
| 1581 | − rc = security_transition_sid(sid, dsec->sid, tclass, &newsid); | |
| 1576 | + rc = security_transition_sid(sid, dsec->sid, tclass, NULL, &newsid); | |
| 1582 | 1577 | if (rc) |
| 1583 | 1578 | return rc; |
| 1584 | 1579 | } |
| @@ -1862,82 +1857,6 @@ static int selinux_capable(struct task_struct *tsk, const struct cred *cred, · 277 unmodified lines | ||
| 1862 | 1857 | return task_has_capability(tsk, cred, cap, audit); |
| 1863 | 1858 | } |
| 1864 | 1859 | |
| 1865 | −static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid) | |
| 1866 | −{ | |
| 1867 | − int buflen, rc; | |
| 1868 | − char *buffer, *path, *end; | |
| 1869 | − | |
| 1870 | − rc = -ENOMEM; | |
| 1871 | − buffer = (char *)__get_free_page(GFP_KERNEL); | |
| 1872 | − if (!buffer) | |
| 1873 | − goto out; | |
| 1874 | − | |
| 1875 | − buflen = PAGE_SIZE; | |
| 1876 | − end = buffer+buflen; | |
| 1877 | − *--end = '\0'; | |
| 1878 | − buflen--; | |
| 1879 | − path = end-1; | |
| 1880 | − *path = '/'; | |
| 1881 | − while (table) { | |
| 1882 | − const char *name = table->procname; | |
| 1883 | − size_t namelen = strlen(name); | |
| 1884 | − buflen -= namelen + 1; | |
| 1885 | − if (buflen < 0) | |
| 1886 | − goto out_free; | |
| 1887 | − end -= namelen; | |
| 1888 | − memcpy(end, name, namelen); | |
| 1889 | − *--end = '/'; | |
| 1890 | − path = end; | |
| 1891 | − table = table->parent; | |
| 1892 | − } | |
| 1893 | − buflen -= 4; | |
| 1894 | − if (buflen < 0) | |
| 1895 | − goto out_free; | |
| 1896 | − end -= 4; | |
| 1897 | − memcpy(end, "/sys", 4); | |
| 1898 | − path = end; | |
| 1899 | − rc = security_genfs_sid("proc", path, tclass, sid); | |
| 1900 | −out_free: | |
| 1901 | − free_page((unsigned long)buffer); | |
| 1902 | −out: | |
| 1903 | − return rc; | |
| 1904 | −} | |
| 1905 | − | |
| 1906 | −static int selinux_sysctl(ctl_table *table, int op) | |
| 1907 | −{ | |
| 1908 | − int error = 0; | |
| 1909 | − u32 av; | |
| 1910 | − u32 tsid, sid; | |
| 1911 | − int rc; | |
| 1912 | − | |
| 1913 | − sid = current_sid(); | |
| 1914 | − | |
| 1915 | − rc = selinux_sysctl_get_sid(table, (op == 0001) ? | |
| 1916 | − SECCLASS_DIR : SECCLASS_FILE, &tsid); | |
| 1917 | − if (rc) { | |
| 1918 | − /* Default to the well-defined sysctl SID. */ | |
| 1919 | − tsid = SECINITSID_SYSCTL; | |
| 1920 | − } | |
| 1921 | − | |
| 1922 | − /* The op values are "defined" in sysctl.c, thereby creating | |
| 1923 | − * a bad coupling between this module and sysctl.c */ | |
| 1924 | − if (op == 001) { | |
| 1925 | − error = avc_has_perm(sid, tsid, | |
| 1926 | − SECCLASS_DIR, DIR__SEARCH, NULL); | |
| 1927 | − } else { | |
| 1928 | − av = 0; | |
| 1929 | − if (op & 004) | |
| 1930 | − av |= FILE__READ; | |
| 1931 | − if (op & 002) | |
| 1932 | − av |= FILE__WRITE; | |
| 1933 | − if (av) | |
| 1934 | − error = avc_has_perm(sid, tsid, | |
| 1935 | − SECCLASS_FILE, av, NULL); | |
| 1936 | − } | |
| 1937 | − | |
| 1938 | − return error; | |
| 1939 | −} | |
| 1940 | − | |
| 1941 | 1860 | static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) |
| 1942 | 1861 | { |
| 1943 | 1862 | const struct cred *cred = current_cred(); |
| @@ -2060,7 +1979,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) · 116 unmodified lines | ||
| 2060 | 1979 | } else { |
| 2061 | 1980 | /* Check for a default transition on this program. */ |
| 2062 | 1981 | rc = security_transition_sid(old_tsec->sid, isec->sid, |
| 2063 | − SECCLASS_PROCESS, &new_tsec->sid); | |
| 1982 | + SECCLASS_PROCESS, NULL, | |
| 1983 | + &new_tsec->sid); | |
| 2064 | 1984 | if (rc) |
| 2065 | 1985 | return rc; |
| 2066 | 1986 | } |
| @@ -2443,6 +2363,91 @@ out: · 376 unmodified lines | ||
| 2443 | 2363 | return rc; |
| 2444 | 2364 | } |
| 2445 | 2365 | |
| 2366 | +static int selinux_sb_remount(struct super_block *sb, void *data) | |
| 2367 | +{ | |
| 2368 | + int rc, i, *flags; | |
| 2369 | + struct security_mnt_opts opts; | |
| 2370 | + char *secdata, **mount_options; | |
| 2371 | + struct superblock_security_struct *sbsec = sb->s_security; | |
| 2372 | + | |
| 2373 | + if (!(sbsec->flags & SE_SBINITIALIZED)) | |
| 2374 | + return 0; | |
| 2375 | + | |
| 2376 | + if (!data) | |
| 2377 | + return 0; | |
| 2378 | + | |
| 2379 | + if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) | |
| 2380 | + return 0; | |
| 2381 | + | |
| 2382 | + security_init_mnt_opts(&opts); | |
| 2383 | + secdata = alloc_secdata(); | |
| 2384 | + if (!secdata) | |
| 2385 | + return -ENOMEM; | |
| 2386 | + rc = selinux_sb_copy_data(data, secdata); | |
| 2387 | + if (rc) | |
| 2388 | + goto out_free_secdata; | |
| 2389 | + | |
| 2390 | + rc = selinux_parse_opts_str(secdata, &opts); | |
| 2391 | + if (rc) | |
| 2392 | + goto out_free_secdata; | |
| 2393 | + | |
| 2394 | + mount_options = opts.mnt_opts; | |
| 2395 | + flags = opts.mnt_opts_flags; | |
| 2396 | + | |
| 2397 | + for (i = 0; i < opts.num_mnt_opts; i++) { | |
| 2398 | + u32 sid; | |
| 2399 | + size_t len; | |
| 2400 | + | |
| 2401 | + if (flags[i] == SE_SBLABELSUPP) | |
| 2402 | + continue; | |
| 2403 | + len = strlen(mount_options[i]); | |
| 2404 | + rc = security_context_to_sid(mount_options[i], len, &sid); | |
| 2405 | + if (rc) { | |
| 2406 | + printk(KERN_WARNING "SELinux: security_context_to_sid" | |
| 2407 | + "(%s) failed for (dev %s, type %s) errno=%d\n", | |
| 2408 | + mount_options[i], sb->s_id, sb->s_type->name, rc); | |
| 2409 | + goto out_free_opts; | |
| 2410 | + } | |
| 2411 | + rc = -EINVAL; | |
| 2412 | + switch (flags[i]) { | |
| 2413 | + case FSCONTEXT_MNT: | |
| 2414 | + if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) | |
| 2415 | + goto out_bad_option; | |
| 2416 | + break; | |
| 2417 | + case CONTEXT_MNT: | |
| 2418 | + if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) | |
| 2419 | + goto out_bad_option; | |
| 2420 | + break; | |
| 2421 | + case ROOTCONTEXT_MNT: { | |
| 2422 | + struct inode_security_struct *root_isec; | |
| 2423 | + root_isec = sb->s_root->d_inode->i_security; | |
| 2424 | + | |
| 2425 | + if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) | |
| 2426 | + goto out_bad_option; | |
| 2427 | + break; | |
| 2428 | + } | |
| 2429 | + case DEFCONTEXT_MNT: | |
| 2430 | + if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) | |
| 2431 | + goto out_bad_option; | |
| 2432 | + break; | |
| 2433 | + default: | |
| 2434 | + goto out_free_opts; | |
| 2435 | + } | |
| 2436 | + } | |
| 2437 | + | |
| 2438 | + rc = 0; | |
| 2439 | +out_free_opts: | |
| 2440 | + security_free_mnt_opts(&opts); | |
| 2441 | +out_free_secdata: | |
| 2442 | + free_secdata(secdata); | |
| 2443 | + return rc; | |
| 2444 | +out_bad_option: | |
| 2445 | + printk(KERN_WARNING "SELinux: unable to change security options " | |
| 2446 | + "during remount (dev %s, type=%s)\n", sb->s_id, | |
| 2447 | + sb->s_type->name); | |
| 2448 | + goto out_free_opts; | |
| 2449 | +} | |
| 2450 | + | |
| 2446 | 2451 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) |
| 2447 | 2452 | { |
| 2448 | 2453 | const struct cred *cred = current_cred(); |
| @@ -2509,8 +2514,8 @@ static void selinux_inode_free_security(struct inode *inode) · 60 unmodified lines | ||
| 2509 | 2514 | } |
| 2510 | 2515 | |
| 2511 | 2516 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, |
| 2512 | − char **name, void **value, | |
| 2513 | − size_t *len) | |
| 2517 | + const struct qstr *qstr, char **name, | |
| 2518 | + void **value, size_t *len) | |
| 2514 | 2519 | { |
| 2515 | 2520 | const struct task_security_struct *tsec = current_security(); |
| 2516 | 2521 | struct inode_security_struct *dsec; |
| @@ -2531,7 +2536,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, · 14 unmodified lines | ||
| 2531 | 2536 | else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { |
| 2532 | 2537 | rc = security_transition_sid(sid, dsec->sid, |
| 2533 | 2538 | inode_mode_to_security_class(inode->i_mode), |
| 2534 | − &newsid); | |
| 2539 | + qstr, &newsid); | |
| 2535 | 2540 | if (rc) { |
| 2536 | 2541 | printk(KERN_WARNING "%s: " |
| 2537 | 2542 | "security_transition_sid failed, rc=%d (dev=%s " |
| @@ -2932,16 +2937,47 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, · 394 unmodified lines | ||
| 2932 | 2937 | unsigned long arg) |
| 2933 | 2938 | { |
| 2934 | 2939 | const struct cred *cred = current_cred(); |
| 2935 | − u32 av = 0; | |
| 2940 | + int error = 0; | |
| 2936 | 2941 | |
| 2937 | − if (_IOC_DIR(cmd) & _IOC_WRITE) | |
| 2938 | − av |= FILE__WRITE; | |
| 2939 | − if (_IOC_DIR(cmd) & _IOC_READ) | |
| 2940 | − av |= FILE__READ; | |
| 2941 | − if (!av) | |
| 2942 | − av = FILE__IOCTL; | |
| 2942 | + switch (cmd) { | |
| 2943 | + case FIONREAD: | |
| 2944 | + /* fall through */ | |
| 2945 | + case FIBMAP: | |
| 2946 | + /* fall through */ | |
| 2947 | + case FIGETBSZ: | |
| 2948 | + /* fall through */ | |
| 2949 | + case EXT2_IOC_GETFLAGS: | |
| 2950 | + /* fall through */ | |
| 2951 | + case EXT2_IOC_GETVERSION: | |
| 2952 | + error = file_has_perm(cred, file, FILE__GETATTR); | |
| 2953 | + break; | |
| 2954 | + | |
| 2955 | + case EXT2_IOC_SETFLAGS: | |
| 2956 | + /* fall through */ | |
| 2957 | + case EXT2_IOC_SETVERSION: | |
| 2958 | + error = file_has_perm(cred, file, FILE__SETATTR); | |
| 2959 | + break; | |
| 2960 | + | |
| 2961 | + /* sys_ioctl() checks */ | |
| 2962 | + case FIONBIO: | |
| 2963 | + /* fall through */ | |
| 2964 | + case FIOASYNC: | |
| 2965 | + error = file_has_perm(cred, file, 0); | |
| 2966 | + break; | |
| 2943 | 2967 | |
| 2944 | − return file_has_perm(cred, file, av); | |
| 2968 | + case KDSKBENT: | |
| 2969 | + case KDSKBSENT: | |
| 2970 | + error = task_has_capability(current, cred, CAP_SYS_TTY_CONFIG, | |
| 2971 | + SECURITY_CAP_AUDIT); | |
| 2972 | + break; | |
| 2973 | + | |
| 2974 | + /* default case assumes that the command will go | |
| 2975 | + * to the file's ioctl() function. | |
| 2976 | + */ | |
| 2977 | + default: | |
| 2978 | + error = file_has_perm(cred, file, FILE__IOCTL); | |
| 2979 | + } | |
| 2980 | + return error; | |
| 2945 | 2981 | } |
| 2946 | 2982 | |
| 2947 | 2983 | static int default_noexec; |
| @@ -3644,9 +3680,16 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) · 696 unmodified lines | ||
| 3644 | 3680 | |
| 3645 | 3681 | /* socket security operations */ |
| 3646 | 3682 | |
| 3647 | −static u32 socket_sockcreate_sid(const struct task_security_struct *tsec) | |
| 3683 | +static int socket_sockcreate_sid(const struct task_security_struct *tsec, | |
| 3684 | + u16 secclass, u32 *socksid) | |
| 3648 | 3685 | { |
| 3649 | − return tsec->sockcreate_sid ? : tsec->sid; | |
| 3686 | + if (tsec->sockcreate_sid > SECSID_NULL) { | |
| 3687 | + *socksid = tsec->sockcreate_sid; | |
| 3688 | + return 0; | |
| 3689 | + } | |
| 3690 | + | |
| 3691 | + return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL, | |
| 3692 | + socksid); | |
| 3650 | 3693 | } |
| 3651 | 3694 | |
| 3652 | 3695 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) |
| @@ -3670,12 +3713,16 @@ static int selinux_socket_create(int family, int type, · 17 unmodified lines | ||
| 3670 | 3713 | const struct task_security_struct *tsec = current_security(); |
| 3671 | 3714 | u32 newsid; |
| 3672 | 3715 | u16 secclass; |
| 3716 | + int rc; | |
| 3673 | 3717 | |
| 3674 | 3718 | if (kern) |
| 3675 | 3719 | return 0; |
| 3676 | 3720 | |
| 3677 | − newsid = socket_sockcreate_sid(tsec); | |
| 3678 | 3721 | secclass = socket_type_to_security_class(family, type, protocol); |
| 3722 | + rc = socket_sockcreate_sid(tsec, secclass, &newsid); | |
| 3723 | + if (rc) | |
| 3724 | + return rc; | |
| 3725 | + | |
| 3679 | 3726 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); |
| 3680 | 3727 | } |
| 3681 | 3728 | |
| @@ -3687,12 +3734,16 @@ static int selinux_socket_post_create(struct socket *sock, int family, · 5 unmodified lines | ||
| 3687 | 3734 | struct sk_security_struct *sksec; |
| 3688 | 3735 | int err = 0; |
| 3689 | 3736 | |
| 3737 | + isec->sclass = socket_type_to_security_class(family, type, protocol); | |
| 3738 | + | |
| 3690 | 3739 | if (kern) |
| 3691 | 3740 | isec->sid = SECINITSID_KERNEL; |
| 3692 | − else | |
| 3693 | − isec->sid = socket_sockcreate_sid(tsec); | |
| 3741 | + else { | |
| 3742 | + err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid)); | |
| 3743 | + if (err) | |
| 3744 | + return err; | |
| 3745 | + } | |
| 3694 | 3746 | |
| 3695 | − isec->sclass = socket_type_to_security_class(family, type, protocol); | |
| 3696 | 3747 | isec->initialized = 1; |
| 3697 | 3748 | |
| 3698 | 3749 | if (sock->sk) { |
| @@ -4002,7 +4053,6 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, · 303 unmodified lines | ||
| 4002 | 4053 | { |
| 4003 | 4054 | int err = 0; |
| 4004 | 4055 | struct sk_security_struct *sksec = sk->sk_security; |
| 4005 | − u32 peer_sid; | |
| 4006 | 4056 | u32 sk_sid = sksec->sid; |
| 4007 | 4057 | struct common_audit_data ad; |
| 4008 | 4058 | char *addrp; |
| @@ -4021,20 +4071,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, · 12 unmodified lines | ||
| 4021 | 4071 | return err; |
| 4022 | 4072 | } |
| 4023 | 4073 | |
| 4024 | − if (selinux_policycap_netpeer) { | |
| 4025 | − err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); | |
| 4026 | − if (err) | |
| 4027 | − return err; | |
| 4028 | − err = avc_has_perm(sk_sid, peer_sid, | |
| 4029 | − SECCLASS_PEER, PEER__RECV, &ad); | |
| 4030 | − if (err) | |
| 4031 | − selinux_netlbl_err(skb, err, 0); | |
| 4032 | − } else { | |
| 4033 | − err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); | |
| 4034 | − if (err) | |
| 4035 | − return err; | |
| 4036 | − err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); | |
| 4037 | − } | |
| 4074 | + err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); | |
| 4075 | + if (err) | |
| 4076 | + return err; | |
| 4077 | + err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); | |
| 4038 | 4078 | |
| 4039 | 4079 | return err; |
| 4040 | 4080 | } |
| @@ -4529,9 +4569,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, · 488 unmodified lines | ||
| 4529 | 4569 | SECCLASS_PACKET, PACKET__SEND, &ad)) |
| 4530 | 4570 | return NF_DROP_ERR(-ECONNREFUSED); |
| 4531 | 4571 | |
| 4532 | − if (selinux_policycap_netpeer) | |
| 4533 | − if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) | |
| 4534 | − return NF_DROP_ERR(-ECONNREFUSED); | |
| 4572 | + if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) | |
| 4573 | + return NF_DROP_ERR(-ECONNREFUSED); | |
| 4535 | 4574 | |
| 4536 | 4575 | return NF_ACCEPT; |
| 4537 | 4576 | } |
| @@ -4574,27 +4613,14 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, · 36 unmodified lines | ||
| 4574 | 4613 | * from the sending socket, otherwise use the kernel's sid */ |
| 4575 | 4614 | sk = skb->sk; |
| 4576 | 4615 | if (sk == NULL) { |
| 4577 | − switch (family) { | |
| 4578 | − case PF_INET: | |
| 4579 | − if (IPCB(skb)->flags & IPSKB_FORWARDED) | |
| 4580 | − secmark_perm = PACKET__FORWARD_OUT; | |
| 4581 | − else | |
| 4582 | − secmark_perm = PACKET__SEND; | |
| 4583 | − break; | |
| 4584 | − case PF_INET6: | |
| 4585 | − if (IP6CB(skb)->flags & IP6SKB_FORWARDED) | |
| 4586 | − secmark_perm = PACKET__FORWARD_OUT; | |
| 4587 | − else | |
| 4588 | − secmark_perm = PACKET__SEND; | |
| 4589 | − break; | |
| 4590 | − default: | |
| 4591 | − return NF_DROP_ERR(-ECONNREFUSED); | |
| 4592 | − } | |
| 4593 | − if (secmark_perm == PACKET__FORWARD_OUT) { | |
| 4616 | + if (skb->skb_iif) { | |
| 4617 | + secmark_perm = PACKET__FORWARD_OUT; | |
| 4594 | 4618 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) |
| 4595 | 4619 | return NF_DROP; |
| 4596 | − } else | |
| 4620 | + } else { | |
| 4621 | + secmark_perm = PACKET__SEND; | |
| 4597 | 4622 | peer_sid = SECINITSID_KERNEL; |
| 4623 | + } | |
| 4598 | 4624 | } else { |
| 4599 | 4625 | struct sk_security_struct *sksec = sk->sk_security; |
| 4600 | 4626 | peer_sid = sksec->sid; |
| @@ -4848,7 +4874,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, · 247 unmodified lines | ||
| 4848 | 4874 | * message queue this message will be stored in |
| 4849 | 4875 | */ |
| 4850 | 4876 | rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG, |
| 4851 | − &msec->sid); | |
| 4877 | + NULL, &msec->sid); | |
| 4852 | 4878 | if (rc) |
| 4853 | 4879 | return rc; |
| 4854 | 4880 | } |
| @@ -5402,7 +5428,6 @@ static struct security_operations selinux_ops = { · 547 unmodified lines | ||
| 5402 | 5428 | .ptrace_traceme = selinux_ptrace_traceme, |
| 5403 | 5429 | .capget = selinux_capget, |
| 5404 | 5430 | .capset = selinux_capset, |
| 5405 | − .sysctl = selinux_sysctl, | |
| 5406 | 5431 | .capable = selinux_capable, |
| 5407 | 5432 | .quotactl = selinux_quotactl, |
| 5408 | 5433 | .quota_on = selinux_quota_on, |
| @@ -5420,6 +5445,7 @@ static struct security_operations selinux_ops = { · 11 unmodified lines | ||
| 5420 | 5445 | .sb_alloc_security = selinux_sb_alloc_security, |
| 5421 | 5446 | .sb_free_security = selinux_sb_free_security, |
| 5422 | 5447 | .sb_copy_data = selinux_sb_copy_data, |
| 5448 | + .sb_remount = selinux_sb_remount, | |
| 5423 | 5449 | .sb_kern_mount = selinux_sb_kern_mount, |
| 5424 | 5450 | .sb_show_options = selinux_sb_show_options, |
| 5425 | 5451 | .sb_statfs = selinux_sb_statfs, |
| @@ -12,6 +12,10 @@ · 11 unmodified lines | ||
| 12 | 12 | #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \ |
| 13 | 13 | "write", "associate", "unix_read", "unix_write" |
| 14 | 14 | |
| 15 | +/* | |
| 16 | + * Note: The name for any socket class should be suffixed by "socket", | |
| 17 | + * and doesn't contain more than one substr of "socket". | |
| 18 | + */ | |
| 15 | 19 | struct security_class_mapping secclass_map[] = { |
| 16 | 20 | { "security", |
| 17 | 21 | { "compute_av", "compute_create", "compute_member", |
| @@ -132,8 +136,7 @@ struct security_class_mapping secclass_map[] = { · 114 unmodified lines | ||
| 132 | 136 | { "appletalk_socket", |
| 133 | 137 | { COMMON_SOCK_PERMS, NULL } }, |
| 134 | 138 | { "packet", |
| 135 | − { "send", "recv", "relabelto", "flow_in", "flow_out", | |
| 136 | − "forward_in", "forward_out", NULL } }, | |
| 139 | + { "send", "recv", "relabelto", "forward_in", "forward_out", NULL } }, | |
| 137 | 140 | { "key", |
| 138 | 141 | { "view", "read", "write", "search", "link", "setattr", "create", |
| 139 | 142 | NULL } }, |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #ifndef _SELINUX_SECURITY_H_ |
| 9 | 9 | #define _SELINUX_SECURITY_H_ |
| 10 | 10 | |
| 11 | +#include <linux/dcache.h> | |
| 11 | 12 | #include <linux/magic.h> |
| 12 | 13 | #include <linux/types.h> |
| 13 | 14 | #include "flask.h" |
| @@ -28,13 +29,14 @@ · 14 unmodified lines | ||
| 28 | 29 | #define POLICYDB_VERSION_POLCAP 22 |
| 29 | 30 | #define POLICYDB_VERSION_PERMISSIVE 23 |
| 30 | 31 | #define POLICYDB_VERSION_BOUNDARY 24 |
| 32 | +#define POLICYDB_VERSION_FILENAME_TRANS 25 | |
| 31 | 33 | |
| 32 | 34 | /* Range of policy versions we understand*/ |
| 33 | 35 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
| 34 | 36 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX |
| 35 | 37 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE |
| 36 | 38 | #else |
| 37 | −#define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY | |
| 39 | +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_FILENAME_TRANS | |
| 38 | 40 | #endif |
| 39 | 41 | |
| 40 | 42 | /* Mask for just the mount related flags */ |
| @@ -106,8 +108,8 @@ void security_compute_av(u32 ssid, u32 tsid, · 65 unmodified lines | ||
| 106 | 108 | void security_compute_av_user(u32 ssid, u32 tsid, |
| 107 | 109 | u16 tclass, struct av_decision *avd); |
| 108 | 110 | |
| 109 | −int security_transition_sid(u32 ssid, u32 tsid, | |
| 110 | − u16 tclass, u32 *out_sid); | |
| 111 | +int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, | |
| 112 | + const struct qstr *qstr, u32 *out_sid); | |
| 111 | 113 | |
| 112 | 114 | int security_transition_sid_user(u32 ssid, u32 tsid, |
| 113 | 115 | u16 tclass, u32 *out_sid); |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | * |
| 15 | 15 | * Copyright (C) 2003 Tresys Technology, LLC |
| 16 | 16 | * This program is free software; you can redistribute it and/or modify |
| 17 | − * it under the terms of the GNU General Public License as published by | |
| 17 | + * it under the terms of the GNU General Public License as published by | |
| 18 | 18 | * the Free Software Foundation, version 2. |
| 19 | 19 | * |
| 20 | 20 | * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp> |
| @@ -27,16 +27,16 @@ struct avtab_key { · 6 unmodified lines | ||
| 27 | 27 | u16 source_type; /* source type */ |
| 28 | 28 | u16 target_type; /* target type */ |
| 29 | 29 | u16 target_class; /* target object class */ |
| 30 | −#define AVTAB_ALLOWED 1 | |
| 31 | −#define AVTAB_AUDITALLOW 2 | |
| 32 | −#define AVTAB_AUDITDENY 4 | |
| 33 | −#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) | |
| 34 | −#define AVTAB_TRANSITION 16 | |
| 35 | −#define AVTAB_MEMBER 32 | |
| 36 | −#define AVTAB_CHANGE 64 | |
| 37 | −#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) | |
| 38 | −#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ | |
| 39 | −#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ | |
| 30 | +#define AVTAB_ALLOWED 0x0001 | |
| 31 | +#define AVTAB_AUDITALLOW 0x0002 | |
| 32 | +#define AVTAB_AUDITDENY 0x0004 | |
| 33 | +#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) | |
| 34 | +#define AVTAB_TRANSITION 0x0010 | |
| 35 | +#define AVTAB_MEMBER 0x0020 | |
| 36 | +#define AVTAB_CHANGE 0x0040 | |
| 37 | +#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) | |
| 38 | +#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ | |
| 39 | +#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ | |
| 40 | 40 | u16 specified; /* what field is specified */ |
| 41 | 41 | }; |
| 42 | 42 | |
| @@ -86,7 +86,6 @@ void avtab_cache_destroy(void); · 43 unmodified lines | ||
| 86 | 86 | |
| 87 | 87 | #define MAX_AVTAB_HASH_BITS 11 |
| 88 | 88 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) |
| 89 | −#define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) | |
| 90 | 89 | |
| 91 | 90 | #endif /* _SS_AVTAB_H_ */ |
| 92 | 91 | |
| @@ -36,7 +36,6 @@ struct ebitmap { · 35 unmodified lines | ||
| 36 | 36 | }; |
| 37 | 37 | |
| 38 | 38 | #define ebitmap_length(e) ((e)->highbit) |
| 39 | −#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) | |
| 40 | 39 | |
| 41 | 40 | static inline unsigned int ebitmap_start_positive(struct ebitmap *e, |
| 42 | 41 | struct ebitmap_node **n) |
| @@ -512,7 +512,8 @@ int mls_compute_sid(struct context *scontext, · 511 unmodified lines | ||
| 512 | 512 | struct context *tcontext, |
| 513 | 513 | u16 tclass, |
| 514 | 514 | u32 specified, |
| 515 | − struct context *newcontext) | |
| 515 | + struct context *newcontext, | |
| 516 | + bool sock) | |
| 516 | 517 | { |
| 517 | 518 | struct range_trans rtr; |
| 518 | 519 | struct mls_range *r; |
| @@ -531,7 +532,7 @@ int mls_compute_sid(struct context *scontext, · 12 unmodified lines | ||
| 531 | 532 | return mls_range_set(newcontext, r); |
| 532 | 533 | /* Fallthrough */ |
| 533 | 534 | case AVTAB_CHANGE: |
| 534 | − if (tclass == policydb.process_class) | |
| 535 | + if ((tclass == policydb.process_class) || (sock == true)) | |
| 535 | 536 | /* Use the process MLS attributes. */ |
| 536 | 537 | return mls_context_cpy(newcontext, scontext); |
| 537 | 538 | else |
| @@ -49,7 +49,8 @@ int mls_compute_sid(struct context *scontext, · 48 unmodified lines | ||
| 49 | 49 | struct context *tcontext, |
| 50 | 50 | u16 tclass, |
| 51 | 51 | u32 specified, |
| 52 | − struct context *newcontext); | |
| 52 | + struct context *newcontext, | |
| 53 | + bool sock); | |
| 53 | 54 | |
| 54 | 55 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, |
| 55 | 56 | struct context *usercon); |
| @@ -123,6 +123,11 @@ static struct policydb_compat_info policydb_compat[] = { · 122 unmodified lines | ||
| 123 | 123 | .sym_num = SYM_NUM, |
| 124 | 124 | .ocon_num = OCON_NUM, |
| 125 | 125 | }, |
| 126 | + { | |
| 127 | + .version = POLICYDB_VERSION_FILENAME_TRANS, | |
| 128 | + .sym_num = SYM_NUM, | |
| 129 | + .ocon_num = OCON_NUM, | |
| 130 | + }, | |
| 126 | 131 | }; |
| 127 | 132 | |
| 128 | 133 | static struct policydb_compat_info *policydb_lookup_compat(int version) |
| @@ -704,6 +709,7 @@ void policydb_destroy(struct policydb *p) · 575 unmodified lines | ||
| 704 | 709 | int i; |
| 705 | 710 | struct role_allow *ra, *lra = NULL; |
| 706 | 711 | struct role_trans *tr, *ltr = NULL; |
| 712 | + struct filename_trans *ft, *nft; | |
| 707 | 713 | |
| 708 | 714 | for (i = 0; i < SYM_NUM; i++) { |
| 709 | 715 | cond_resched(); |
| @@ -781,6 +787,15 @@ void policydb_destroy(struct policydb *p) · 71 unmodified lines | ||
| 781 | 787 | } |
| 782 | 788 | flex_array_free(p->type_attr_map_array); |
| 783 | 789 | } |
| 790 | + | |
| 791 | + ft = p->filename_trans; | |
| 792 | + while (ft) { | |
| 793 | + nft = ft->next; | |
| 794 | + kfree(ft->name); | |
| 795 | + kfree(ft); | |
| 796 | + ft = nft; | |
| 797 | + } | |
| 798 | + | |
| 784 | 799 | ebitmap_destroy(&p->policycaps); |
| 785 | 800 | ebitmap_destroy(&p->permissive_map); |
| 786 | 801 | |
| @@ -1788,6 +1803,76 @@ out: · 1001 unmodified lines | ||
| 1788 | 1803 | return rc; |
| 1789 | 1804 | } |
| 1790 | 1805 | |
| 1806 | +static int filename_trans_read(struct policydb *p, void *fp) | |
| 1807 | +{ | |
| 1808 | + struct filename_trans *ft, *last; | |
| 1809 | + u32 nel, len; | |
| 1810 | + char *name; | |
| 1811 | + __le32 buf[4]; | |
| 1812 | + int rc, i; | |
| 1813 | + | |
| 1814 | + if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) | |
| 1815 | + return 0; | |
| 1816 | + | |
| 1817 | + rc = next_entry(buf, fp, sizeof(u32)); | |
| 1818 | + if (rc) | |
| 1819 | + goto out; | |
| 1820 | + nel = le32_to_cpu(buf[0]); | |
| 1821 | + | |
| 1822 | + printk(KERN_ERR "%s: nel=%d\n", __func__, nel); | |
| 1823 | + | |
| 1824 | + last = p->filename_trans; | |
| 1825 | + while (last && last->next) | |
| 1826 | + last = last->next; | |
| 1827 | + | |
| 1828 | + for (i = 0; i < nel; i++) { | |
| 1829 | + rc = -ENOMEM; | |
| 1830 | + ft = kzalloc(sizeof(*ft), GFP_KERNEL); | |
| 1831 | + if (!ft) | |
| 1832 | + goto out; | |
| 1833 | + | |
| 1834 | + /* add it to the tail of the list */ | |
| 1835 | + if (!last) | |
| 1836 | + p->filename_trans = ft; | |
| 1837 | + else | |
| 1838 | + last->next = ft; | |
| 1839 | + last = ft; | |
| 1840 | + | |
| 1841 | + /* length of the path component string */ | |
| 1842 | + rc = next_entry(buf, fp, sizeof(u32)); | |
| 1843 | + if (rc) | |
| 1844 | + goto out; | |
| 1845 | + len = le32_to_cpu(buf[0]); | |
| 1846 | + | |
| 1847 | + rc = -ENOMEM; | |
| 1848 | + name = kmalloc(len + 1, GFP_KERNEL); | |
| 1849 | + if (!name) | |
| 1850 | + goto out; | |
| 1851 | + | |
| 1852 | + ft->name = name; | |
| 1853 | + | |
| 1854 | + /* path component string */ | |
| 1855 | + rc = next_entry(name, fp, len); | |
| 1856 | + if (rc) | |
| 1857 | + goto out; | |
| 1858 | + name[len] = 0; | |
| 1859 | + | |
| 1860 | + printk(KERN_ERR "%s: ft=%p ft->name=%p ft->name=%s\n", __func__, ft, ft->name, ft->name); | |
| 1861 | + | |
| 1862 | + rc = next_entry(buf, fp, sizeof(u32) * 4); | |
| 1863 | + if (rc) | |
| 1864 | + goto out; | |
| 1865 | + | |
| 1866 | + ft->stype = le32_to_cpu(buf[0]); | |
| 1867 | + ft->ttype = le32_to_cpu(buf[1]); | |
| 1868 | + ft->tclass = le32_to_cpu(buf[2]); | |
| 1869 | + ft->otype = le32_to_cpu(buf[3]); | |
| 1870 | + } | |
| 1871 | + rc = 0; | |
| 1872 | +out: | |
| 1873 | + return rc; | |
| 1874 | +} | |
| 1875 | + | |
| 1791 | 1876 | static int genfs_read(struct policydb *p, void *fp) |
| 1792 | 1877 | { |
| 1793 | 1878 | int i, j, rc; |
| @@ -2251,6 +2336,10 @@ int policydb_read(struct policydb *p, void *fp) · 457 unmodified lines | ||
| 2251 | 2336 | lra = ra; |
| 2252 | 2337 | } |
| 2253 | 2338 | |
| 2339 | + rc = filename_trans_read(p, fp); | |
| 2340 | + if (rc) | |
| 2341 | + goto bad; | |
| 2342 | + | |
| 2254 | 2343 | rc = policydb_index(p); |
| 2255 | 2344 | if (rc) |
| 2256 | 2345 | goto bad; |
| @@ -3025,6 +3114,43 @@ static int range_write(struct policydb *p, void *fp) · 768 unmodified lines | ||
| 3025 | 3114 | return 0; |
| 3026 | 3115 | } |
| 3027 | 3116 | |
| 3117 | +static int filename_trans_write(struct policydb *p, void *fp) | |
| 3118 | +{ | |
| 3119 | + struct filename_trans *ft; | |
| 3120 | + u32 len, nel = 0; | |
| 3121 | + __le32 buf[4]; | |
| 3122 | + int rc; | |
| 3123 | + | |
| 3124 | + for (ft = p->filename_trans; ft; ft = ft->next) | |
| 3125 | + nel++; | |
| 3126 | + | |
| 3127 | + buf[0] = cpu_to_le32(nel); | |
| 3128 | + rc = put_entry(buf, sizeof(u32), 1, fp); | |
| 3129 | + if (rc) | |
| 3130 | + return rc; | |
| 3131 | + | |
| 3132 | + for (ft = p->filename_trans; ft; ft = ft->next) { | |
| 3133 | + len = strlen(ft->name); | |
| 3134 | + buf[0] = cpu_to_le32(len); | |
| 3135 | + rc = put_entry(buf, sizeof(u32), 1, fp); | |
| 3136 | + if (rc) | |
| 3137 | + return rc; | |
| 3138 | + | |
| 3139 | + rc = put_entry(ft->name, sizeof(char), len, fp); | |
| 3140 | + if (rc) | |
| 3141 | + return rc; | |
| 3142 | + | |
| 3143 | + buf[0] = ft->stype; | |
| 3144 | + buf[1] = ft->ttype; | |
| 3145 | + buf[2] = ft->tclass; | |
| 3146 | + buf[3] = ft->otype; | |
| 3147 | + | |
| 3148 | + rc = put_entry(buf, sizeof(u32), 4, fp); | |
| 3149 | + if (rc) | |
| 3150 | + return rc; | |
| 3151 | + } | |
| 3152 | + return 0; | |
| 3153 | +} | |
| 3028 | 3154 | /* |
| 3029 | 3155 | * Write the configuration data in a policy database |
| 3030 | 3156 | * structure to a policy database binary representation |
| @@ -3135,6 +3261,10 @@ int policydb_write(struct policydb *p, void *fp) · 104 unmodified lines | ||
| 3135 | 3261 | if (rc) |
| 3136 | 3262 | return rc; |
| 3137 | 3263 | |
| 3264 | + rc = filename_trans_write(p, fp); | |
| 3265 | + if (rc) | |
| 3266 | + return rc; | |
| 3267 | + | |
| 3138 | 3268 | rc = ocontext_write(p, info, fp); |
| 3139 | 3269 | if (rc) |
| 3140 | 3270 | return rc; |
| @@ -77,6 +77,15 @@ struct role_trans { · 76 unmodified lines | ||
| 77 | 77 | struct role_trans *next; |
| 78 | 78 | }; |
| 79 | 79 | |
| 80 | +struct filename_trans { | |
| 81 | + struct filename_trans *next; | |
| 82 | + u32 stype; /* current process */ | |
| 83 | + u32 ttype; /* parent dir context */ | |
| 84 | + u16 tclass; /* class of new object */ | |
| 85 | + const char *name; /* last path component */ | |
| 86 | + u32 otype; /* expected of new object */ | |
| 87 | +}; | |
| 88 | + | |
| 80 | 89 | struct role_allow { |
| 81 | 90 | u32 role; /* current role */ |
| 82 | 91 | u32 new_role; /* new role */ |
| @@ -217,6 +226,9 @@ struct policydb { · 134 unmodified lines | ||
| 217 | 226 | /* role transitions */ |
| 218 | 227 | struct role_trans *role_tr; |
| 219 | 228 | |
| 229 | + /* file transitions with the last path component */ | |
| 230 | + struct filename_trans *filename_trans; | |
| 231 | + | |
| 220 | 232 | /* bools indexed by (value - 1) */ |
| 221 | 233 | struct cond_bool_datum **bool_val_to_struct; |
| 222 | 234 | /* type enforcement conditional access vectors and transitions */ |
| @@ -302,7 +314,7 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes) · 79 unmodified lines | ||
| 302 | 314 | return 0; |
| 303 | 315 | } |
| 304 | 316 | |
| 305 | −static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file *fp) | |
| 317 | +static inline int put_entry(const void *buf, size_t bytes, int num, struct policy_file *fp) | |
| 306 | 318 | { |
| 307 | 319 | size_t len = bytes * num; |
| 308 | 320 | |
| @@ -201,6 +201,21 @@ static u16 unmap_class(u16 tclass) · 200 unmodified lines | ||
| 201 | 201 | return tclass; |
| 202 | 202 | } |
| 203 | 203 | |
| 204 | +/* | |
| 205 | + * Get kernel value for class from its policy value | |
| 206 | + */ | |
| 207 | +static u16 map_class(u16 pol_value) | |
| 208 | +{ | |
| 209 | + u16 i; | |
| 210 | + | |
| 211 | + for (i = 1; i < current_mapping_size; i++) { | |
| 212 | + if (current_mapping[i].value == pol_value) | |
| 213 | + return i; | |
| 214 | + } | |
| 215 | + | |
| 216 | + return pol_value; | |
| 217 | +} | |
| 218 | + | |
| 204 | 219 | static void map_decision(u16 tclass, struct av_decision *avd, |
| 205 | 220 | int allow_unknown) |
| 206 | 221 | { |
| @@ -1343,10 +1358,27 @@ out: · 1136 unmodified lines | ||
| 1343 | 1358 | return -EACCES; |
| 1344 | 1359 | } |
| 1345 | 1360 | |
| 1361 | +static void filename_compute_type(struct policydb *p, struct context *newcontext, | |
| 1362 | + u32 scon, u32 tcon, u16 tclass, | |
| 1363 | + const struct qstr *qstr) | |
| 1364 | +{ | |
| 1365 | + struct filename_trans *ft; | |
| 1366 | + for (ft = p->filename_trans; ft; ft = ft->next) { | |
| 1367 | + if (ft->stype == scon && | |
| 1368 | + ft->ttype == tcon && | |
| 1369 | + ft->tclass == tclass && | |
| 1370 | + !strcmp(ft->name, qstr->name)) { | |
| 1371 | + newcontext->type = ft->otype; | |
| 1372 | + return; | |
| 1373 | + } | |
| 1374 | + } | |
| 1375 | +} | |
| 1376 | + | |
| 1346 | 1377 | static int security_compute_sid(u32 ssid, |
| 1347 | 1378 | u32 tsid, |
| 1348 | 1379 | u16 orig_tclass, |
| 1349 | 1380 | u32 specified, |
| 1381 | + const struct qstr *qstr, | |
| 1350 | 1382 | u32 *out_sid, |
| 1351 | 1383 | bool kern) |
| 1352 | 1384 | { |
| @@ -1357,6 +1389,7 @@ static int security_compute_sid(u32 ssid, · 4 unmodified lines | ||
| 1357 | 1389 | struct avtab_node *node; |
| 1358 | 1390 | u16 tclass; |
| 1359 | 1391 | int rc = 0; |
| 1392 | + bool sock; | |
| 1360 | 1393 | |
| 1361 | 1394 | if (!ss_initialized) { |
| 1362 | 1395 | switch (orig_tclass) { |
| @@ -1374,10 +1407,13 @@ static int security_compute_sid(u32 ssid, · 11 unmodified lines | ||
| 1374 | 1407 | |
| 1375 | 1408 | read_lock(&policy_rwlock); |
| 1376 | 1409 | |
| 1377 | − if (kern) | |
| 1410 | + if (kern) { | |
| 1378 | 1411 | tclass = unmap_class(orig_tclass); |
| 1379 | − else | |
| 1412 | + sock = security_is_socket_class(orig_tclass); | |
| 1413 | + } else { | |
| 1380 | 1414 | tclass = orig_tclass; |
| 1415 | + sock = security_is_socket_class(map_class(tclass)); | |
| 1416 | + } | |
| 1381 | 1417 | |
| 1382 | 1418 | scontext = sidtab_search(&sidtab, ssid); |
| 1383 | 1419 | if (!scontext) { |
| @@ -1408,7 +1444,7 @@ static int security_compute_sid(u32 ssid, · 24 unmodified lines | ||
| 1408 | 1444 | } |
| 1409 | 1445 | |
| 1410 | 1446 | /* Set the role and type to default values. */ |
| 1411 | − if (tclass == policydb.process_class) { | |
| 1447 | + if ((tclass == policydb.process_class) || (sock == true)) { | |
| 1412 | 1448 | /* Use the current role and type of process. */ |
| 1413 | 1449 | newcontext.role = scontext->role; |
| 1414 | 1450 | newcontext.type = scontext->type; |
| @@ -1442,6 +1478,11 @@ static int security_compute_sid(u32 ssid, · 27 unmodified lines | ||
| 1442 | 1478 | newcontext.type = avdatum->data; |
| 1443 | 1479 | } |
| 1444 | 1480 | |
| 1481 | + /* if we have a qstr this is a file trans check so check those rules */ | |
| 1482 | + if (qstr) | |
| 1483 | + filename_compute_type(&policydb, &newcontext, scontext->type, | |
| 1484 | + tcontext->type, tclass, qstr); | |
| 1485 | + | |
| 1445 | 1486 | /* Check for class-specific changes. */ |
| 1446 | 1487 | if (tclass == policydb.process_class) { |
| 1447 | 1488 | if (specified & AVTAB_TRANSITION) { |
| @@ -1460,7 +1501,8 @@ static int security_compute_sid(u32 ssid, · 12 unmodified lines | ||
| 1460 | 1501 | |
| 1461 | 1502 | /* Set the MLS attributes. |
| 1462 | 1503 | This is done last because it may allocate memory. */ |
| 1463 | − rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext); | |
| 1504 | + rc = mls_compute_sid(scontext, tcontext, tclass, specified, | |
| 1505 | + &newcontext, sock); | |
| 1464 | 1506 | if (rc) |
| 1465 | 1507 | goto out_unlock; |
| 1466 | 1508 | |
| @@ -1495,22 +1537,17 @@ out: · 28 unmodified lines | ||
| 1495 | 1537 | * if insufficient memory is available, or %0 if the new SID was |
| 1496 | 1538 | * computed successfully. |
| 1497 | 1539 | */ |
| 1498 | −int security_transition_sid(u32 ssid, | |
| 1499 | − u32 tsid, | |
| 1500 | − u16 tclass, | |
| 1501 | − u32 *out_sid) | |
| 1540 | +int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, | |
| 1541 | + const struct qstr *qstr, u32 *out_sid) | |
| 1502 | 1542 | { |
| 1503 | 1543 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, |
| 1504 | − out_sid, true); | |
| 1544 | + qstr, out_sid, true); | |
| 1505 | 1545 | } |
| 1506 | 1546 | |
| 1507 | −int security_transition_sid_user(u32 ssid, | |
| 1508 | − u32 tsid, | |
| 1509 | − u16 tclass, | |
| 1510 | − u32 *out_sid) | |
| 1547 | +int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid) | |
| 1511 | 1548 | { |
| 1512 | 1549 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, |
| 1513 | − out_sid, false); | |
| 1550 | + NULL, out_sid, false); | |
| 1514 | 1551 | } |
| 1515 | 1552 | |
| 1516 | 1553 | /** |
| @@ -1531,8 +1568,8 @@ int security_member_sid(u32 ssid, · 14 unmodified lines | ||
| 1531 | 1568 | u16 tclass, |
| 1532 | 1569 | u32 *out_sid) |
| 1533 | 1570 | { |
| 1534 | − return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid, | |
| 1535 | − false); | |
| 1571 | + return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, NULL, | |
| 1572 | + out_sid, false); | |
| 1536 | 1573 | } |
| 1537 | 1574 | |
| 1538 | 1575 | /** |
| @@ -1553,8 +1590,8 @@ int security_change_sid(u32 ssid, · 14 unmodified lines | ||
| 1553 | 1590 | u16 tclass, |
| 1554 | 1591 | u32 *out_sid) |
| 1555 | 1592 | { |
| 1556 | − return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid, | |
| 1557 | − false); | |
| 1593 | + return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL, | |
| 1594 | + out_sid, false); | |
| 1558 | 1595 | } |
| 1559 | 1596 | |
| 1560 | 1597 | /* Clone the SID into the new SID table. */ |
| @@ -208,7 +208,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, · 207 unmodified lines | ||
| 208 | 208 | if (!uctx) |
| 209 | 209 | goto not_from_user; |
| 210 | 210 | |
| 211 | − if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX) | |
| 211 | + if (uctx->ctx_alg != XFRM_SC_ALG_SELINUX) | |
| 212 | 212 | return -EINVAL; |
| 213 | 213 | |
| 214 | 214 | str_len = uctx->ctx_len; |
| @@ -52,13 +52,16 @@ struct socket_smack { · 51 unmodified lines | ||
| 52 | 52 | struct inode_smack { |
| 53 | 53 | char *smk_inode; /* label of the fso */ |
| 54 | 54 | char *smk_task; /* label of the task */ |
| 55 | + char *smk_mmap; /* label of the mmap domain */ | |
| 55 | 56 | struct mutex smk_lock; /* initialization lock */ |
| 56 | 57 | int smk_flags; /* smack inode flags */ |
| 57 | 58 | }; |
| 58 | 59 | |
| 59 | 60 | struct task_smack { |
| 60 | − char *smk_task; /* label used for access control */ | |
| 61 | − char *smk_forked; /* label when forked */ | |
| 61 | + char *smk_task; /* label for access control */ | |
| 62 | + char *smk_forked; /* label when forked */ | |
| 63 | + struct list_head smk_rules; /* per task access rules */ | |
| 64 | + struct mutex smk_rules_lock; /* lock for the rules */ | |
| 62 | 65 | }; |
| 63 | 66 | |
| 64 | 67 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ |
| @@ -151,12 +154,6 @@ struct smack_known { · 86 unmodified lines | ||
| 151 | 154 | */ |
| 152 | 155 | #define SMACK_MAGIC 0x43415d53 /* "SMAC" */ |
| 153 | 156 | |
| 154 | −/* | |
| 155 | − * A limit on the number of entries in the lists | |
| 156 | − * makes some of the list administration easier. | |
| 157 | − */ | |
| 158 | −#define SMACK_LIST_MAX 10000 | |
| 159 | − | |
| 160 | 157 | /* |
| 161 | 158 | * CIPSO defaults. |
| 162 | 159 | */ |
| @@ -174,9 +171,7 @@ struct smack_known { · 11 unmodified lines | ||
| 174 | 171 | /* |
| 175 | 172 | * Just to make the common cases easier to deal with |
| 176 | 173 | */ |
| 177 | −#define MAY_ANY (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) | |
| 178 | 174 | #define MAY_ANYREAD (MAY_READ | MAY_EXEC) |
| 179 | −#define MAY_ANYWRITE (MAY_WRITE | MAY_APPEND) | |
| 180 | 175 | #define MAY_READWRITE (MAY_READ | MAY_WRITE) |
| 181 | 176 | #define MAY_NOT 0 |
| 182 | 177 | |
| @@ -202,7 +197,7 @@ struct inode_smack *new_inode_smack(char *); · 19 unmodified lines | ||
| 202 | 197 | /* |
| 203 | 198 | * These functions are in smack_access.c |
| 204 | 199 | */ |
| 205 | −int smk_access_entry(char *, char *); | |
| 200 | +int smk_access_entry(char *, char *, struct list_head *); | |
| 206 | 201 | int smk_access(char *, char *, int, struct smk_audit_info *); |
| 207 | 202 | int smk_curacc(char *, u32, struct smk_audit_info *); |
| 208 | 203 | int smack_to_cipso(const char *, struct smack_cipso *); |
| @@ -70,10 +70,11 @@ int log_policy = SMACK_AUDIT_DENIED; · 69 unmodified lines | ||
| 70 | 70 | * smk_access_entry - look up matching access rule |
| 71 | 71 | * @subject_label: a pointer to the subject's Smack label |
| 72 | 72 | * @object_label: a pointer to the object's Smack label |
| 73 | + * @rule_list: the list of rules to search | |
| 73 | 74 | * |
| 74 | 75 | * This function looks up the subject/object pair in the |
| 75 | − * access rule list and returns pointer to the matching rule if found, | |
| 76 | − * NULL otherwise. | |
| 76 | + * access rule list and returns the access mode. If no | |
| 77 | + * entry is found returns -ENOENT. | |
| 77 | 78 | * |
| 78 | 79 | * NOTE: |
| 79 | 80 | * Even though Smack labels are usually shared on smack_list |
| @@ -85,13 +86,13 @@ int log_policy = SMACK_AUDIT_DENIED; · 5 unmodified lines | ||
| 85 | 86 | * will be on the list, so checking the pointers may be a worthwhile |
| 86 | 87 | * optimization. |
| 87 | 88 | */ |
| 88 | −int smk_access_entry(char *subject_label, char *object_label) | |
| 89 | +int smk_access_entry(char *subject_label, char *object_label, | |
| 90 | + struct list_head *rule_list) | |
| 89 | 91 | { |
| 90 | − u32 may = MAY_NOT; | |
| 92 | + int may = -ENOENT; | |
| 91 | 93 | struct smack_rule *srp; |
| 92 | 94 | |
| 93 | − rcu_read_lock(); | |
| 94 | − list_for_each_entry_rcu(srp, &smack_rule_list, list) { | |
| 95 | + list_for_each_entry_rcu(srp, rule_list, list) { | |
| 95 | 96 | if (srp->smk_subject == subject_label || |
| 96 | 97 | strcmp(srp->smk_subject, subject_label) == 0) { |
| 97 | 98 | if (srp->smk_object == object_label || |
| @@ -101,7 +102,6 @@ int smk_access_entry(char *subject_label, char *object_label) · 3 unmodified lines | ||
| 101 | 102 | } |
| 102 | 103 | } |
| 103 | 104 | } |
| 104 | − rcu_read_unlock(); | |
| 105 | 105 | |
| 106 | 106 | return may; |
| 107 | 107 | } |
| @@ -129,7 +129,7 @@ int smk_access_entry(char *subject_label, char *object_label) · 21 unmodified lines | ||
| 129 | 129 | int smk_access(char *subject_label, char *object_label, int request, |
| 130 | 130 | struct smk_audit_info *a) |
| 131 | 131 | { |
| 132 | − u32 may = MAY_NOT; | |
| 132 | + int may = MAY_NOT; | |
| 133 | 133 | int rc = 0; |
| 134 | 134 | |
| 135 | 135 | /* |
| @@ -181,13 +181,14 @@ int smk_access(char *subject_label, char *object_label, int request, · 45 unmodified lines | ||
| 181 | 181 | * Beyond here an explicit relationship is required. |
| 182 | 182 | * If the requested access is contained in the available |
| 183 | 183 | * access (e.g. read is included in readwrite) it's |
| 184 | − * good. | |
| 185 | − */ | |
| 186 | − may = smk_access_entry(subject_label, object_label); | |
| 187 | − /* | |
| 188 | − * This is a bit map operation. | |
| 184 | + * good. A negative response from smk_access_entry() | |
| 185 | + * indicates there is no entry for this pair. | |
| 189 | 186 | */ |
| 190 | − if ((request & may) == request) | |
| 187 | + rcu_read_lock(); | |
| 188 | + may = smk_access_entry(subject_label, object_label, &smack_rule_list); | |
| 189 | + rcu_read_unlock(); | |
| 190 | + | |
| 191 | + if (may > 0 && (request & may) == request) | |
| 191 | 192 | goto out_audit; |
| 192 | 193 | |
| 193 | 194 | rc = -EACCES; |
| @@ -212,12 +213,27 @@ out_audit: · 18 unmodified lines | ||
| 212 | 213 | */ |
| 213 | 214 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) |
| 214 | 215 | { |
| 216 | + struct task_smack *tsp = current_security(); | |
| 217 | + char *sp = smk_of_task(tsp); | |
| 218 | + int may; | |
| 215 | 219 | int rc; |
| 216 | − char *sp = smk_of_current(); | |
| 217 | 220 | |
| 221 | + /* | |
| 222 | + * Check the global rule list | |
| 223 | + */ | |
| 218 | 224 | rc = smk_access(sp, obj_label, mode, NULL); |
| 219 | − if (rc == 0) | |
| 220 | − goto out_audit; | |
| 225 | + if (rc == 0) { | |
| 226 | + /* | |
| 227 | + * If there is an entry in the task's rule list | |
| 228 | + * it can further restrict access. | |
| 229 | + */ | |
| 230 | + may = smk_access_entry(sp, obj_label, &tsp->smk_rules); | |
| 231 | + if (may < 0) | |
| 232 | + goto out_audit; | |
| 233 | + if ((mode & may) == mode) | |
| 234 | + goto out_audit; | |
| 235 | + rc = -EACCES; | |
| 236 | + } | |
| 221 | 237 | |
| 222 | 238 | /* |
| 223 | 239 | * Return if a specific label has been designated as the |
| @@ -228,7 +244,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) · 4 unmodified lines | ||
| 228 | 244 | goto out_audit; |
| 229 | 245 | |
| 230 | 246 | if (capable(CAP_MAC_OVERRIDE)) |
| 231 | − return 0; | |
| 247 | + rc = 0; | |
| 232 | 248 | |
| 233 | 249 | out_audit: |
| 234 | 250 | #ifdef CONFIG_AUDIT |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <net/cipso_ipv4.h> |
| 34 | 34 | #include <linux/audit.h> |
| 35 | 35 | #include <linux/magic.h> |
| 36 | +#include <linux/dcache.h> | |
| 36 | 37 | #include "smack.h" |
| 37 | 38 | |
| 38 | 39 | #define task_security(task) (task_cred_xxx((task), security)) |
| @@ -84,6 +85,56 @@ struct inode_smack *new_inode_smack(char *smack) · 45 unmodified lines | ||
| 84 | 85 | return isp; |
| 85 | 86 | } |
| 86 | 87 | |
| 88 | +/** | |
| 89 | + * new_task_smack - allocate a task security blob | |
| 90 | + * @smack: a pointer to the Smack label to use in the blob | |
| 91 | + * | |
| 92 | + * Returns the new blob or NULL if there's no memory available | |
| 93 | + */ | |
| 94 | +static struct task_smack *new_task_smack(char *task, char *forked, gfp_t gfp) | |
| 95 | +{ | |
| 96 | + struct task_smack *tsp; | |
| 97 | + | |
| 98 | + tsp = kzalloc(sizeof(struct task_smack), gfp); | |
| 99 | + if (tsp == NULL) | |
| 100 | + return NULL; | |
| 101 | + | |
| 102 | + tsp->smk_task = task; | |
| 103 | + tsp->smk_forked = forked; | |
| 104 | + INIT_LIST_HEAD(&tsp->smk_rules); | |
| 105 | + mutex_init(&tsp->smk_rules_lock); | |
| 106 | + | |
| 107 | + return tsp; | |
| 108 | +} | |
| 109 | + | |
| 110 | +/** | |
| 111 | + * smk_copy_rules - copy a rule set | |
| 112 | + * @nhead - new rules header pointer | |
| 113 | + * @ohead - old rules header pointer | |
| 114 | + * | |
| 115 | + * Returns 0 on success, -ENOMEM on error | |
| 116 | + */ | |
| 117 | +static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, | |
| 118 | + gfp_t gfp) | |
| 119 | +{ | |
| 120 | + struct smack_rule *nrp; | |
| 121 | + struct smack_rule *orp; | |
| 122 | + int rc = 0; | |
| 123 | + | |
| 124 | + INIT_LIST_HEAD(nhead); | |
| 125 | + | |
| 126 | + list_for_each_entry_rcu(orp, ohead, list) { | |
| 127 | + nrp = kzalloc(sizeof(struct smack_rule), gfp); | |
| 128 | + if (nrp == NULL) { | |
| 129 | + rc = -ENOMEM; | |
| 130 | + break; | |
| 131 | + } | |
| 132 | + *nrp = *orp; | |
| 133 | + list_add_rcu(&nrp->list, nhead); | |
| 134 | + } | |
| 135 | + return rc; | |
| 136 | +} | |
| 137 | + | |
| 87 | 138 | /* |
| 88 | 139 | * LSM hooks. |
| 89 | 140 | * We he, that is fun! |
| @@ -102,23 +153,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) · 12 unmodified lines | ||
| 102 | 153 | { |
| 103 | 154 | int rc; |
| 104 | 155 | struct smk_audit_info ad; |
| 105 | − char *sp, *tsp; | |
| 156 | + char *tsp; | |
| 106 | 157 | |
| 107 | 158 | rc = cap_ptrace_access_check(ctp, mode); |
| 108 | 159 | if (rc != 0) |
| 109 | 160 | return rc; |
| 110 | 161 | |
| 111 | − sp = smk_of_current(); | |
| 112 | 162 | tsp = smk_of_task(task_security(ctp)); |
| 113 | 163 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
| 114 | 164 | smk_ad_setfield_u_tsk(&ad, ctp); |
| 115 | 165 | |
| 116 | − /* we won't log here, because rc can be overriden */ | |
| 117 | − rc = smk_access(sp, tsp, MAY_READWRITE, NULL); | |
| 118 | − if (rc != 0 && capable(CAP_MAC_OVERRIDE)) | |
| 119 | − rc = 0; | |
| 120 | − | |
| 121 | − smack_log(sp, tsp, MAY_READWRITE, rc, &ad); | |
| 166 | + rc = smk_curacc(tsp, MAY_READWRITE, &ad); | |
| 122 | 167 | return rc; |
| 123 | 168 | } |
| 124 | 169 | |
| @@ -134,23 +179,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp) · 9 unmodified lines | ||
| 134 | 179 | { |
| 135 | 180 | int rc; |
| 136 | 181 | struct smk_audit_info ad; |
| 137 | − char *sp, *tsp; | |
| 182 | + char *tsp; | |
| 138 | 183 | |
| 139 | 184 | rc = cap_ptrace_traceme(ptp); |
| 140 | 185 | if (rc != 0) |
| 141 | 186 | return rc; |
| 142 | 187 | |
| 188 | + tsp = smk_of_task(task_security(ptp)); | |
| 143 | 189 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
| 144 | 190 | smk_ad_setfield_u_tsk(&ad, ptp); |
| 145 | 191 | |
| 146 | − sp = smk_of_current(); | |
| 147 | − tsp = smk_of_task(task_security(ptp)); | |
| 148 | − /* we won't log here, because rc can be overriden */ | |
| 149 | − rc = smk_access(tsp, sp, MAY_READWRITE, NULL); | |
| 150 | − if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE)) | |
| 151 | − rc = 0; | |
| 152 | − | |
| 153 | − smack_log(tsp, sp, MAY_READWRITE, rc, &ad); | |
| 192 | + rc = smk_curacc(tsp, MAY_READWRITE, &ad); | |
| 154 | 193 | return rc; |
| 155 | 194 | } |
| 156 | 195 | |
| @@ -463,6 +502,7 @@ static void smack_inode_free_security(struct inode *inode) · 306 unmodified lines | ||
| 463 | 502 | * smack_inode_init_security - copy out the smack from an inode |
| 464 | 503 | * @inode: the inode |
| 465 | 504 | * @dir: unused |
| 505 | + * @qstr: unused | |
| 466 | 506 | * @name: where to put the attribute name |
| 467 | 507 | * @value: where to put the attribute value |
| 468 | 508 | * @len: where to put the length of the attribute |
| @@ -470,11 +510,12 @@ static void smack_inode_free_security(struct inode *inode) · 1 unmodified line | ||
| 470 | 510 | * Returns 0 if it all works out, -ENOMEM if there's no memory |
| 471 | 511 | */ |
| 472 | 512 | static int smack_inode_init_security(struct inode *inode, struct inode *dir, |
| 473 | − char **name, void **value, size_t *len) | |
| 513 | + const struct qstr *qstr, char **name, | |
| 514 | + void **value, size_t *len) | |
| 474 | 515 | { |
| 475 | 516 | char *isp = smk_of_inode(inode); |
| 476 | 517 | char *dsp = smk_of_inode(dir); |
| 477 | − u32 may; | |
| 518 | + int may; | |
| 478 | 519 | |
| 479 | 520 | if (name) { |
| 480 | 521 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); |
| @@ -483,14 +524,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, · 2 unmodified lines | ||
| 483 | 524 | } |
| 484 | 525 | |
| 485 | 526 | if (value) { |
| 486 | − may = smk_access_entry(smk_of_current(), dsp); | |
| 527 | + rcu_read_lock(); | |
| 528 | + may = smk_access_entry(smk_of_current(), dsp, &smack_rule_list); | |
| 529 | + rcu_read_unlock(); | |
| 487 | 530 | |
| 488 | 531 | /* |
| 489 | 532 | * If the access rule allows transmutation and |
| 490 | 533 | * the directory requests transmutation then |
| 491 | 534 | * by all means transmute. |
| 492 | 535 | */ |
| 493 | − if (((may & MAY_TRANSMUTE) != 0) && smk_inode_transmutable(dir)) | |
| 536 | + if (may > 0 && ((may & MAY_TRANSMUTE) != 0) && | |
| 537 | + smk_inode_transmutable(dir)) | |
| 494 | 538 | isp = dsp; |
| 495 | 539 | |
| 496 | 540 | *value = kstrdup(isp, GFP_KERNEL); |
| @@ -716,7 +760,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, · 219 unmodified lines | ||
| 716 | 760 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
| 717 | 761 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
| 718 | 762 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
| 719 | − strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { | |
| 763 | + strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | |
| 764 | + strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { | |
| 720 | 765 | if (!capable(CAP_MAC_ADMIN)) |
| 721 | 766 | rc = -EPERM; |
| 722 | 767 | /* |
| @@ -773,6 +818,12 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, · 50 unmodified lines | ||
| 773 | 818 | isp->smk_task = nsp; |
| 774 | 819 | else |
| 775 | 820 | isp->smk_task = smack_known_invalid.smk_known; |
| 821 | + } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { | |
| 822 | + nsp = smk_import(value, size); | |
| 823 | + if (nsp != NULL) | |
| 824 | + isp->smk_mmap = nsp; | |
| 825 | + else | |
| 826 | + isp->smk_mmap = smack_known_invalid.smk_known; | |
| 776 | 827 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) |
| 777 | 828 | isp->smk_flags |= SMK_INODE_TRANSMUTE; |
| 778 | 829 | |
| @@ -815,7 +866,8 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) · 36 unmodified lines | ||
| 815 | 866 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
| 816 | 867 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
| 817 | 868 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || |
| 818 | − strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | |
| 869 | + strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 || | |
| 870 | + strcmp(name, XATTR_NAME_SMACKMMAP)) { | |
| 819 | 871 | if (!capable(CAP_MAC_ADMIN)) |
| 820 | 872 | rc = -EPERM; |
| 821 | 873 | } else |
| @@ -829,6 +881,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) · 7 unmodified lines | ||
| 829 | 881 | if (rc == 0) { |
| 830 | 882 | isp = dentry->d_inode->i_security; |
| 831 | 883 | isp->smk_task = NULL; |
| 884 | + isp->smk_mmap = NULL; | |
| 832 | 885 | } |
| 833 | 886 | |
| 834 | 887 | return rc; |
| @@ -1059,6 +1112,126 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, · 224 unmodified lines | ||
| 1059 | 1112 | return rc; |
| 1060 | 1113 | } |
| 1061 | 1114 | |
| 1115 | +/** | |
| 1116 | + * smack_file_mmap : | |
| 1117 | + * Check permissions for a mmap operation. The @file may be NULL, e.g. | |
| 1118 | + * if mapping anonymous memory. | |
| 1119 | + * @file contains the file structure for file to map (may be NULL). | |
| 1120 | + * @reqprot contains the protection requested by the application. | |
| 1121 | + * @prot contains the protection that will be applied by the kernel. | |
| 1122 | + * @flags contains the operational flags. | |
| 1123 | + * Return 0 if permission is granted. | |
| 1124 | + */ | |
| 1125 | +static int smack_file_mmap(struct file *file, | |
| 1126 | + unsigned long reqprot, unsigned long prot, | |
| 1127 | + unsigned long flags, unsigned long addr, | |
| 1128 | + unsigned long addr_only) | |
| 1129 | +{ | |
| 1130 | + struct smack_rule *srp; | |
| 1131 | + struct task_smack *tsp; | |
| 1132 | + char *sp; | |
| 1133 | + char *msmack; | |
| 1134 | + char *osmack; | |
| 1135 | + struct inode_smack *isp; | |
| 1136 | + struct dentry *dp; | |
| 1137 | + int may; | |
| 1138 | + int mmay; | |
| 1139 | + int tmay; | |
| 1140 | + int rc; | |
| 1141 | + | |
| 1142 | + /* do DAC check on address space usage */ | |
| 1143 | + rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | |
| 1144 | + if (rc || addr_only) | |
| 1145 | + return rc; | |
| 1146 | + | |
| 1147 | + if (file == NULL || file->f_dentry == NULL) | |
| 1148 | + return 0; | |
| 1149 | + | |
| 1150 | + dp = file->f_dentry; | |
| 1151 | + | |
| 1152 | + if (dp->d_inode == NULL) | |
| 1153 | + return 0; | |
| 1154 | + | |
| 1155 | + isp = dp->d_inode->i_security; | |
| 1156 | + if (isp->smk_mmap == NULL) | |
| 1157 | + return 0; | |
| 1158 | + msmack = isp->smk_mmap; | |
| 1159 | + | |
| 1160 | + tsp = current_security(); | |
| 1161 | + sp = smk_of_current(); | |
| 1162 | + rc = 0; | |
| 1163 | + | |
| 1164 | + rcu_read_lock(); | |
| 1165 | + /* | |
| 1166 | + * For each Smack rule associated with the subject | |
| 1167 | + * label verify that the SMACK64MMAP also has access | |
| 1168 | + * to that rule's object label. | |
| 1169 | + * | |
| 1170 | + * Because neither of the labels comes | |
| 1171 | + * from the networking code it is sufficient | |
| 1172 | + * to compare pointers. | |
| 1173 | + */ | |
| 1174 | + list_for_each_entry_rcu(srp, &smack_rule_list, list) { | |
| 1175 | + if (srp->smk_subject != sp) | |
| 1176 | + continue; | |
| 1177 | + | |
| 1178 | + osmack = srp->smk_object; | |
| 1179 | + /* | |
| 1180 | + * Matching labels always allows access. | |
| 1181 | + */ | |
| 1182 | + if (msmack == osmack) | |
| 1183 | + continue; | |
| 1184 | + /* | |
| 1185 | + * If there is a matching local rule take | |
| 1186 | + * that into account as well. | |
| 1187 | + */ | |
| 1188 | + may = smk_access_entry(srp->smk_subject, osmack, | |
| 1189 | + &tsp->smk_rules); | |
| 1190 | + if (may == -ENOENT) | |
| 1191 | + may = srp->smk_access; | |
| 1192 | + else | |
| 1193 | + may &= srp->smk_access; | |
| 1194 | + /* | |
| 1195 | + * If may is zero the SMACK64MMAP subject can't | |
| 1196 | + * possibly have less access. | |
| 1197 | + */ | |
| 1198 | + if (may == 0) | |
| 1199 | + continue; | |
| 1200 | + | |
| 1201 | + /* | |
| 1202 | + * Fetch the global list entry. | |
| 1203 | + * If there isn't one a SMACK64MMAP subject | |
| 1204 | + * can't have as much access as current. | |
| 1205 | + */ | |
| 1206 | + mmay = smk_access_entry(msmack, osmack, &smack_rule_list); | |
| 1207 | + if (mmay == -ENOENT) { | |
| 1208 | + rc = -EACCES; | |
| 1209 | + break; | |
| 1210 | + } | |
| 1211 | + /* | |
| 1212 | + * If there is a local entry it modifies the | |
| 1213 | + * potential access, too. | |
| 1214 | + */ | |
| 1215 | + tmay = smk_access_entry(msmack, osmack, &tsp->smk_rules); | |
| 1216 | + if (tmay != -ENOENT) | |
| 1217 | + mmay &= tmay; | |
| 1218 | + | |
| 1219 | + /* | |
| 1220 | + * If there is any access available to current that is | |
| 1221 | + * not available to a SMACK64MMAP subject | |
| 1222 | + * deny access. | |
| 1223 | + */ | |
| 1224 | + if ((may | mmay) != mmay) { | |
| 1225 | + rc = -EACCES; | |
| 1226 | + break; | |
| 1227 | + } | |
| 1228 | + } | |
| 1229 | + | |
| 1230 | + rcu_read_unlock(); | |
| 1231 | + | |
| 1232 | + return rc; | |
| 1233 | +} | |
| 1234 | + | |
| 1062 | 1235 | /** |
| 1063 | 1236 | * smack_file_set_fowner - set the file security blob value |
| 1064 | 1237 | * @file: object in question |
| @@ -1095,6 +1268,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, · 30 unmodified lines | ||
| 1095 | 1268 | * struct fown_struct is never outside the context of a struct file |
| 1096 | 1269 | */ |
| 1097 | 1270 | file = container_of(fown, struct file, f_owner); |
| 1271 | + | |
| 1098 | 1272 | /* we don't log here as rc can be overriden */ |
| 1099 | 1273 | rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); |
| 1100 | 1274 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) |
| @@ -1145,9 +1319,14 @@ static int smack_file_receive(struct file *file) · 44 unmodified lines | ||
| 1145 | 1319 | */ |
| 1146 | 1320 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
| 1147 | 1321 | { |
| 1148 | − cred->security = kzalloc(sizeof(struct task_smack), gfp); | |
| 1149 | − if (cred->security == NULL) | |
| 1322 | + struct task_smack *tsp; | |
| 1323 | + | |
| 1324 | + tsp = new_task_smack(NULL, NULL, gfp); | |
| 1325 | + if (tsp == NULL) | |
| 1150 | 1326 | return -ENOMEM; |
| 1327 | + | |
| 1328 | + cred->security = tsp; | |
| 1329 | + | |
| 1151 | 1330 | return 0; |
| 1152 | 1331 | } |
| 1153 | 1332 | |
| @@ -1156,13 +1335,24 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) · 2 unmodified lines | ||
| 1156 | 1335 | * smack_cred_free - "free" task-level security credentials |
| 1157 | 1336 | * @cred: the credentials in question |
| 1158 | 1337 | * |
| 1159 | − * Smack isn't using copies of blobs. Everyone | |
| 1160 | − * points to an immutable list. The blobs never go away. | |
| 1161 | − * There is no leak here. | |
| 1162 | 1338 | */ |
| 1163 | 1339 | static void smack_cred_free(struct cred *cred) |
| 1164 | 1340 | { |
| 1165 | − kfree(cred->security); | |
| 1341 | + struct task_smack *tsp = cred->security; | |
| 1342 | + struct smack_rule *rp; | |
| 1343 | + struct list_head *l; | |
| 1344 | + struct list_head *n; | |
| 1345 | + | |
| 1346 | + if (tsp == NULL) | |
| 1347 | + return; | |
| 1348 | + cred->security = NULL; | |
| 1349 | + | |
| 1350 | + list_for_each_safe(l, n, &tsp->smk_rules) { | |
| 1351 | + rp = list_entry(l, struct smack_rule, list); | |
| 1352 | + list_del(&rp->list); | |
| 1353 | + kfree(rp); | |
| 1354 | + } | |
| 1355 | + kfree(tsp); | |
| 1166 | 1356 | } |
| 1167 | 1357 | |
| 1168 | 1358 | /** |
| @@ -1178,13 +1368,16 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old, · 9 unmodified lines | ||
| 1178 | 1368 | { |
| 1179 | 1369 | struct task_smack *old_tsp = old->security; |
| 1180 | 1370 | struct task_smack *new_tsp; |
| 1371 | + int rc; | |
| 1181 | 1372 | |
| 1182 | − new_tsp = kzalloc(sizeof(struct task_smack), gfp); | |
| 1373 | + new_tsp = new_task_smack(old_tsp->smk_task, old_tsp->smk_task, gfp); | |
| 1183 | 1374 | if (new_tsp == NULL) |
| 1184 | 1375 | return -ENOMEM; |
| 1185 | 1376 | |
| 1186 | − new_tsp->smk_task = old_tsp->smk_task; | |
| 1187 | − new_tsp->smk_forked = old_tsp->smk_task; | |
| 1377 | + rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp); | |
| 1378 | + if (rc != 0) | |
| 1379 | + return rc; | |
| 1380 | + | |
| 1188 | 1381 | new->security = new_tsp; |
| 1189 | 1382 | return 0; |
| 1190 | 1383 | } |
| @@ -1203,6 +1396,11 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) · 12 unmodified lines | ||
| 1203 | 1396 | |
| 1204 | 1397 | new_tsp->smk_task = old_tsp->smk_task; |
| 1205 | 1398 | new_tsp->smk_forked = old_tsp->smk_task; |
| 1399 | + mutex_init(&new_tsp->smk_rules_lock); | |
| 1400 | + INIT_LIST_HEAD(&new_tsp->smk_rules); | |
| 1401 | + | |
| 1402 | + | |
| 1403 | + /* cbs copy rule list */ | |
| 1206 | 1404 | } |
| 1207 | 1405 | |
| 1208 | 1406 | /** |
| @@ -2419,6 +2617,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) · 1210 unmodified lines | ||
| 2419 | 2617 | } |
| 2420 | 2618 | } |
| 2421 | 2619 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); |
| 2620 | + isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); | |
| 2422 | 2621 | |
| 2423 | 2622 | dput(dp); |
| 2424 | 2623 | break; |
| @@ -2478,6 +2677,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) · 53 unmodified lines | ||
| 2478 | 2677 | static int smack_setprocattr(struct task_struct *p, char *name, |
| 2479 | 2678 | void *value, size_t size) |
| 2480 | 2679 | { |
| 2680 | + int rc; | |
| 2481 | 2681 | struct task_smack *tsp; |
| 2482 | 2682 | struct task_smack *oldtsp; |
| 2483 | 2683 | struct cred *new; |
| @@ -2513,13 +2713,16 @@ static int smack_setprocattr(struct task_struct *p, char *name, · 29 unmodified lines | ||
| 2513 | 2713 | new = prepare_creds(); |
| 2514 | 2714 | if (new == NULL) |
| 2515 | 2715 | return -ENOMEM; |
| 2516 | − tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); | |
| 2716 | + | |
| 2717 | + tsp = new_task_smack(newsmack, oldtsp->smk_forked, GFP_KERNEL); | |
| 2517 | 2718 | if (tsp == NULL) { |
| 2518 | 2719 | kfree(new); |
| 2519 | 2720 | return -ENOMEM; |
| 2520 | 2721 | } |
| 2521 | − tsp->smk_task = newsmack; | |
| 2522 | − tsp->smk_forked = oldtsp->smk_forked; | |
| 2722 | + rc = smk_copy_rules(&tsp->smk_rules, &oldtsp->smk_rules, GFP_KERNEL); | |
| 2723 | + if (rc != 0) | |
| 2724 | + return rc; | |
| 2725 | + | |
| 2523 | 2726 | new->security = tsp; |
| 2524 | 2727 | commit_creds(new); |
| 2525 | 2728 | return size; |
| @@ -3221,6 +3424,7 @@ struct security_operations smack_ops = { · 695 unmodified lines | ||
| 3221 | 3424 | .file_ioctl = smack_file_ioctl, |
| 3222 | 3425 | .file_lock = smack_file_lock, |
| 3223 | 3426 | .file_fcntl = smack_file_fcntl, |
| 3427 | + .file_mmap = smack_file_mmap, | |
| 3224 | 3428 | .file_set_fowner = smack_file_set_fowner, |
| 3225 | 3429 | .file_send_sigiotask = smack_file_send_sigiotask, |
| 3226 | 3430 | .file_receive = smack_file_receive, |
| @@ -3334,23 +3538,20 @@ static __init int smack_init(void) · 107 unmodified lines | ||
| 3334 | 3538 | struct cred *cred; |
| 3335 | 3539 | struct task_smack *tsp; |
| 3336 | 3540 | |
| 3337 | − tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); | |
| 3541 | + if (!security_module_enable(&smack_ops)) | |
| 3542 | + return 0; | |
| 3543 | + | |
| 3544 | + tsp = new_task_smack(smack_known_floor.smk_known, | |
| 3545 | + smack_known_floor.smk_known, GFP_KERNEL); | |
| 3338 | 3546 | if (tsp == NULL) |
| 3339 | 3547 | return -ENOMEM; |
| 3340 | 3548 | |
| 3341 | − if (!security_module_enable(&smack_ops)) { | |
| 3342 | − kfree(tsp); | |
| 3343 | − return 0; | |
| 3344 | − } | |
| 3345 | − | |
| 3346 | 3549 | printk(KERN_INFO "Smack: Initializing.\n"); |
| 3347 | 3550 | |
| 3348 | 3551 | /* |
| 3349 | 3552 | * Set the security state for the initial task. |
| 3350 | 3553 | */ |
| 3351 | 3554 | cred = (struct cred *) current->cred; |
| 3352 | − tsp->smk_forked = smack_known_floor.smk_known; | |
| 3353 | − tsp->smk_task = smack_known_floor.smk_known; | |
| 3354 | 3555 | cred->security = tsp; |
| 3355 | 3556 | |
| 3356 | 3557 | /* initialize the smack_know_list */ |
| @@ -43,6 +43,7 @@ enum smk_inos { · 42 unmodified lines | ||
| 43 | 43 | SMK_NETLBLADDR = 8, /* single label hosts */ |
| 44 | 44 | SMK_ONLYCAP = 9, /* the only "capable" label */ |
| 45 | 45 | SMK_LOGGING = 10, /* logging */ |
| 46 | + SMK_LOAD_SELF = 11, /* task specific rules */ | |
| 46 | 47 | }; |
| 47 | 48 | |
| 48 | 49 | /* |
| @@ -135,104 +136,30 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap) · 86 unmodified lines | ||
| 135 | 136 | #define SMK_NETLBLADDRMIN 9 |
| 136 | 137 | #define SMK_NETLBLADDRMAX 42 |
| 137 | 138 | |
| 138 | −/* | |
| 139 | − * Seq_file read operations for /smack/load | |
| 140 | − */ | |
| 141 | − | |
| 142 | −static void *load_seq_start(struct seq_file *s, loff_t *pos) | |
| 143 | −{ | |
| 144 | − if (*pos == SEQ_READ_FINISHED) | |
| 145 | − return NULL; | |
| 146 | − if (list_empty(&smack_rule_list)) | |
| 147 | − return NULL; | |
| 148 | − return smack_rule_list.next; | |
| 149 | −} | |
| 150 | − | |
| 151 | −static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) | |
| 152 | −{ | |
| 153 | − struct list_head *list = v; | |
| 154 | − | |
| 155 | − if (list_is_last(list, &smack_rule_list)) { | |
| 156 | − *pos = SEQ_READ_FINISHED; | |
| 157 | − return NULL; | |
| 158 | − } | |
| 159 | − return list->next; | |
| 160 | −} | |
| 161 | − | |
| 162 | −static int load_seq_show(struct seq_file *s, void *v) | |
| 163 | −{ | |
| 164 | − struct list_head *list = v; | |
| 165 | − struct smack_rule *srp = | |
| 166 | − list_entry(list, struct smack_rule, list); | |
| 167 | − | |
| 168 | − seq_printf(s, "%s %s", (char *)srp->smk_subject, | |
| 169 | − (char *)srp->smk_object); | |
| 170 | − | |
| 171 | − seq_putc(s, ' '); | |
| 172 | − | |
| 173 | − if (srp->smk_access & MAY_READ) | |
| 174 | − seq_putc(s, 'r'); | |
| 175 | − if (srp->smk_access & MAY_WRITE) | |
| 176 | − seq_putc(s, 'w'); | |
| 177 | − if (srp->smk_access & MAY_EXEC) | |
| 178 | − seq_putc(s, 'x'); | |
| 179 | − if (srp->smk_access & MAY_APPEND) | |
| 180 | − seq_putc(s, 'a'); | |
| 181 | − if (srp->smk_access & MAY_TRANSMUTE) | |
| 182 | − seq_putc(s, 't'); | |
| 183 | − if (srp->smk_access == 0) | |
| 184 | − seq_putc(s, '-'); | |
| 185 | − | |
| 186 | − seq_putc(s, '\n'); | |
| 187 | − | |
| 188 | − return 0; | |
| 189 | −} | |
| 190 | − | |
| 191 | −static void load_seq_stop(struct seq_file *s, void *v) | |
| 192 | −{ | |
| 193 | − /* No-op */ | |
| 194 | −} | |
| 195 | − | |
| 196 | −static const struct seq_operations load_seq_ops = { | |
| 197 | − .start = load_seq_start, | |
| 198 | − .next = load_seq_next, | |
| 199 | − .show = load_seq_show, | |
| 200 | − .stop = load_seq_stop, | |
| 201 | −}; | |
| 202 | − | |
| 203 | −/** | |
| 204 | − * smk_open_load - open() for /smack/load | |
| 205 | − * @inode: inode structure representing file | |
| 206 | − * @file: "load" file pointer | |
| 207 | − * | |
| 208 | − * For reading, use load_seq_* seq_file reading operations. | |
| 209 | − */ | |
| 210 | −static int smk_open_load(struct inode *inode, struct file *file) | |
| 211 | −{ | |
| 212 | − return seq_open(file, &load_seq_ops); | |
| 213 | −} | |
| 214 | − | |
| 215 | 139 | /** |
| 216 | 140 | * smk_set_access - add a rule to the rule list |
| 217 | 141 | * @srp: the new rule to add |
| 142 | + * @rule_list: the list of rules | |
| 143 | + * @rule_lock: the rule list lock | |
| 218 | 144 | * |
| 219 | 145 | * Looks through the current subject/object/access list for |
| 220 | 146 | * the subject/object pair and replaces the access that was |
| 221 | 147 | * there. If the pair isn't found add it with the specified |
| 222 | 148 | * access. |
| 223 | 149 | * |
| 150 | + * Returns 1 if a rule was found to exist already, 0 if it is new | |
| 224 | 151 | * Returns 0 if nothing goes wrong or -ENOMEM if it fails |
| 225 | 152 | * during the allocation of the new pair to add. |
| 226 | 153 | */ |
| 227 | −static int smk_set_access(struct smack_rule *srp) | |
| 154 | +static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list, | |
| 155 | + struct mutex *rule_lock) | |
| 228 | 156 | { |
| 229 | 157 | struct smack_rule *sp; |
| 230 | − int ret = 0; | |
| 231 | − int found; | |
| 232 | − mutex_lock(&smack_list_lock); | |
| 158 | + int found = 0; | |
| 233 | 159 | |
| 234 | − found = 0; | |
| 235 | − list_for_each_entry_rcu(sp, &smack_rule_list, list) { | |
| 160 | + mutex_lock(rule_lock); | |
| 161 | + | |
| 162 | + list_for_each_entry_rcu(sp, rule_list, list) { | |
| 236 | 163 | if (sp->smk_subject == srp->smk_subject && |
| 237 | 164 | sp->smk_object == srp->smk_object) { |
| 238 | 165 | found = 1; |
| @@ -241,19 +168,21 @@ static int smk_set_access(struct smack_rule *srp) · 2 unmodified lines | ||
| 241 | 168 | } |
| 242 | 169 | } |
| 243 | 170 | if (found == 0) |
| 244 | − list_add_rcu(&srp->list, &smack_rule_list); | |
| 171 | + list_add_rcu(&srp->list, rule_list); | |
| 245 | 172 | |
| 246 | − mutex_unlock(&smack_list_lock); | |
| 173 | + mutex_unlock(rule_lock); | |
| 247 | 174 | |
| 248 | − return ret; | |
| 175 | + return found; | |
| 249 | 176 | } |
| 250 | 177 | |
| 251 | 178 | /** |
| 252 | − * smk_write_load - write() for /smack/load | |
| 179 | + * smk_write_load_list - write() for any /smack/load | |
| 253 | 180 | * @file: file pointer, not actually used |
| 254 | 181 | * @buf: where to get the data from |
| 255 | 182 | * @count: bytes sent |
| 256 | 183 | * @ppos: where to start - must be 0 |
| 184 | + * @rule_list: the list of rules to write to | |
| 185 | + * @rule_lock: lock for the rule list | |
| 257 | 186 | * |
| 258 | 187 | * Get one smack access rule from above. |
| 259 | 188 | * The format is exactly: |
| @@ -263,21 +192,19 @@ static int smk_set_access(struct smack_rule *srp) · 3 unmodified lines | ||
| 263 | 192 | * |
| 264 | 193 | * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes. |
| 265 | 194 | */ |
| 266 | −static ssize_t smk_write_load(struct file *file, const char __user *buf, | |
| 267 | − size_t count, loff_t *ppos) | |
| 195 | +static ssize_t smk_write_load_list(struct file *file, const char __user *buf, | |
| 196 | + size_t count, loff_t *ppos, | |
| 197 | + struct list_head *rule_list, | |
| 198 | + struct mutex *rule_lock) | |
| 268 | 199 | { |
| 269 | 200 | struct smack_rule *rule; |
| 270 | 201 | char *data; |
| 271 | 202 | int rc = -EINVAL; |
| 272 | 203 | |
| 273 | 204 | /* |
| 274 | − * Must have privilege. | |
| 275 | 205 | * No partial writes. |
| 276 | 206 | * Enough data must be present. |
| 277 | 207 | */ |
| 278 | − if (!capable(CAP_MAC_ADMIN)) | |
| 279 | − return -EPERM; | |
| 280 | − | |
| 281 | 208 | if (*ppos != 0) |
| 282 | 209 | return -EINVAL; |
| 283 | 210 | /* |
| @@ -372,11 +299,13 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf, · 88 unmodified lines | ||
| 372 | 299 | goto out_free_rule; |
| 373 | 300 | } |
| 374 | 301 | |
| 375 | − rc = smk_set_access(rule); | |
| 376 | − | |
| 377 | − if (!rc) | |
| 378 | − rc = count; | |
| 379 | − goto out; | |
| 302 | + rc = count; | |
| 303 | + /* | |
| 304 | + * smk_set_access returns true if there was already a rule | |
| 305 | + * for the subject/object pair, and false if it was new. | |
| 306 | + */ | |
| 307 | + if (!smk_set_access(rule, rule_list, rule_lock)) | |
| 308 | + goto out; | |
| 380 | 309 | |
| 381 | 310 | out_free_rule: |
| 382 | 311 | kfree(rule); |
| @@ -385,6 +314,108 @@ out: · 2 unmodified lines | ||
| 385 | 314 | return rc; |
| 386 | 315 | } |
| 387 | 316 | |
| 317 | + | |
| 318 | +/* | |
| 319 | + * Seq_file read operations for /smack/load | |
| 320 | + */ | |
| 321 | + | |
| 322 | +static void *load_seq_start(struct seq_file *s, loff_t *pos) | |
| 323 | +{ | |
| 324 | + if (*pos == SEQ_READ_FINISHED) | |
| 325 | + return NULL; | |
| 326 | + if (list_empty(&smack_rule_list)) | |
| 327 | + return NULL; | |
| 328 | + return smack_rule_list.next; | |
| 329 | +} | |
| 330 | + | |
| 331 | +static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) | |
| 332 | +{ | |
| 333 | + struct list_head *list = v; | |
| 334 | + | |
| 335 | + if (list_is_last(list, &smack_rule_list)) { | |
| 336 | + *pos = SEQ_READ_FINISHED; | |
| 337 | + return NULL; | |
| 338 | + } | |
| 339 | + return list->next; | |
| 340 | +} | |
| 341 | + | |
| 342 | +static int load_seq_show(struct seq_file *s, void *v) | |
| 343 | +{ | |
| 344 | + struct list_head *list = v; | |
| 345 | + struct smack_rule *srp = | |
| 346 | + list_entry(list, struct smack_rule, list); | |
| 347 | + | |
| 348 | + seq_printf(s, "%s %s", (char *)srp->smk_subject, | |
| 349 | + (char *)srp->smk_object); | |
| 350 | + | |
| 351 | + seq_putc(s, ' '); | |
| 352 | + | |
| 353 | + if (srp->smk_access & MAY_READ) | |
| 354 | + seq_putc(s, 'r'); | |
| 355 | + if (srp->smk_access & MAY_WRITE) | |
| 356 | + seq_putc(s, 'w'); | |
| 357 | + if (srp->smk_access & MAY_EXEC) | |
| 358 | + seq_putc(s, 'x'); | |
| 359 | + if (srp->smk_access & MAY_APPEND) | |
| 360 | + seq_putc(s, 'a'); | |
| 361 | + if (srp->smk_access & MAY_TRANSMUTE) | |
| 362 | + seq_putc(s, 't'); | |
| 363 | + if (srp->smk_access == 0) | |
| 364 | + seq_putc(s, '-'); | |
| 365 | + | |
| 366 | + seq_putc(s, '\n'); | |
| 367 | + | |
| 368 | + return 0; | |
| 369 | +} | |
| 370 | + | |
| 371 | +static void load_seq_stop(struct seq_file *s, void *v) | |
| 372 | +{ | |
| 373 | + /* No-op */ | |
| 374 | +} | |
| 375 | + | |
| 376 | +static const struct seq_operations load_seq_ops = { | |
| 377 | + .start = load_seq_start, | |
| 378 | + .next = load_seq_next, | |
| 379 | + .show = load_seq_show, | |
| 380 | + .stop = load_seq_stop, | |
| 381 | +}; | |
| 382 | + | |
| 383 | +/** | |
| 384 | + * smk_open_load - open() for /smack/load | |
| 385 | + * @inode: inode structure representing file | |
| 386 | + * @file: "load" file pointer | |
| 387 | + * | |
| 388 | + * For reading, use load_seq_* seq_file reading operations. | |
| 389 | + */ | |
| 390 | +static int smk_open_load(struct inode *inode, struct file *file) | |
| 391 | +{ | |
| 392 | + return seq_open(file, &load_seq_ops); | |
| 393 | +} | |
| 394 | + | |
| 395 | +/** | |
| 396 | + * smk_write_load - write() for /smack/load | |
| 397 | + * @file: file pointer, not actually used | |
| 398 | + * @buf: where to get the data from | |
| 399 | + * @count: bytes sent | |
| 400 | + * @ppos: where to start - must be 0 | |
| 401 | + * | |
| 402 | + */ | |
| 403 | +static ssize_t smk_write_load(struct file *file, const char __user *buf, | |
| 404 | + size_t count, loff_t *ppos) | |
| 405 | +{ | |
| 406 | + | |
| 407 | + /* | |
| 408 | + * Must have privilege. | |
| 409 | + * No partial writes. | |
| 410 | + * Enough data must be present. | |
| 411 | + */ | |
| 412 | + if (!capable(CAP_MAC_ADMIN)) | |
| 413 | + return -EPERM; | |
| 414 | + | |
| 415 | + return smk_write_load_list(file, buf, count, ppos, &smack_rule_list, | |
| 416 | + &smack_list_lock); | |
| 417 | +} | |
| 418 | + | |
| 388 | 419 | static const struct file_operations smk_load_ops = { |
| 389 | 420 | .open = smk_open_load, |
| 390 | 421 | .read = seq_read, |
| @@ -1288,6 +1319,112 @@ static const struct file_operations smk_logging_ops = { · 897 unmodified lines | ||
| 1288 | 1319 | .write = smk_write_logging, |
| 1289 | 1320 | .llseek = default_llseek, |
| 1290 | 1321 | }; |
| 1322 | + | |
| 1323 | +/* | |
| 1324 | + * Seq_file read operations for /smack/load-self | |
| 1325 | + */ | |
| 1326 | + | |
| 1327 | +static void *load_self_seq_start(struct seq_file *s, loff_t *pos) | |
| 1328 | +{ | |
| 1329 | + struct task_smack *tsp = current_security(); | |
| 1330 | + | |
| 1331 | + if (*pos == SEQ_READ_FINISHED) | |
| 1332 | + return NULL; | |
| 1333 | + if (list_empty(&tsp->smk_rules)) | |
| 1334 | + return NULL; | |
| 1335 | + return tsp->smk_rules.next; | |
| 1336 | +} | |
| 1337 | + | |
| 1338 | +static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos) | |
| 1339 | +{ | |
| 1340 | + struct task_smack *tsp = current_security(); | |
| 1341 | + struct list_head *list = v; | |
| 1342 | + | |
| 1343 | + if (list_is_last(list, &tsp->smk_rules)) { | |
| 1344 | + *pos = SEQ_READ_FINISHED; | |
| 1345 | + return NULL; | |
| 1346 | + } | |
| 1347 | + return list->next; | |
| 1348 | +} | |
| 1349 | + | |
| 1350 | +static int load_self_seq_show(struct seq_file *s, void *v) | |
| 1351 | +{ | |
| 1352 | + struct list_head *list = v; | |
| 1353 | + struct smack_rule *srp = | |
| 1354 | + list_entry(list, struct smack_rule, list); | |
| 1355 | + | |
| 1356 | + seq_printf(s, "%s %s", (char *)srp->smk_subject, | |
| 1357 | + (char *)srp->smk_object); | |
| 1358 | + | |
| 1359 | + seq_putc(s, ' '); | |
| 1360 | + | |
| 1361 | + if (srp->smk_access & MAY_READ) | |
| 1362 | + seq_putc(s, 'r'); | |
| 1363 | + if (srp->smk_access & MAY_WRITE) | |
| 1364 | + seq_putc(s, 'w'); | |
| 1365 | + if (srp->smk_access & MAY_EXEC) | |
| 1366 | + seq_putc(s, 'x'); | |
| 1367 | + if (srp->smk_access & MAY_APPEND) | |
| 1368 | + seq_putc(s, 'a'); | |
| 1369 | + if (srp->smk_access & MAY_TRANSMUTE) | |
| 1370 | + seq_putc(s, 't'); | |
| 1371 | + if (srp->smk_access == 0) | |
| 1372 | + seq_putc(s, '-'); | |
| 1373 | + | |
| 1374 | + seq_putc(s, '\n'); | |
| 1375 | + | |
| 1376 | + return 0; | |
| 1377 | +} | |
| 1378 | + | |
| 1379 | +static void load_self_seq_stop(struct seq_file *s, void *v) | |
| 1380 | +{ | |
| 1381 | + /* No-op */ | |
| 1382 | +} | |
| 1383 | + | |
| 1384 | +static const struct seq_operations load_self_seq_ops = { | |
| 1385 | + .start = load_self_seq_start, | |
| 1386 | + .next = load_self_seq_next, | |
| 1387 | + .show = load_self_seq_show, | |
| 1388 | + .stop = load_self_seq_stop, | |
| 1389 | +}; | |
| 1390 | + | |
| 1391 | + | |
| 1392 | +/** | |
| 1393 | + * smk_open_load_self - open() for /smack/load-self | |
| 1394 | + * @inode: inode structure representing file | |
| 1395 | + * @file: "load" file pointer | |
| 1396 | + * | |
| 1397 | + * For reading, use load_seq_* seq_file reading operations. | |
| 1398 | + */ | |
| 1399 | +static int smk_open_load_self(struct inode *inode, struct file *file) | |
| 1400 | +{ | |
| 1401 | + return seq_open(file, &load_self_seq_ops); | |
| 1402 | +} | |
| 1403 | + | |
| 1404 | +/** | |
| 1405 | + * smk_write_load_self - write() for /smack/load-self | |
| 1406 | + * @file: file pointer, not actually used | |
| 1407 | + * @buf: where to get the data from | |
| 1408 | + * @count: bytes sent | |
| 1409 | + * @ppos: where to start - must be 0 | |
| 1410 | + * | |
| 1411 | + */ | |
| 1412 | +static ssize_t smk_write_load_self(struct file *file, const char __user *buf, | |
| 1413 | + size_t count, loff_t *ppos) | |
| 1414 | +{ | |
| 1415 | + struct task_smack *tsp = current_security(); | |
| 1416 | + | |
| 1417 | + return smk_write_load_list(file, buf, count, ppos, &tsp->smk_rules, | |
| 1418 | + &tsp->smk_rules_lock); | |
| 1419 | +} | |
| 1420 | + | |
| 1421 | +static const struct file_operations smk_load_self_ops = { | |
| 1422 | + .open = smk_open_load_self, | |
| 1423 | + .read = seq_read, | |
| 1424 | + .llseek = seq_lseek, | |
| 1425 | + .write = smk_write_load_self, | |
| 1426 | + .release = seq_release, | |
| 1427 | +}; | |
| 1291 | 1428 | /** |
| 1292 | 1429 | * smk_fill_super - fill the /smackfs superblock |
| 1293 | 1430 | * @sb: the empty superblock |
| @@ -1304,23 +1441,26 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) · 10 unmodified lines | ||
| 1304 | 1441 | struct inode *root_inode; |
| 1305 | 1442 | |
| 1306 | 1443 | static struct tree_descr smack_files[] = { |
| 1307 | − [SMK_LOAD] = | |
| 1308 | − {"load", &smk_load_ops, S_IRUGO|S_IWUSR}, | |
| 1309 | − [SMK_CIPSO] = | |
| 1310 | − {"cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR}, | |
| 1311 | − [SMK_DOI] = | |
| 1312 | − {"doi", &smk_doi_ops, S_IRUGO|S_IWUSR}, | |
| 1313 | − [SMK_DIRECT] = | |
| 1314 | − {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, | |
| 1315 | − [SMK_AMBIENT] = | |
| 1316 | − {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, | |
| 1317 | − [SMK_NETLBLADDR] = | |
| 1318 | − {"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR}, | |
| 1319 | − [SMK_ONLYCAP] = | |
| 1320 | − {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, | |
| 1321 | − [SMK_LOGGING] = | |
| 1322 | − {"logging", &smk_logging_ops, S_IRUGO|S_IWUSR}, | |
| 1323 | − /* last one */ {""} | |
| 1444 | + [SMK_LOAD] = { | |
| 1445 | + "load", &smk_load_ops, S_IRUGO|S_IWUSR}, | |
| 1446 | + [SMK_CIPSO] = { | |
| 1447 | + "cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR}, | |
| 1448 | + [SMK_DOI] = { | |
| 1449 | + "doi", &smk_doi_ops, S_IRUGO|S_IWUSR}, | |
| 1450 | + [SMK_DIRECT] = { | |
| 1451 | + "direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, | |
| 1452 | + [SMK_AMBIENT] = { | |
| 1453 | + "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, | |
| 1454 | + [SMK_NETLBLADDR] = { | |
| 1455 | + "netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR}, | |
| 1456 | + [SMK_ONLYCAP] = { | |
| 1457 | + "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, | |
| 1458 | + [SMK_LOGGING] = { | |
| 1459 | + "logging", &smk_logging_ops, S_IRUGO|S_IWUSR}, | |
| 1460 | + [SMK_LOAD_SELF] = { | |
| 1461 | + "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO}, | |
| 1462 | + /* last one */ | |
| 1463 | + {""} | |
| 1324 | 1464 | }; |
| 1325 | 1465 | |
| 1326 | 1466 | rc = simple_fill_super(sb, SMACK_MAGIC, smack_files); |
| @@ -927,7 +927,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, · 926 unmodified lines | ||
| 927 | 927 | struct path *path, const int flag) |
| 928 | 928 | { |
| 929 | 929 | const u8 acc_mode = ACC_MODE(flag); |
| 930 | − int error = -ENOMEM; | |
| 930 | + int error = 0; | |
| 931 | 931 | struct tomoyo_path_info buf; |
| 932 | 932 | struct tomoyo_request_info r; |
| 933 | 933 | int idx; |
| @@ -938,9 +938,6 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, · 4 unmodified lines | ||
| 938 | 938 | buf.name = NULL; |
| 939 | 939 | r.mode = TOMOYO_CONFIG_DISABLED; |
| 940 | 940 | idx = tomoyo_read_lock(); |
| 941 | − if (!tomoyo_get_realpath(&buf, path)) | |
| 942 | − goto out; | |
| 943 | − error = 0; | |
| 944 | 941 | /* |
| 945 | 942 | * If the filename is specified by "deny_rewrite" keyword, |
| 946 | 943 | * we need to check "allow_rewrite" permission when the filename is not |