diff options
author | James Morris <jmorris@namei.org> | 2011-03-15 18:41:17 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-03-15 18:41:17 -0400 |
commit | a002951c97ff8da49938c982a4c236bf2fafdc9f (patch) | |
tree | d43e7885ea7376df0a47a0fc8ceca66dc5bfa357 | |
parent | 521cb40b0c44418a4fd36dc633f575813d59a43d (diff) | |
parent | c151694b2c48d956ac8c8c59c6927f89cc29ef70 (diff) |
Merge branch 'next' into for-linus
85 files changed, 1549 insertions, 712 deletions
diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt index 09b55e461740..69686ad12c66 100644 --- a/Documentation/keys-request-key.txt +++ b/Documentation/keys-request-key.txt | |||
@@ -127,14 +127,15 @@ This is because process A's keyrings can't simply be attached to | |||
127 | of them, and (b) it requires the same UID/GID/Groups all the way through. | 127 | of them, and (b) it requires the same UID/GID/Groups all the way through. |
128 | 128 | ||
129 | 129 | ||
130 | ====================== | 130 | ==================================== |
131 | NEGATIVE INSTANTIATION | 131 | NEGATIVE INSTANTIATION AND REJECTION |
132 | ====================== | 132 | ==================================== |
133 | 133 | ||
134 | Rather than instantiating a key, it is possible for the possessor of an | 134 | Rather than instantiating a key, it is possible for the possessor of an |
135 | authorisation key to negatively instantiate a key that's under construction. | 135 | authorisation key to negatively instantiate a key that's under construction. |
136 | This is a short duration placeholder that causes any attempt at re-requesting | 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 | This is provided to prevent excessive repeated spawning of /sbin/request-key | 140 | This is provided to prevent excessive repeated spawning of /sbin/request-key |
140 | processes for a key that will never be obtainable. | 141 | processes for a key that will never be obtainable. |
diff --git a/Documentation/keys.txt b/Documentation/keys.txt index e4dbbdb1bd96..6523a9e6f293 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt | |||
@@ -637,6 +637,9 @@ The keyctl syscall functions are: | |||
637 | long keyctl(KEYCTL_INSTANTIATE, key_serial_t key, | 637 | long keyctl(KEYCTL_INSTANTIATE, key_serial_t key, |
638 | const void *payload, size_t plen, | 638 | const void *payload, size_t plen, |
639 | key_serial_t keyring); | 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 | If the kernel calls back to userspace to complete the instantiation of a | 644 | If the kernel calls back to userspace to complete the instantiation of a |
642 | key, userspace should use this call to supply data for the key before the | 645 | key, userspace should use this call to supply data for the key before the |
@@ -652,11 +655,16 @@ The keyctl syscall functions are: | |||
652 | 655 | ||
653 | The payload and plen arguments describe the payload data as for add_key(). | 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 | (*) Negatively instantiate a partially constructed key. | 662 | (*) Negatively instantiate a partially constructed key. |
657 | 663 | ||
658 | long keyctl(KEYCTL_NEGATE, key_serial_t key, | 664 | long keyctl(KEYCTL_NEGATE, key_serial_t key, |
659 | unsigned timeout, key_serial_t keyring); | 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 | If the kernel calls back to userspace to complete the instantiation of a | 669 | If the kernel calls back to userspace to complete the instantiation of a |
662 | key, userspace should use this call mark the key as negative before the | 670 | key, userspace should use this call mark the key as negative before the |
@@ -669,6 +677,10 @@ The keyctl syscall functions are: | |||
669 | that keyring, however all the constraints applying in KEYCTL_LINK apply in | 677 | that keyring, however all the constraints applying in KEYCTL_LINK apply in |
670 | this case too. | 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 | (*) Set the default request-key destination keyring. | 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: | |||
1062 | viable. | 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 | (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); | 1084 | (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); |
1066 | 1085 | ||
1067 | This method is called to attach a payload to a key during construction. | 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 | |||
1231 | example, the KDE desktop manager). | 1250 | example, the KDE desktop manager). |
1232 | 1251 | ||
1233 | The program (or whatever it calls) should finish construction of the key by | 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 | 1253 | calling KEYCTL_INSTANTIATE or KEYCTL_INSTANTIATE_IOV, which also permits it to |
1235 | the keyrings (probably the session ring) before returning. Alternatively, the | 1254 | cache the key in one of the keyrings (probably the session ring) before |
1236 | key can be marked as negative with KEYCTL_NEGATE; this also permits the key to | 1255 | returning. Alternatively, the key can be marked as negative with KEYCTL_NEGATE |
1237 | be cached in one of the keyrings. | 1256 | or KEYCTL_REJECT; this also permits the key to be cached in one of the |
1257 | keyrings. | ||
1238 | 1258 | ||
1239 | If it returns with the key remaining in the unconstructed state, the key will | 1259 | If it returns with the key remaining in the unconstructed state, the key will |
1240 | be marked as being negative, it will be added to the session keyring, and an | 1260 | be marked as being negative, it will be added to the session keyring, and an |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index d5ed94d30aad..b46b75bef496 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -2138,6 +2138,11 @@ config SYSVIPC_COMPAT | |||
2138 | def_bool y | 2138 | def_bool y |
2139 | depends on COMPAT && SYSVIPC | 2139 | depends on COMPAT && SYSVIPC |
2140 | 2140 | ||
2141 | config KEYS_COMPAT | ||
2142 | bool | ||
2143 | depends on COMPAT && KEYS | ||
2144 | default y | ||
2145 | |||
2141 | endmenu | 2146 | endmenu |
2142 | 2147 | ||
2143 | 2148 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9007bbd01dbf..93323ac26b0a 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -90,13 +90,14 @@ static noinline int cow_file_range(struct inode *inode, | |||
90 | unsigned long *nr_written, int unlock); | 90 | unsigned long *nr_written, int unlock); |
91 | 91 | ||
92 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, | 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 | int err; | 96 | int err; |
96 | 97 | ||
97 | err = btrfs_init_acl(trans, inode, dir); | 98 | err = btrfs_init_acl(trans, inode, dir); |
98 | if (!err) | 99 | if (!err) |
99 | err = btrfs_xattr_security_init(trans, inode, dir); | 100 | err = btrfs_xattr_security_init(trans, inode, dir, qstr); |
100 | return err; | 101 | return err; |
101 | } | 102 | } |
102 | 103 | ||
@@ -4704,7 +4705,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
4704 | if (IS_ERR(inode)) | 4705 | if (IS_ERR(inode)) |
4705 | goto out_unlock; | 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 | if (err) { | 4709 | if (err) { |
4709 | drop_inode = 1; | 4710 | drop_inode = 1; |
4710 | goto out_unlock; | 4711 | goto out_unlock; |
@@ -4765,7 +4766,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
4765 | if (IS_ERR(inode)) | 4766 | if (IS_ERR(inode)) |
4766 | goto out_unlock; | 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 | if (err) { | 4770 | if (err) { |
4770 | drop_inode = 1; | 4771 | drop_inode = 1; |
4771 | goto out_unlock; | 4772 | goto out_unlock; |
@@ -4894,7 +4895,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
4894 | 4895 | ||
4895 | drop_on_err = 1; | 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 | if (err) | 4899 | if (err) |
4899 | goto out_fail; | 4900 | goto out_fail; |
4900 | 4901 | ||
@@ -7106,7 +7107,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
7106 | if (IS_ERR(inode)) | 7107 | if (IS_ERR(inode)) |
7107 | goto out_unlock; | 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 | if (err) { | 7111 | if (err) { |
7111 | drop_inode = 1; | 7112 | drop_inode = 1; |
7112 | goto out_unlock; | 7113 | goto out_unlock; |
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index a5776531dc2b..d779cefcfd7d 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c | |||
@@ -370,7 +370,8 @@ int btrfs_removexattr(struct dentry *dentry, const char *name) | |||
370 | } | 370 | } |
371 | 371 | ||
372 | int btrfs_xattr_security_init(struct btrfs_trans_handle *trans, | 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 | int err; | 376 | int err; |
376 | size_t len; | 377 | size_t len; |
@@ -378,7 +379,8 @@ int btrfs_xattr_security_init(struct btrfs_trans_handle *trans, | |||
378 | char *suffix; | 379 | char *suffix; |
379 | char *name; | 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 | if (err) { | 384 | if (err) { |
383 | if (err == -EOPNOTSUPP) | 385 | if (err == -EOPNOTSUPP) |
384 | return 0; | 386 | return 0; |
diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h index 7a43fd640bbb..b3cc8039134b 100644 --- a/fs/btrfs/xattr.h +++ b/fs/btrfs/xattr.h | |||
@@ -37,6 +37,7 @@ extern int btrfs_setxattr(struct dentry *dentry, const char *name, | |||
37 | extern int btrfs_removexattr(struct dentry *dentry, const char *name); | 37 | extern int btrfs_removexattr(struct dentry *dentry, const char *name); |
38 | 38 | ||
39 | extern int btrfs_xattr_security_init(struct btrfs_trans_handle *trans, | 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 | #endif /* __XATTR__ */ | 43 | #endif /* __XATTR__ */ |
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 42c7fafc8bfe..a0358c2189cb 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
@@ -275,6 +275,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, | |||
275 | bool preemptive) | 275 | bool preemptive) |
276 | { | 276 | { |
277 | struct dentry *grave, *trap; | 277 | struct dentry *grave, *trap; |
278 | struct path path, path_to_graveyard; | ||
278 | char nbuffer[8 + 8 + 1]; | 279 | char nbuffer[8 + 8 + 1]; |
279 | int ret; | 280 | int ret; |
280 | 281 | ||
@@ -287,10 +288,18 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, | |||
287 | /* non-directories can just be unlinked */ | 288 | /* non-directories can just be unlinked */ |
288 | if (!S_ISDIR(rep->d_inode->i_mode)) { | 289 | if (!S_ISDIR(rep->d_inode->i_mode)) { |
289 | _debug("unlink stale object"); | 290 | _debug("unlink stale object"); |
290 | ret = vfs_unlink(dir->d_inode, rep); | ||
291 | 291 | ||
292 | if (preemptive) | 292 | path.mnt = cache->mnt; |
293 | cachefiles_mark_object_buried(cache, rep); | 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 | mutex_unlock(&dir->d_inode->i_mutex); | 304 | mutex_unlock(&dir->d_inode->i_mutex); |
296 | 305 | ||
@@ -379,12 +388,23 @@ try_again: | |||
379 | } | 388 | } |
380 | 389 | ||
381 | /* attempt the rename */ | 390 | /* attempt the rename */ |
382 | ret = vfs_rename(dir->d_inode, rep, cache->graveyard->d_inode, grave); | 391 | path.mnt = cache->mnt; |
383 | if (ret != 0 && ret != -ENOMEM) | 392 | path.dentry = dir; |
384 | cachefiles_io_error(cache, "Rename failed with error %d", ret); | 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) | 405 | if (preemptive) |
387 | cachefiles_mark_object_buried(cache, rep); | 406 | cachefiles_mark_object_buried(cache, rep); |
407 | } | ||
388 | 408 | ||
389 | unlock_rename(cache->graveyard, dir); | 409 | unlock_rename(cache->graveyard, dir); |
390 | dput(grave); | 410 | dput(grave); |
@@ -448,6 +468,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, | |||
448 | { | 468 | { |
449 | struct cachefiles_cache *cache; | 469 | struct cachefiles_cache *cache; |
450 | struct dentry *dir, *next = NULL; | 470 | struct dentry *dir, *next = NULL; |
471 | struct path path; | ||
451 | unsigned long start; | 472 | unsigned long start; |
452 | const char *name; | 473 | const char *name; |
453 | int ret, nlen; | 474 | int ret, nlen; |
@@ -458,6 +479,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, | |||
458 | 479 | ||
459 | cache = container_of(parent->fscache.cache, | 480 | cache = container_of(parent->fscache.cache, |
460 | struct cachefiles_cache, cache); | 481 | struct cachefiles_cache, cache); |
482 | path.mnt = cache->mnt; | ||
461 | 483 | ||
462 | ASSERT(parent->dentry); | 484 | ASSERT(parent->dentry); |
463 | ASSERT(parent->dentry->d_inode); | 485 | ASSERT(parent->dentry->d_inode); |
@@ -511,6 +533,10 @@ lookup_again: | |||
511 | if (ret < 0) | 533 | if (ret < 0) |
512 | goto create_error; | 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 | start = jiffies; | 540 | start = jiffies; |
515 | ret = vfs_mkdir(dir->d_inode, next, 0); | 541 | ret = vfs_mkdir(dir->d_inode, next, 0); |
516 | cachefiles_hist(cachefiles_mkdir_histogram, start); | 542 | cachefiles_hist(cachefiles_mkdir_histogram, start); |
@@ -536,6 +562,10 @@ lookup_again: | |||
536 | if (ret < 0) | 562 | if (ret < 0) |
537 | goto create_error; | 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 | start = jiffies; | 569 | start = jiffies; |
540 | ret = vfs_create(dir->d_inode, next, S_IFREG, NULL); | 570 | ret = vfs_create(dir->d_inode, next, S_IFREG, NULL); |
541 | cachefiles_hist(cachefiles_create_histogram, start); | 571 | cachefiles_hist(cachefiles_create_histogram, start); |
@@ -692,6 +722,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, | |||
692 | { | 722 | { |
693 | struct dentry *subdir; | 723 | struct dentry *subdir; |
694 | unsigned long start; | 724 | unsigned long start; |
725 | struct path path; | ||
695 | int ret; | 726 | int ret; |
696 | 727 | ||
697 | _enter(",,%s", dirname); | 728 | _enter(",,%s", dirname); |
@@ -719,6 +750,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, | |||
719 | 750 | ||
720 | _debug("attempt mkdir"); | 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 | ret = vfs_mkdir(dir->d_inode, subdir, 0700); | 758 | ret = vfs_mkdir(dir->d_inode, subdir, 0700); |
723 | if (ret < 0) | 759 | if (ret < 0) |
724 | goto mkdir_error; | 760 | goto mkdir_error; |
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 6346a2acf326..1b48c3370872 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
@@ -110,7 +110,7 @@ extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **); | |||
110 | extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *, int); | 110 | extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *, int); |
111 | 111 | ||
112 | /* ialloc.c */ | 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 | extern void ext2_free_inode (struct inode *); | 114 | extern void ext2_free_inode (struct inode *); |
115 | extern unsigned long ext2_count_free_inodes (struct super_block *); | 115 | extern unsigned long ext2_count_free_inodes (struct super_block *); |
116 | extern void ext2_check_inodes_bitmap (struct super_block *); | 116 | extern void ext2_check_inodes_bitmap (struct super_block *); |
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index ad70479aabff..ee9ed31948e1 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c | |||
@@ -429,7 +429,8 @@ found: | |||
429 | return group; | 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 | struct super_block *sb; | 435 | struct super_block *sb; |
435 | struct buffer_head *bitmap_bh = NULL; | 436 | struct buffer_head *bitmap_bh = NULL; |
@@ -585,7 +586,7 @@ got: | |||
585 | if (err) | 586 | if (err) |
586 | goto fail_free_drop; | 587 | goto fail_free_drop; |
587 | 588 | ||
588 | err = ext2_init_security(inode,dir); | 589 | err = ext2_init_security(inode, dir, qstr); |
589 | if (err) | 590 | if (err) |
590 | goto fail_free_drop; | 591 | goto fail_free_drop; |
591 | 592 | ||
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index adb91855ccd0..ed5c5d496ee9 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c | |||
@@ -104,7 +104,7 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st | |||
104 | 104 | ||
105 | dquot_initialize(dir); | 105 | dquot_initialize(dir); |
106 | 106 | ||
107 | inode = ext2_new_inode(dir, mode); | 107 | inode = ext2_new_inode(dir, mode, &dentry->d_name); |
108 | if (IS_ERR(inode)) | 108 | if (IS_ERR(inode)) |
109 | return PTR_ERR(inode); | 109 | return PTR_ERR(inode); |
110 | 110 | ||
@@ -133,7 +133,7 @@ static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_ | |||
133 | 133 | ||
134 | dquot_initialize(dir); | 134 | dquot_initialize(dir); |
135 | 135 | ||
136 | inode = ext2_new_inode (dir, mode); | 136 | inode = ext2_new_inode (dir, mode, &dentry->d_name); |
137 | err = PTR_ERR(inode); | 137 | err = PTR_ERR(inode); |
138 | if (!IS_ERR(inode)) { | 138 | if (!IS_ERR(inode)) { |
139 | init_special_inode(inode, inode->i_mode, rdev); | 139 | init_special_inode(inode, inode->i_mode, rdev); |
@@ -159,7 +159,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry, | |||
159 | 159 | ||
160 | dquot_initialize(dir); | 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 | err = PTR_ERR(inode); | 163 | err = PTR_ERR(inode); |
164 | if (IS_ERR(inode)) | 164 | if (IS_ERR(inode)) |
165 | goto out; | 165 | goto out; |
@@ -230,7 +230,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) | |||
230 | 230 | ||
231 | inode_inc_link_count(dir); | 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 | err = PTR_ERR(inode); | 234 | err = PTR_ERR(inode); |
235 | if (IS_ERR(inode)) | 235 | if (IS_ERR(inode)) |
236 | goto out_dir; | 236 | goto out_dir; |
diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h index a1a1c2184616..5e41cccff762 100644 --- a/fs/ext2/xattr.h +++ b/fs/ext2/xattr.h | |||
@@ -116,9 +116,11 @@ exit_ext2_xattr(void) | |||
116 | # endif /* CONFIG_EXT2_FS_XATTR */ | 116 | # endif /* CONFIG_EXT2_FS_XATTR */ |
117 | 117 | ||
118 | #ifdef CONFIG_EXT2_FS_SECURITY | 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 | #else | 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 | return 0; | 125 | return 0; |
124 | } | 126 | } |
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c index 3004e15d5da5..5d979b4347b0 100644 --- a/fs/ext2/xattr_security.c +++ b/fs/ext2/xattr_security.c | |||
@@ -47,14 +47,15 @@ ext2_xattr_security_set(struct dentry *dentry, const char *name, | |||
47 | } | 47 | } |
48 | 48 | ||
49 | int | 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 | int err; | 53 | int err; |
53 | size_t len; | 54 | size_t len; |
54 | void *value; | 55 | void *value; |
55 | char *name; | 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 | if (err) { | 59 | if (err) { |
59 | if (err == -EOPNOTSUPP) | 60 | if (err == -EOPNOTSUPP) |
60 | return 0; | 61 | return 0; |
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 9724aef22460..bfc2dc43681d 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c | |||
@@ -404,7 +404,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent) | |||
404 | * For other inodes, search forward from the parent directory's block | 404 | * For other inodes, search forward from the parent directory's block |
405 | * group to find a free inode. | 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 | struct super_block *sb; | 410 | struct super_block *sb; |
410 | struct buffer_head *bitmap_bh = NULL; | 411 | struct buffer_head *bitmap_bh = NULL; |
@@ -589,7 +590,7 @@ got: | |||
589 | if (err) | 590 | if (err) |
590 | goto fail_free_drop; | 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 | if (err) | 594 | if (err) |
594 | goto fail_free_drop; | 595 | goto fail_free_drop; |
595 | 596 | ||
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index b27ba71810ec..9dba3bd69d9a 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -1710,7 +1710,7 @@ retry: | |||
1710 | if (IS_DIRSYNC(dir)) | 1710 | if (IS_DIRSYNC(dir)) |
1711 | handle->h_sync = 1; | 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 | err = PTR_ERR(inode); | 1714 | err = PTR_ERR(inode); |
1715 | if (!IS_ERR(inode)) { | 1715 | if (!IS_ERR(inode)) { |
1716 | inode->i_op = &ext3_file_inode_operations; | 1716 | inode->i_op = &ext3_file_inode_operations; |
@@ -1746,7 +1746,7 @@ retry: | |||
1746 | if (IS_DIRSYNC(dir)) | 1746 | if (IS_DIRSYNC(dir)) |
1747 | handle->h_sync = 1; | 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 | err = PTR_ERR(inode); | 1750 | err = PTR_ERR(inode); |
1751 | if (!IS_ERR(inode)) { | 1751 | if (!IS_ERR(inode)) { |
1752 | init_special_inode(inode, inode->i_mode, rdev); | 1752 | init_special_inode(inode, inode->i_mode, rdev); |
@@ -1784,7 +1784,7 @@ retry: | |||
1784 | if (IS_DIRSYNC(dir)) | 1784 | if (IS_DIRSYNC(dir)) |
1785 | handle->h_sync = 1; | 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 | err = PTR_ERR(inode); | 1788 | err = PTR_ERR(inode); |
1789 | if (IS_ERR(inode)) | 1789 | if (IS_ERR(inode)) |
1790 | goto out_stop; | 1790 | goto out_stop; |
@@ -2206,7 +2206,7 @@ retry: | |||
2206 | if (IS_DIRSYNC(dir)) | 2206 | if (IS_DIRSYNC(dir)) |
2207 | handle->h_sync = 1; | 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 | err = PTR_ERR(inode); | 2210 | err = PTR_ERR(inode); |
2211 | if (IS_ERR(inode)) | 2211 | if (IS_ERR(inode)) |
2212 | goto out_stop; | 2212 | goto out_stop; |
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h index 377fe7201169..2be4f69bfa64 100644 --- a/fs/ext3/xattr.h +++ b/fs/ext3/xattr.h | |||
@@ -128,10 +128,10 @@ exit_ext3_xattr(void) | |||
128 | 128 | ||
129 | #ifdef CONFIG_EXT3_FS_SECURITY | 129 | #ifdef CONFIG_EXT3_FS_SECURITY |
130 | extern int ext3_init_security(handle_t *handle, struct inode *inode, | 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 | #else | 132 | #else |
133 | static inline int ext3_init_security(handle_t *handle, struct inode *inode, | 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 | return 0; | 136 | return 0; |
137 | } | 137 | } |
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c index 03a99bfc59f9..b8d9f83aa5c5 100644 --- a/fs/ext3/xattr_security.c +++ b/fs/ext3/xattr_security.c | |||
@@ -49,14 +49,15 @@ ext3_xattr_security_set(struct dentry *dentry, const char *name, | |||
49 | } | 49 | } |
50 | 50 | ||
51 | int | 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 | int err; | 55 | int err; |
55 | size_t len; | 56 | size_t len; |
56 | void *value; | 57 | void *value; |
57 | char *name; | 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 | if (err) { | 61 | if (err) { |
61 | if (err == -EOPNOTSUPP) | 62 | if (err == -EOPNOTSUPP) |
62 | return 0; | 63 | return 0; |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index eb9097aec6f0..78b79e1bd7ed 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -1042,7 +1042,7 @@ got: | |||
1042 | if (err) | 1042 | if (err) |
1043 | goto fail_free_drop; | 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 | if (err) | 1046 | if (err) |
1047 | goto fail_free_drop; | 1047 | goto fail_free_drop; |
1048 | 1048 | ||
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index 1ef16520b950..25b7387ff183 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h | |||
@@ -145,10 +145,10 @@ ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, | |||
145 | 145 | ||
146 | #ifdef CONFIG_EXT4_FS_SECURITY | 146 | #ifdef CONFIG_EXT4_FS_SECURITY |
147 | extern int ext4_init_security(handle_t *handle, struct inode *inode, | 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 | #else | 149 | #else |
150 | static inline int ext4_init_security(handle_t *handle, struct inode *inode, | 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 | return 0; | 153 | return 0; |
154 | } | 154 | } |
diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c index 9b21268e121c..007c3bfbf094 100644 --- a/fs/ext4/xattr_security.c +++ b/fs/ext4/xattr_security.c | |||
@@ -49,14 +49,15 @@ ext4_xattr_security_set(struct dentry *dentry, const char *name, | |||
49 | } | 49 | } |
50 | 50 | ||
51 | int | 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 | int err; | 55 | int err; |
55 | size_t len; | 56 | size_t len; |
56 | void *value; | 57 | void *value; |
57 | char *name; | 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 | if (err) { | 61 | if (err) { |
61 | if (err == -EOPNOTSUPP) | 62 | if (err == -EOPNOTSUPP) |
62 | return 0; | 63 | return 0; |
diff --git a/fs/file_table.c b/fs/file_table.c index eb36b6b17e26..cbeec70ee310 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -190,7 +190,8 @@ struct file *alloc_file(struct path *path, fmode_t mode, | |||
190 | file_take_write(file); | 190 | file_take_write(file); |
191 | WARN_ON(mnt_clone_write(path->mnt)); | 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 | return file; | 195 | return file; |
195 | } | 196 | } |
196 | EXPORT_SYMBOL(alloc_file); | 197 | EXPORT_SYMBOL(alloc_file); |
@@ -251,6 +252,8 @@ static void __fput(struct file *file) | |||
251 | fops_put(file->f_op); | 252 | fops_put(file->f_op); |
252 | put_pid(file->f_owner.pid); | 253 | put_pid(file->f_owner.pid); |
253 | file_sb_list_del(file); | 254 | file_sb_list_del(file); |
255 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | ||
256 | i_readcount_dec(inode); | ||
254 | if (file->f_mode & FMODE_WRITE) | 257 | if (file->f_mode & FMODE_WRITE) |
255 | drop_file_write_access(file); | 258 | drop_file_write_access(file); |
256 | file->f_path.dentry = NULL; | 259 | file->f_path.dentry = NULL; |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 7aa7d4f8984a..97d54a28776a 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -763,14 +763,15 @@ fail: | |||
763 | return error; | 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 | int err; | 769 | int err; |
769 | size_t len; | 770 | size_t len; |
770 | void *value; | 771 | void *value; |
771 | char *name; | 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 | &name, &value, &len); | 775 | &name, &value, &len); |
775 | 776 | ||
776 | if (err) { | 777 | if (err) { |
@@ -854,7 +855,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
854 | if (error) | 855 | if (error) |
855 | goto fail_gunlock2; | 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 | if (error) | 859 | if (error) |
859 | goto fail_gunlock2; | 860 | goto fail_gunlock2; |
860 | 861 | ||
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 92978658ed18..82faddd1f321 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -215,8 +215,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, | |||
215 | no chance of AB-BA deadlock involving its f->sem). */ | 215 | no chance of AB-BA deadlock involving its f->sem). */ |
216 | mutex_unlock(&f->sem); | 216 | mutex_unlock(&f->sem); |
217 | 217 | ||
218 | ret = jffs2_do_create(c, dir_f, f, ri, | 218 | ret = jffs2_do_create(c, dir_f, f, ri, &dentry->d_name); |
219 | dentry->d_name.name, dentry->d_name.len); | ||
220 | if (ret) | 219 | if (ret) |
221 | goto fail; | 220 | goto fail; |
222 | 221 | ||
@@ -386,7 +385,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
386 | 385 | ||
387 | jffs2_complete_reservation(c); | 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 | if (ret) | 389 | if (ret) |
391 | goto fail; | 390 | goto fail; |
392 | 391 | ||
@@ -530,7 +529,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
530 | 529 | ||
531 | jffs2_complete_reservation(c); | 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 | if (ret) | 533 | if (ret) |
535 | goto fail; | 534 | goto fail; |
536 | 535 | ||
@@ -703,7 +702,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
703 | 702 | ||
704 | jffs2_complete_reservation(c); | 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 | if (ret) | 706 | if (ret) |
708 | goto fail; | 707 | goto fail; |
709 | 708 | ||
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 5a53d9bdb2b5..e4619b00f7c5 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
@@ -401,7 +401,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
401 | struct jffs2_raw_inode *ri, unsigned char *buf, | 401 | struct jffs2_raw_inode *ri, unsigned char *buf, |
402 | uint32_t offset, uint32_t writelen, uint32_t *retlen); | 402 | uint32_t offset, uint32_t writelen, uint32_t *retlen); |
403 | int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, | 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 | int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, | 405 | int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, |
406 | int namelen, struct jffs2_inode_info *dead_f, uint32_t time); | 406 | int namelen, struct jffs2_inode_info *dead_f, uint32_t time); |
407 | int jffs2_do_link(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, | 407 | int jffs2_do_link(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, |
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c index 239f51216a68..cfeb7164b085 100644 --- a/fs/jffs2/security.c +++ b/fs/jffs2/security.c | |||
@@ -23,14 +23,15 @@ | |||
23 | #include "nodelist.h" | 23 | #include "nodelist.h" |
24 | 24 | ||
25 | /* ---- Initial Security Label Attachment -------------- */ | 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 | int rc; | 29 | int rc; |
29 | size_t len; | 30 | size_t len; |
30 | void *value; | 31 | void *value; |
31 | char *name; | 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 | if (rc) { | 35 | if (rc) { |
35 | if (rc == -EOPNOTSUPP) | 36 | if (rc == -EOPNOTSUPP) |
36 | return 0; | 37 | return 0; |
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index c819eb0e982d..30d175b6d290 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c | |||
@@ -424,7 +424,9 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
424 | return ret; | 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 | struct jffs2_raw_dirent *rd; | 431 | struct jffs2_raw_dirent *rd; |
430 | struct jffs2_full_dnode *fn; | 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 | |||
466 | mutex_unlock(&f->sem); | 468 | mutex_unlock(&f->sem); |
467 | jffs2_complete_reservation(c); | 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 | if (ret) | 472 | if (ret) |
471 | return ret; | 473 | return ret; |
472 | ret = jffs2_init_acl_post(&f->vfs_inode); | 474 | ret = jffs2_init_acl_post(&f->vfs_inode); |
473 | if (ret) | 475 | if (ret) |
474 | return ret; | 476 | return ret; |
475 | 477 | ||
476 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, | 478 | ret = jffs2_reserve_space(c, sizeof(*rd)+qstr->len, &alloclen, |
477 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 479 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(qstr->len)); |
478 | 480 | ||
479 | if (ret) { | 481 | if (ret) { |
480 | /* Eep. */ | 482 | /* Eep. */ |
@@ -493,19 +495,19 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
493 | 495 | ||
494 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 496 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
495 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); | 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 | rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); | 499 | rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); |
498 | 500 | ||
499 | rd->pino = cpu_to_je32(dir_f->inocache->ino); | 501 | rd->pino = cpu_to_je32(dir_f->inocache->ino); |
500 | rd->version = cpu_to_je32(++dir_f->highest_version); | 502 | rd->version = cpu_to_je32(++dir_f->highest_version); |
501 | rd->ino = ri->ino; | 503 | rd->ino = ri->ino; |
502 | rd->mctime = ri->ctime; | 504 | rd->mctime = ri->ctime; |
503 | rd->nsize = namelen; | 505 | rd->nsize = qstr->len; |
504 | rd->type = DT_REG; | 506 | rd->type = DT_REG; |
505 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); | 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 | jffs2_free_raw_dirent(rd); | 512 | jffs2_free_raw_dirent(rd); |
511 | 513 | ||
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h index cf4f5759b42b..7be4beb306f3 100644 --- a/fs/jffs2/xattr.h +++ b/fs/jffs2/xattr.h | |||
@@ -121,10 +121,11 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); | |||
121 | #endif /* CONFIG_JFFS2_FS_XATTR */ | 121 | #endif /* CONFIG_JFFS2_FS_XATTR */ |
122 | 122 | ||
123 | #ifdef CONFIG_JFFS2_FS_SECURITY | 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 | extern const struct xattr_handler jffs2_security_xattr_handler; | 126 | extern const struct xattr_handler jffs2_security_xattr_handler; |
126 | #else | 127 | #else |
127 | #define jffs2_init_security(inode,dir) (0) | 128 | #define jffs2_init_security(inode,dir,qstr) (0) |
128 | #endif /* CONFIG_JFFS2_FS_SECURITY */ | 129 | #endif /* CONFIG_JFFS2_FS_SECURITY */ |
129 | 130 | ||
130 | #endif /* _JFFS2_FS_XATTR_H_ */ | 131 | #endif /* _JFFS2_FS_XATTR_H_ */ |
diff --git a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h index 88b6cc535bf2..e9e100fd7c09 100644 --- a/fs/jfs/jfs_xattr.h +++ b/fs/jfs/jfs_xattr.h | |||
@@ -62,10 +62,11 @@ extern ssize_t jfs_listxattr(struct dentry *, char *, size_t); | |||
62 | extern int jfs_removexattr(struct dentry *, const char *); | 62 | extern int jfs_removexattr(struct dentry *, const char *); |
63 | 63 | ||
64 | #ifdef CONFIG_JFS_SECURITY | 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 | #else | 67 | #else |
67 | static inline int jfs_init_security(tid_t tid, struct inode *inode, | 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 | return 0; | 71 | return 0; |
71 | } | 72 | } |
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 5a2b269428a6..c61600ece4fb 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
@@ -115,7 +115,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, | |||
115 | if (rc) | 115 | if (rc) |
116 | goto out3; | 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 | if (rc) { | 119 | if (rc) { |
120 | txAbort(tid, 0); | 120 | txAbort(tid, 0); |
121 | goto out3; | 121 | goto out3; |
@@ -253,7 +253,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) | |||
253 | if (rc) | 253 | if (rc) |
254 | goto out3; | 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 | if (rc) { | 257 | if (rc) { |
258 | txAbort(tid, 0); | 258 | txAbort(tid, 0); |
259 | goto out3; | 259 | goto out3; |
@@ -932,7 +932,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, | |||
932 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); | 932 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); |
933 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); | 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 | if (rc) | 936 | if (rc) |
937 | goto out3; | 937 | goto out3; |
938 | 938 | ||
@@ -1395,7 +1395,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, | |||
1395 | if (rc) | 1395 | if (rc) |
1396 | goto out3; | 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 | if (rc) { | 1399 | if (rc) { |
1400 | txAbort(tid, 0); | 1400 | txAbort(tid, 0); |
1401 | goto out3; | 1401 | goto out3; |
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 2d7f165d0f1d..3fa4c32272df 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c | |||
@@ -1091,7 +1091,8 @@ int jfs_removexattr(struct dentry *dentry, const char *name) | |||
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | #ifdef CONFIG_JFS_SECURITY | 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 | int rc; | 1097 | int rc; |
1097 | size_t len; | 1098 | size_t len; |
@@ -1099,7 +1100,8 @@ int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir) | |||
1099 | char *suffix; | 1100 | char *suffix; |
1100 | char *name; | 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 | if (rc) { | 1105 | if (rc) { |
1104 | if (rc == -EOPNOTSUPP) | 1106 | if (rc == -EOPNOTSUPP) |
1105 | return 0; | 1107 | return 0; |
diff --git a/fs/namespace.c b/fs/namespace.c index d1edf26025dc..a66feed7311d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1767,6 +1767,10 @@ static int do_remount(struct path *path, int flags, int mnt_flags, | |||
1767 | if (path->dentry != path->mnt->mnt_root) | 1767 | if (path->dentry != path->mnt->mnt_root) |
1768 | return -EINVAL; | 1768 | return -EINVAL; |
1769 | 1769 | ||
1770 | err = security_sb_remount(sb, data); | ||
1771 | if (err) | ||
1772 | return err; | ||
1773 | |||
1770 | down_write(&sb->s_umount); | 1774 | down_write(&sb->s_umount); |
1771 | if (flags & MS_BIND) | 1775 | if (flags & MS_BIND) |
1772 | err = change_mount_flags(path->mnt, flags); | 1776 | err = change_mount_flags(path->mnt, flags); |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 849fb4a2e814..d6c25d76b537 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -293,7 +293,7 @@ static int ocfs2_mknod(struct inode *dir, | |||
293 | } | 293 | } |
294 | 294 | ||
295 | /* get security xattr */ | 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 | if (status) { | 297 | if (status) { |
298 | if (status == -EOPNOTSUPP) | 298 | if (status == -EOPNOTSUPP) |
299 | si.enable = 0; | 299 | si.enable = 0; |
@@ -1665,7 +1665,7 @@ static int ocfs2_symlink(struct inode *dir, | |||
1665 | } | 1665 | } |
1666 | 1666 | ||
1667 | /* get security xattr */ | 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 | if (status) { | 1669 | if (status) { |
1670 | if (status == -EOPNOTSUPP) | 1670 | if (status == -EOPNOTSUPP) |
1671 | si.enable = 0; | 1671 | si.enable = 0; |
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 19ebc5aad391..35798b88042d 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
@@ -4328,7 +4328,8 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir, | |||
4328 | 4328 | ||
4329 | /* If the security isn't preserved, we need to re-initialize them. */ | 4329 | /* If the security isn't preserved, we need to re-initialize them. */ |
4330 | if (!preserve) { | 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 | if (error) | 4333 | if (error) |
4333 | mlog_errno(error); | 4334 | mlog_errno(error); |
4334 | } | 4335 | } |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 67cd43914641..6bb602486c6b 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -7185,7 +7185,8 @@ out: | |||
7185 | * must not hold any lock expect i_mutex. | 7185 | * must not hold any lock expect i_mutex. |
7186 | */ | 7186 | */ |
7187 | int ocfs2_init_security_and_acl(struct inode *dir, | 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 | int ret = 0; | 7191 | int ret = 0; |
7191 | struct buffer_head *dir_bh = NULL; | 7192 | struct buffer_head *dir_bh = NULL; |
@@ -7193,7 +7194,7 @@ int ocfs2_init_security_and_acl(struct inode *dir, | |||
7193 | .enable = 1, | 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 | if (!ret) { | 7198 | if (!ret) { |
7198 | ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY, | 7199 | ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY, |
7199 | si.name, si.value, si.value_len, | 7200 | si.name, si.value, si.value_len, |
@@ -7261,13 +7262,14 @@ static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name, | |||
7261 | 7262 | ||
7262 | int ocfs2_init_security_get(struct inode *inode, | 7263 | int ocfs2_init_security_get(struct inode *inode, |
7263 | struct inode *dir, | 7264 | struct inode *dir, |
7265 | const struct qstr *qstr, | ||
7264 | struct ocfs2_security_xattr_info *si) | 7266 | struct ocfs2_security_xattr_info *si) |
7265 | { | 7267 | { |
7266 | /* check whether ocfs2 support feature xattr */ | 7268 | /* check whether ocfs2 support feature xattr */ |
7267 | if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb))) | 7269 | if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb))) |
7268 | return -EOPNOTSUPP; | 7270 | return -EOPNOTSUPP; |
7269 | return security_inode_init_security(inode, dir, &si->name, &si->value, | 7271 | return security_inode_init_security(inode, dir, qstr, &si->name, |
7270 | &si->value_len); | 7272 | &si->value, &si->value_len); |
7271 | } | 7273 | } |
7272 | 7274 | ||
7273 | int ocfs2_init_security_set(handle_t *handle, | 7275 | int ocfs2_init_security_set(handle_t *handle, |
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h index aa64bb37a65b..d63cfb72316b 100644 --- a/fs/ocfs2/xattr.h +++ b/fs/ocfs2/xattr.h | |||
@@ -57,6 +57,7 @@ int ocfs2_has_inline_xattr_value_outside(struct inode *inode, | |||
57 | struct ocfs2_dinode *di); | 57 | struct ocfs2_dinode *di); |
58 | int ocfs2_xattr_remove(struct inode *, struct buffer_head *); | 58 | int ocfs2_xattr_remove(struct inode *, struct buffer_head *); |
59 | int ocfs2_init_security_get(struct inode *, struct inode *, | 59 | int ocfs2_init_security_get(struct inode *, struct inode *, |
60 | const struct qstr *, | ||
60 | struct ocfs2_security_xattr_info *); | 61 | struct ocfs2_security_xattr_info *); |
61 | int ocfs2_init_security_set(handle_t *, struct inode *, | 62 | int ocfs2_init_security_set(handle_t *, struct inode *, |
62 | struct buffer_head *, | 63 | struct buffer_head *, |
@@ -94,5 +95,6 @@ int ocfs2_reflink_xattrs(struct inode *old_inode, | |||
94 | struct buffer_head *new_bh, | 95 | struct buffer_head *new_bh, |
95 | bool preserve_security); | 96 | bool preserve_security); |
96 | int ocfs2_init_security_and_acl(struct inode *dir, | 97 | int ocfs2_init_security_and_acl(struct inode *dir, |
97 | struct inode *inode); | 98 | struct inode *inode, |
99 | const struct qstr *qstr); | ||
98 | #endif /* OCFS2_XATTR_H */ | 100 | #endif /* OCFS2_XATTR_H */ |
@@ -701,7 +701,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
701 | if (error) | 701 | if (error) |
702 | goto cleanup_all; | 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 | f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); | 707 | f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); |
707 | 708 | ||
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 8eb2522111c5..f50133c11c24 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
@@ -32,7 +32,6 @@ static struct inode *proc_sys_make_inode(struct super_block *sb, | |||
32 | ei->sysctl_entry = table; | 32 | ei->sysctl_entry = table; |
33 | 33 | ||
34 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 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 | inode->i_mode = table->mode; | 35 | inode->i_mode = table->mode; |
37 | if (!table->child) { | 36 | if (!table->child) { |
38 | inode->i_mode |= S_IFREG; | 37 | inode->i_mode |= S_IFREG; |
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 68fdf45cc6c9..82f45542dcfc 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c | |||
@@ -593,7 +593,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
593 | new_inode_init(inode, dir, mode); | 593 | new_inode_init(inode, dir, mode); |
594 | 594 | ||
595 | jbegin_count += reiserfs_cache_default_acl(dir); | 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 | if (retval < 0) { | 597 | if (retval < 0) { |
598 | drop_new_inode(inode); | 598 | drop_new_inode(inode); |
599 | return retval; | 599 | return retval; |
@@ -667,7 +667,7 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode, | |||
667 | new_inode_init(inode, dir, mode); | 667 | new_inode_init(inode, dir, mode); |
668 | 668 | ||
669 | jbegin_count += reiserfs_cache_default_acl(dir); | 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 | if (retval < 0) { | 671 | if (retval < 0) { |
672 | drop_new_inode(inode); | 672 | drop_new_inode(inode); |
673 | return retval; | 673 | return retval; |
@@ -747,7 +747,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
747 | new_inode_init(inode, dir, mode); | 747 | new_inode_init(inode, dir, mode); |
748 | 748 | ||
749 | jbegin_count += reiserfs_cache_default_acl(dir); | 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 | if (retval < 0) { | 751 | if (retval < 0) { |
752 | drop_new_inode(inode); | 752 | drop_new_inode(inode); |
753 | return retval; | 753 | return retval; |
@@ -1032,7 +1032,8 @@ static int reiserfs_symlink(struct inode *parent_dir, | |||
1032 | } | 1032 | } |
1033 | new_inode_init(inode, parent_dir, mode); | 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 | if (retval < 0) { | 1037 | if (retval < 0) { |
1037 | drop_new_inode(inode); | 1038 | drop_new_inode(inode); |
1038 | return retval; | 1039 | return retval; |
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c index 237c6928d3c6..ef66c18a9332 100644 --- a/fs/reiserfs/xattr_security.c +++ b/fs/reiserfs/xattr_security.c | |||
@@ -54,6 +54,7 @@ static size_t security_list(struct dentry *dentry, char *list, size_t list_len, | |||
54 | * of blocks needed for the transaction. If successful, reiserfs_security | 54 | * of blocks needed for the transaction. If successful, reiserfs_security |
55 | * must be released using reiserfs_security_free when the caller is done. */ | 55 | * must be released using reiserfs_security_free when the caller is done. */ |
56 | int reiserfs_security_init(struct inode *dir, struct inode *inode, | 56 | int reiserfs_security_init(struct inode *dir, struct inode *inode, |
57 | const struct qstr *qstr, | ||
57 | struct reiserfs_security_handle *sec) | 58 | struct reiserfs_security_handle *sec) |
58 | { | 59 | { |
59 | int blocks = 0; | 60 | int blocks = 0; |
@@ -65,7 +66,7 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode, | |||
65 | if (IS_PRIVATE(dir)) | 66 | if (IS_PRIVATE(dir)) |
66 | return 0; | 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 | &sec->value, &sec->length); | 70 | &sec->value, &sec->length); |
70 | if (error) { | 71 | if (error) { |
71 | if (error == -EOPNOTSUPP) | 72 | if (error == -EOPNOTSUPP) |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index bd5727852fd6..9ff7fc603d2f 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -102,7 +102,8 @@ xfs_mark_inode_dirty( | |||
102 | STATIC int | 102 | STATIC int |
103 | xfs_init_security( | 103 | xfs_init_security( |
104 | struct inode *inode, | 104 | struct inode *inode, |
105 | struct inode *dir) | 105 | struct inode *dir, |
106 | const struct qstr *qstr) | ||
106 | { | 107 | { |
107 | struct xfs_inode *ip = XFS_I(inode); | 108 | struct xfs_inode *ip = XFS_I(inode); |
108 | size_t length; | 109 | size_t length; |
@@ -110,7 +111,7 @@ xfs_init_security( | |||
110 | unsigned char *name; | 111 | unsigned char *name; |
111 | int error; | 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 | &value, &length); | 115 | &value, &length); |
115 | if (error) { | 116 | if (error) { |
116 | if (error == -EOPNOTSUPP) | 117 | if (error == -EOPNOTSUPP) |
@@ -194,7 +195,7 @@ xfs_vn_mknod( | |||
194 | 195 | ||
195 | inode = VFS_I(ip); | 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 | if (unlikely(error)) | 199 | if (unlikely(error)) |
199 | goto out_cleanup_inode; | 200 | goto out_cleanup_inode; |
200 | 201 | ||
@@ -367,7 +368,7 @@ xfs_vn_symlink( | |||
367 | 368 | ||
368 | inode = VFS_I(cip); | 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 | if (unlikely(error)) | 372 | if (unlikely(error)) |
372 | goto out_cleanup_inode; | 373 | goto out_cleanup_inode; |
373 | 374 | ||
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 65990ef612f5..6043c64c207a 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h | |||
@@ -884,7 +884,8 @@ extern int ext3fs_dirhash(const char *name, int len, struct | |||
884 | dx_hash_info *hinfo); | 884 | dx_hash_info *hinfo); |
885 | 885 | ||
886 | /* ialloc.c */ | 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 | extern void ext3_free_inode (handle_t *, struct inode *); | 889 | extern void ext3_free_inode (handle_t *, struct inode *); |
889 | extern struct inode * ext3_orphan_get (struct super_block *, unsigned long); | 890 | extern struct inode * ext3_orphan_get (struct super_block *, unsigned long); |
890 | extern unsigned long ext3_count_free_inodes (struct super_block *); | 891 | extern unsigned long ext3_count_free_inodes (struct super_block *); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index e38b50a4b9d2..af5bd7a629e5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -798,8 +798,7 @@ struct inode { | |||
798 | #endif | 798 | #endif |
799 | 799 | ||
800 | #ifdef CONFIG_IMA | 800 | #ifdef CONFIG_IMA |
801 | /* protected by i_lock */ | 801 | atomic_t i_readcount; /* struct files open RO */ |
802 | unsigned int i_readcount; /* struct files open RO */ | ||
803 | #endif | 802 | #endif |
804 | atomic_t i_writecount; | 803 | atomic_t i_writecount; |
805 | #ifdef CONFIG_SECURITY | 804 | #ifdef CONFIG_SECURITY |
@@ -2200,6 +2199,26 @@ static inline void allow_write_access(struct file *file) | |||
2200 | if (file) | 2199 | if (file) |
2201 | atomic_inc(&file->f_path.dentry->d_inode->i_writecount); | 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 | extern int do_pipe_flags(int *, int); | 2222 | extern int do_pipe_flags(int *, int); |
2204 | extern struct file *create_read_pipe(struct file *f, int flags); | 2223 | extern struct file *create_read_pipe(struct file *f, int flags); |
2205 | extern struct file *create_write_pipe(int flags); | 2224 | extern struct file *create_write_pipe(int flags); |
diff --git a/include/linux/ima.h b/include/linux/ima.h index 975837e7d6c0..09e6e62f9953 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h | |||
@@ -20,7 +20,6 @@ extern void ima_inode_free(struct inode *inode); | |||
20 | extern int ima_file_check(struct file *file, int mask); | 20 | extern int ima_file_check(struct file *file, int mask); |
21 | extern void ima_file_free(struct file *file); | 21 | extern void ima_file_free(struct file *file); |
22 | extern int ima_file_mmap(struct file *file, unsigned long prot); | 22 | extern int ima_file_mmap(struct file *file, unsigned long prot); |
23 | extern void ima_counts_get(struct file *file); | ||
24 | 23 | ||
25 | #else | 24 | #else |
26 | static inline int ima_bprm_check(struct linux_binprm *bprm) | 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) | |||
53 | return 0; | 52 | return 0; |
54 | } | 53 | } |
55 | 54 | ||
56 | static inline void ima_counts_get(struct file *file) | ||
57 | { | ||
58 | return; | ||
59 | } | ||
60 | |||
61 | #endif /* CONFIG_IMA_H */ | 55 | #endif /* CONFIG_IMA_H */ |
62 | #endif /* _LINUX_IMA_H */ | 56 | #endif /* _LINUX_IMA_H */ |
diff --git a/include/linux/key-type.h b/include/linux/key-type.h index 65833d4d5998..9efd081bb31e 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h | |||
@@ -41,6 +41,9 @@ struct key_type { | |||
41 | */ | 41 | */ |
42 | size_t def_datalen; | 42 | size_t def_datalen; |
43 | 43 | ||
44 | /* vet a description */ | ||
45 | int (*vet_description)(const char *description); | ||
46 | |||
44 | /* instantiate a key of this type | 47 | /* instantiate a key of this type |
45 | * - this method should call key_payload_reserve() to determine if the | 48 | * - this method should call key_payload_reserve() to determine if the |
46 | * user's quota will hold the payload | 49 | * user's quota will hold the payload |
@@ -102,11 +105,20 @@ extern int key_instantiate_and_link(struct key *key, | |||
102 | size_t datalen, | 105 | size_t datalen, |
103 | struct key *keyring, | 106 | struct key *keyring, |
104 | struct key *instkey); | 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 | unsigned timeout, | 109 | unsigned timeout, |
110 | unsigned error, | ||
107 | struct key *keyring, | 111 | struct key *keyring, |
108 | struct key *instkey); | 112 | struct key *instkey); |
109 | extern void complete_request_key(struct key_construction *cons, int error); | 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 | #endif /* CONFIG_KEYS */ | 123 | #endif /* CONFIG_KEYS */ |
112 | #endif /* _LINUX_KEY_TYPE_H */ | 124 | #endif /* _LINUX_KEY_TYPE_H */ |
diff --git a/include/linux/key.h b/include/linux/key.h index 3db0adce1fda..b2bb01719561 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -170,6 +170,7 @@ struct key { | |||
170 | struct list_head link; | 170 | struct list_head link; |
171 | unsigned long x[2]; | 171 | unsigned long x[2]; |
172 | void *p[2]; | 172 | void *p[2]; |
173 | int reject_error; | ||
173 | } type_data; | 174 | } type_data; |
174 | 175 | ||
175 | /* key data | 176 | /* key data |
@@ -275,6 +276,10 @@ static inline key_serial_t key_serial(struct key *key) | |||
275 | return key ? key->serial : 0; | 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 | #ifdef CONFIG_SYSCTL | 283 | #ifdef CONFIG_SYSCTL |
279 | extern ctl_table key_sysctls[]; | 284 | extern ctl_table key_sysctls[]; |
280 | #endif | 285 | #endif |
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h index bd383f1944fb..9b0b865ce622 100644 --- a/include/linux/keyctl.h +++ b/include/linux/keyctl.h | |||
@@ -53,5 +53,7 @@ | |||
53 | #define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */ | 53 | #define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */ |
54 | #define KEYCTL_GET_SECURITY 17 /* get key security label */ | 54 | #define KEYCTL_GET_SECURITY 17 /* get key security label */ |
55 | #define KEYCTL_SESSION_TO_PARENT 18 /* apply session keyring to parent process */ | 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 | #endif /* _LINUX_KEYCTL_H */ | 59 | #endif /* _LINUX_KEYCTL_H */ |
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h index 3b94c91f20a6..6deef5dc95fb 100644 --- a/include/linux/reiserfs_xattr.h +++ b/include/linux/reiserfs_xattr.h | |||
@@ -63,6 +63,7 @@ extern const struct xattr_handler reiserfs_xattr_trusted_handler; | |||
63 | extern const struct xattr_handler reiserfs_xattr_security_handler; | 63 | extern const struct xattr_handler reiserfs_xattr_security_handler; |
64 | #ifdef CONFIG_REISERFS_FS_SECURITY | 64 | #ifdef CONFIG_REISERFS_FS_SECURITY |
65 | int reiserfs_security_init(struct inode *dir, struct inode *inode, | 65 | int reiserfs_security_init(struct inode *dir, struct inode *inode, |
66 | const struct qstr *qstr, | ||
66 | struct reiserfs_security_handle *sec); | 67 | struct reiserfs_security_handle *sec); |
67 | int reiserfs_security_write(struct reiserfs_transaction_handle *th, | 68 | int reiserfs_security_write(struct reiserfs_transaction_handle *th, |
68 | struct inode *inode, | 69 | struct inode *inode, |
@@ -130,6 +131,7 @@ static inline void reiserfs_init_xattr_rwsem(struct inode *inode) | |||
130 | #ifndef CONFIG_REISERFS_FS_SECURITY | 131 | #ifndef CONFIG_REISERFS_FS_SECURITY |
131 | static inline int reiserfs_security_init(struct inode *dir, | 132 | static inline int reiserfs_security_init(struct inode *dir, |
132 | struct inode *inode, | 133 | struct inode *inode, |
134 | const struct qstr *qstr, | ||
133 | struct reiserfs_security_handle *sec) | 135 | struct reiserfs_security_handle *sec) |
134 | { | 136 | { |
135 | return 0; | 137 | return 0; |
diff --git a/include/linux/security.h b/include/linux/security.h index b2b7f9749f5e..84a202ac3de9 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/fsnotify.h> | 26 | #include <linux/fsnotify.h> |
27 | #include <linux/binfmts.h> | 27 | #include <linux/binfmts.h> |
28 | #include <linux/dcache.h> | ||
28 | #include <linux/signal.h> | 29 | #include <linux/signal.h> |
29 | #include <linux/resource.h> | 30 | #include <linux/resource.h> |
30 | #include <linux/sem.h> | 31 | #include <linux/sem.h> |
@@ -267,6 +268,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
267 | * @orig the original mount data copied from userspace. | 268 | * @orig the original mount data copied from userspace. |
268 | * @copy copied data which will be passed to the security module. | 269 | * @copy copied data which will be passed to the security module. |
269 | * Returns 0 if the copy was successful. | 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 | * @sb_umount: | 277 | * @sb_umount: |
271 | * Check permission before the @mnt file system is unmounted. | 278 | * Check permission before the @mnt file system is unmounted. |
272 | * @mnt contains the mounted file system. | 279 | * @mnt contains the mounted file system. |
@@ -315,6 +322,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
315 | * then it should return -EOPNOTSUPP to skip this processing. | 322 | * then it should return -EOPNOTSUPP to skip this processing. |
316 | * @inode contains the inode structure of the newly created inode. | 323 | * @inode contains the inode structure of the newly created inode. |
317 | * @dir contains the inode structure of the parent directory. | 324 | * @dir contains the inode structure of the parent directory. |
325 | * @qstr contains the last path component of the new object | ||
318 | * @name will be set to the allocated name suffix (e.g. selinux). | 326 | * @name will be set to the allocated name suffix (e.g. selinux). |
319 | * @value will be set to the allocated attribute value. | 327 | * @value will be set to the allocated attribute value. |
320 | * @len will be set to the length of the value. | 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) | |||
1257 | * @cap contains the capability <include/linux/capability.h>. | 1265 | * @cap contains the capability <include/linux/capability.h>. |
1258 | * @audit: Whether to write an audit message or not | 1266 | * @audit: Whether to write an audit message or not |
1259 | * Return 0 if the capability is granted for @tsk. | 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 | * @syslog: | 1268 | * @syslog: |
1267 | * Check permission before accessing the kernel message ring or changing | 1269 | * Check permission before accessing the kernel message ring or changing |
1268 | * logging to the console. | 1270 | * logging to the console. |
@@ -1383,7 +1385,6 @@ struct security_operations { | |||
1383 | const kernel_cap_t *permitted); | 1385 | const kernel_cap_t *permitted); |
1384 | int (*capable) (struct task_struct *tsk, const struct cred *cred, | 1386 | int (*capable) (struct task_struct *tsk, const struct cred *cred, |
1385 | int cap, int audit); | 1387 | int cap, int audit); |
1386 | int (*sysctl) (struct ctl_table *table, int op); | ||
1387 | int (*quotactl) (int cmds, int type, int id, struct super_block *sb); | 1388 | int (*quotactl) (int cmds, int type, int id, struct super_block *sb); |
1388 | int (*quota_on) (struct dentry *dentry); | 1389 | int (*quota_on) (struct dentry *dentry); |
1389 | int (*syslog) (int type); | 1390 | int (*syslog) (int type); |
@@ -1399,6 +1400,7 @@ struct security_operations { | |||
1399 | int (*sb_alloc_security) (struct super_block *sb); | 1400 | int (*sb_alloc_security) (struct super_block *sb); |
1400 | void (*sb_free_security) (struct super_block *sb); | 1401 | void (*sb_free_security) (struct super_block *sb); |
1401 | int (*sb_copy_data) (char *orig, char *copy); | 1402 | int (*sb_copy_data) (char *orig, char *copy); |
1403 | int (*sb_remount) (struct super_block *sb, void *data); | ||
1402 | int (*sb_kern_mount) (struct super_block *sb, int flags, void *data); | 1404 | int (*sb_kern_mount) (struct super_block *sb, int flags, void *data); |
1403 | int (*sb_show_options) (struct seq_file *m, struct super_block *sb); | 1405 | int (*sb_show_options) (struct seq_file *m, struct super_block *sb); |
1404 | int (*sb_statfs) (struct dentry *dentry); | 1406 | int (*sb_statfs) (struct dentry *dentry); |
@@ -1435,7 +1437,8 @@ struct security_operations { | |||
1435 | int (*inode_alloc_security) (struct inode *inode); | 1437 | int (*inode_alloc_security) (struct inode *inode); |
1436 | void (*inode_free_security) (struct inode *inode); | 1438 | void (*inode_free_security) (struct inode *inode); |
1437 | int (*inode_init_security) (struct inode *inode, struct inode *dir, | 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 | int (*inode_create) (struct inode *dir, | 1442 | int (*inode_create) (struct inode *dir, |
1440 | struct dentry *dentry, int mode); | 1443 | struct dentry *dentry, int mode); |
1441 | int (*inode_link) (struct dentry *old_dentry, | 1444 | int (*inode_link) (struct dentry *old_dentry, |
@@ -1665,7 +1668,6 @@ int security_capset(struct cred *new, const struct cred *old, | |||
1665 | int security_capable(const struct cred *cred, int cap); | 1668 | int security_capable(const struct cred *cred, int cap); |
1666 | int security_real_capable(struct task_struct *tsk, int cap); | 1669 | int security_real_capable(struct task_struct *tsk, int cap); |
1667 | int security_real_capable_noaudit(struct task_struct *tsk, int cap); | 1670 | int security_real_capable_noaudit(struct task_struct *tsk, int cap); |
1668 | int security_sysctl(struct ctl_table *table, int op); | ||
1669 | int security_quotactl(int cmds, int type, int id, struct super_block *sb); | 1671 | int security_quotactl(int cmds, int type, int id, struct super_block *sb); |
1670 | int security_quota_on(struct dentry *dentry); | 1672 | int security_quota_on(struct dentry *dentry); |
1671 | int security_syslog(int type); | 1673 | int security_syslog(int type); |
@@ -1681,6 +1683,7 @@ int security_bprm_secureexec(struct linux_binprm *bprm); | |||
1681 | int security_sb_alloc(struct super_block *sb); | 1683 | int security_sb_alloc(struct super_block *sb); |
1682 | void security_sb_free(struct super_block *sb); | 1684 | void security_sb_free(struct super_block *sb); |
1683 | int security_sb_copy_data(char *orig, char *copy); | 1685 | int security_sb_copy_data(char *orig, char *copy); |
1686 | int security_sb_remount(struct super_block *sb, void *data); | ||
1684 | int security_sb_kern_mount(struct super_block *sb, int flags, void *data); | 1687 | int security_sb_kern_mount(struct super_block *sb, int flags, void *data); |
1685 | int security_sb_show_options(struct seq_file *m, struct super_block *sb); | 1688 | int security_sb_show_options(struct seq_file *m, struct super_block *sb); |
1686 | int security_sb_statfs(struct dentry *dentry); | 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); | |||
1696 | int security_inode_alloc(struct inode *inode); | 1699 | int security_inode_alloc(struct inode *inode); |
1697 | void security_inode_free(struct inode *inode); | 1700 | void security_inode_free(struct inode *inode); |
1698 | int security_inode_init_security(struct inode *inode, struct inode *dir, | 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 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode); | 1704 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode); |
1701 | int security_inode_link(struct dentry *old_dentry, struct inode *dir, | 1705 | int security_inode_link(struct dentry *old_dentry, struct inode *dir, |
1702 | struct dentry *new_dentry); | 1706 | struct dentry *new_dentry); |
@@ -1883,11 +1887,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap) | |||
1883 | return ret; | 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 | static inline int security_quotactl(int cmds, int type, int id, | 1890 | static inline int security_quotactl(int cmds, int type, int id, |
1892 | struct super_block *sb) | 1891 | struct super_block *sb) |
1893 | { | 1892 | { |
@@ -1964,6 +1963,11 @@ static inline int security_sb_copy_data(char *orig, char *copy) | |||
1964 | return 0; | 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 | static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data) | 1971 | static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data) |
1968 | { | 1972 | { |
1969 | return 0; | 1973 | return 0; |
@@ -2023,6 +2027,7 @@ static inline void security_inode_free(struct inode *inode) | |||
2023 | 2027 | ||
2024 | static inline int security_inode_init_security(struct inode *inode, | 2028 | static inline int security_inode_init_security(struct inode *inode, |
2025 | struct inode *dir, | 2029 | struct inode *dir, |
2030 | const struct qstr *qstr, | ||
2026 | char **name, | 2031 | char **name, |
2027 | void **value, | 2032 | void **value, |
2028 | size_t *len) | 2033 | size_t *len) |
diff --git a/include/linux/xattr.h b/include/linux/xattr.h index e6131ef98d8f..6050783005bd 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h | |||
@@ -42,11 +42,13 @@ | |||
42 | #define XATTR_SMACK_IPOUT "SMACK64IPOUT" | 42 | #define XATTR_SMACK_IPOUT "SMACK64IPOUT" |
43 | #define XATTR_SMACK_EXEC "SMACK64EXEC" | 43 | #define XATTR_SMACK_EXEC "SMACK64EXEC" |
44 | #define XATTR_SMACK_TRANSMUTE "SMACK64TRANSMUTE" | 44 | #define XATTR_SMACK_TRANSMUTE "SMACK64TRANSMUTE" |
45 | #define XATTR_SMACK_MMAP "SMACK64MMAP" | ||
45 | #define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX | 46 | #define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX |
46 | #define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN | 47 | #define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN |
47 | #define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT | 48 | #define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT |
48 | #define XATTR_NAME_SMACKEXEC XATTR_SECURITY_PREFIX XATTR_SMACK_EXEC | 49 | #define XATTR_NAME_SMACKEXEC XATTR_SECURITY_PREFIX XATTR_SMACK_EXEC |
49 | #define XATTR_NAME_SMACKTRANSMUTE XATTR_SECURITY_PREFIX XATTR_SMACK_TRANSMUTE | 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 | #define XATTR_CAPS_SUFFIX "capability" | 53 | #define XATTR_CAPS_SUFFIX "capability" |
52 | #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX | 54 | #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4eed0af5d144..4cb152574433 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -1690,13 +1690,8 @@ static int test_perm(int mode, int op) | |||
1690 | 1690 | ||
1691 | int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op) | 1691 | int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op) |
1692 | { | 1692 | { |
1693 | int error; | ||
1694 | int mode; | 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 | if (root->permissions) | 1695 | if (root->permissions) |
1701 | mode = root->permissions(root, current->nsproxy, table); | 1696 | mode = root->permissions(root, current->nsproxy, table); |
1702 | else | 1697 | else |
diff --git a/mm/shmem.c b/mm/shmem.c index 5ee67c990602..7c9cdc6fe137 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1843,8 +1843,9 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | |||
1843 | 1843 | ||
1844 | inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE); | 1844 | inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE); |
1845 | if (inode) { | 1845 | if (inode) { |
1846 | error = security_inode_init_security(inode, dir, NULL, NULL, | 1846 | error = security_inode_init_security(inode, dir, |
1847 | NULL); | 1847 | &dentry->d_name, NULL, |
1848 | NULL, NULL); | ||
1848 | if (error) { | 1849 | if (error) { |
1849 | if (error != -EOPNOTSUPP) { | 1850 | if (error != -EOPNOTSUPP) { |
1850 | iput(inode); | 1851 | iput(inode); |
@@ -1983,8 +1984,8 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s | |||
1983 | if (!inode) | 1984 | if (!inode) |
1984 | return -ENOSPC; | 1985 | return -ENOSPC; |
1985 | 1986 | ||
1986 | error = security_inode_init_security(inode, dir, NULL, NULL, | 1987 | error = security_inode_init_security(inode, dir, &dentry->d_name, NULL, |
1987 | NULL); | 1988 | NULL, NULL); |
1988 | if (error) { | 1989 | if (error) { |
1989 | if (error != -EOPNOTSUPP) { | 1990 | if (error != -EOPNOTSUPP) { |
1990 | iput(inode); | 1991 | iput(inode); |
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index d763793d39de..43ea7de2fc8e 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <keys/user-type.h> | 25 | #include <keys/user-type.h> |
26 | #include "ar-internal.h" | 26 | #include "ar-internal.h" |
27 | 27 | ||
28 | static int rxrpc_vet_description_s(const char *); | ||
28 | static int rxrpc_instantiate(struct key *, const void *, size_t); | 29 | static int rxrpc_instantiate(struct key *, const void *, size_t); |
29 | static int rxrpc_instantiate_s(struct key *, const void *, size_t); | 30 | static int rxrpc_instantiate_s(struct key *, const void *, size_t); |
30 | static void rxrpc_destroy(struct key *); | 31 | static void rxrpc_destroy(struct key *); |
@@ -52,6 +53,7 @@ EXPORT_SYMBOL(key_type_rxrpc); | |||
52 | */ | 53 | */ |
53 | struct key_type key_type_rxrpc_s = { | 54 | struct key_type key_type_rxrpc_s = { |
54 | .name = "rxrpc_s", | 55 | .name = "rxrpc_s", |
56 | .vet_description = rxrpc_vet_description_s, | ||
55 | .instantiate = rxrpc_instantiate_s, | 57 | .instantiate = rxrpc_instantiate_s, |
56 | .match = user_match, | 58 | .match = user_match, |
57 | .destroy = rxrpc_destroy_s, | 59 | .destroy = rxrpc_destroy_s, |
@@ -59,6 +61,23 @@ struct key_type key_type_rxrpc_s = { | |||
59 | }; | 61 | }; |
60 | 62 | ||
61 | /* | 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 | |||
80 | /* | ||
62 | * parse an RxKAD type XDR format token | 81 | * parse an RxKAD type XDR format token |
63 | * - the caller guarantees we have at least 4 words | 82 | * - the caller guarantees we have at least 4 words |
64 | */ | 83 | */ |
diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c index 58a12c278706..539855ff31f9 100644 --- a/scripts/selinux/genheaders/genheaders.c +++ b/scripts/selinux/genheaders/genheaders.c | |||
@@ -43,6 +43,8 @@ int main(int argc, char *argv[]) | |||
43 | int i, j, k; | 43 | int i, j, k; |
44 | int isids_len; | 44 | int isids_len; |
45 | FILE *fout; | 45 | FILE *fout; |
46 | const char *needle = "SOCKET"; | ||
47 | char *substr; | ||
46 | 48 | ||
47 | progname = argv[0]; | 49 | progname = argv[0]; |
48 | 50 | ||
@@ -88,6 +90,24 @@ int main(int argc, char *argv[]) | |||
88 | fprintf(fout, "%2d\n", i); | 90 | fprintf(fout, "%2d\n", i); |
89 | } | 91 | } |
90 | fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1); | 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 | fprintf(fout, "\n#endif\n"); | 111 | fprintf(fout, "\n#endif\n"); |
92 | fclose(fout); | 112 | fclose(fout); |
93 | 113 | ||
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile index f204869399ea..2dafe50a2e25 100644 --- a/security/apparmor/Makefile +++ b/security/apparmor/Makefile | |||
@@ -6,19 +6,47 @@ apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ | |||
6 | path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ | 6 | path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ |
7 | resource.o sid.o file.o | 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 | quiet_cmd_make-caps = GEN $@ | 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 | quiet_cmd_make-rlim = GEN $@ | 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 | $(obj)/capability.o : $(obj)/capability_names.h | 47 | $(obj)/capability.o : $(obj)/capability_names.h |
18 | $(obj)/resource.o : $(obj)/rlim_names.h | 48 | $(obj)/resource.o : $(obj)/rlim_names.h |
19 | $(obj)/capability_names.h : $(srctree)/include/linux/capability.h | 49 | $(obj)/capability_names.h : $(srctree)/include/linux/capability.h |
20 | $(call cmd,make-caps) | 50 | $(call cmd,make-caps) |
21 | $(obj)/af_names.h : $(srctree)/include/linux/socket.h | ||
22 | $(call cmd,make-af) | ||
23 | $(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h | 51 | $(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h |
24 | $(call cmd,make-rlim) | 52 | $(call cmd,make-rlim) |
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index b7106f192b75..d21a427a35ae 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
@@ -693,11 +693,9 @@ static struct kernel_param_ops param_ops_aalockpolicy = { | |||
693 | 693 | ||
694 | static int param_set_audit(const char *val, struct kernel_param *kp); | 694 | static int param_set_audit(const char *val, struct kernel_param *kp); |
695 | static int param_get_audit(char *buffer, struct kernel_param *kp); | 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 | static int param_set_mode(const char *val, struct kernel_param *kp); | 697 | static int param_set_mode(const char *val, struct kernel_param *kp); |
699 | static int param_get_mode(char *buffer, struct kernel_param *kp); | 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 | /* Flag values, also controllable via /sys/module/apparmor/parameters | 700 | /* Flag values, also controllable via /sys/module/apparmor/parameters |
703 | * We define special types as we want to do additional mediation. | 701 | * We define special types as we want to do additional mediation. |
diff --git a/security/capability.c b/security/capability.c index 2a5df2b7da83..ab3d807accc3 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -12,11 +12,6 @@ | |||
12 | 12 | ||
13 | #include <linux/security.h> | 13 | #include <linux/security.h> |
14 | 14 | ||
15 | static int cap_sysctl(ctl_table *table, int op) | ||
16 | { | ||
17 | return 0; | ||
18 | } | ||
19 | |||
20 | static int cap_syslog(int type) | 15 | static int cap_syslog(int type) |
21 | { | 16 | { |
22 | return 0; | 17 | return 0; |
@@ -59,6 +54,11 @@ static int cap_sb_copy_data(char *orig, char *copy) | |||
59 | return 0; | 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 | static int cap_sb_kern_mount(struct super_block *sb, int flags, void *data) | 62 | static int cap_sb_kern_mount(struct super_block *sb, int flags, void *data) |
63 | { | 63 | { |
64 | return 0; | 64 | return 0; |
@@ -118,7 +118,8 @@ static void cap_inode_free_security(struct inode *inode) | |||
118 | } | 118 | } |
119 | 119 | ||
120 | static int cap_inode_init_security(struct inode *inode, struct inode *dir, | 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 | return -EOPNOTSUPP; | 124 | return -EOPNOTSUPP; |
124 | } | 125 | } |
@@ -880,7 +881,6 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
880 | set_to_cap_if_null(ops, capable); | 881 | set_to_cap_if_null(ops, capable); |
881 | set_to_cap_if_null(ops, quotactl); | 882 | set_to_cap_if_null(ops, quotactl); |
882 | set_to_cap_if_null(ops, quota_on); | 883 | set_to_cap_if_null(ops, quota_on); |
883 | set_to_cap_if_null(ops, sysctl); | ||
884 | set_to_cap_if_null(ops, syslog); | 884 | set_to_cap_if_null(ops, syslog); |
885 | set_to_cap_if_null(ops, settime); | 885 | set_to_cap_if_null(ops, settime); |
886 | set_to_cap_if_null(ops, vm_enough_memory); | 886 | set_to_cap_if_null(ops, vm_enough_memory); |
@@ -892,6 +892,7 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
892 | set_to_cap_if_null(ops, sb_alloc_security); | 892 | set_to_cap_if_null(ops, sb_alloc_security); |
893 | set_to_cap_if_null(ops, sb_free_security); | 893 | set_to_cap_if_null(ops, sb_free_security); |
894 | set_to_cap_if_null(ops, sb_copy_data); | 894 | set_to_cap_if_null(ops, sb_copy_data); |
895 | set_to_cap_if_null(ops, sb_remount); | ||
895 | set_to_cap_if_null(ops, sb_kern_mount); | 896 | set_to_cap_if_null(ops, sb_kern_mount); |
896 | set_to_cap_if_null(ops, sb_show_options); | 897 | set_to_cap_if_null(ops, sb_show_options); |
897 | set_to_cap_if_null(ops, sb_statfs); | 898 | set_to_cap_if_null(ops, sb_statfs); |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index ac79032bdf23..08408bd71462 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -110,8 +110,7 @@ struct ima_iint_cache { | |||
110 | }; | 110 | }; |
111 | 111 | ||
112 | /* LIM API function definitions */ | 112 | /* LIM API function definitions */ |
113 | int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode, | 113 | int ima_must_measure(struct inode *inode, int mask, int function); |
114 | int mask, int function); | ||
115 | int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file); | 114 | int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file); |
116 | void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, | 115 | void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, |
117 | const unsigned char *filename); | 116 | const unsigned char *filename); |
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index d3963de6003d..da36d2c085a4 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
@@ -105,20 +105,13 @@ err_out: | |||
105 | * mask: contains the permission mask | 105 | * mask: contains the permission mask |
106 | * fsmagic: hex value | 106 | * fsmagic: hex value |
107 | * | 107 | * |
108 | * Must be called with iint->mutex held. | 108 | * Return 0 to measure. For matching a DONT_MEASURE policy, no policy, |
109 | * | 109 | * or other error, return an error code. |
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. | ||
113 | */ | 110 | */ |
114 | int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode, | 111 | int ima_must_measure(struct inode *inode, int mask, int function) |
115 | int mask, int function) | ||
116 | { | 112 | { |
117 | int must_measure; | 113 | int must_measure; |
118 | 114 | ||
119 | if (iint && iint->flags & IMA_MEASURED) | ||
120 | return 1; | ||
121 | |||
122 | must_measure = ima_match_policy(inode, function, mask); | 115 | must_measure = ima_match_policy(inode, function, mask); |
123 | return must_measure ? 0 : -EACCES; | 116 | return must_measure ? 0 : -EACCES; |
124 | } | 117 | } |
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index c442e47b6785..4ae73040ab7b 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c | |||
@@ -137,11 +137,6 @@ void ima_inode_free(struct inode *inode) | |||
137 | { | 137 | { |
138 | struct ima_iint_cache *iint; | 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 | if (!IS_IMA(inode)) | 140 | if (!IS_IMA(inode)) |
146 | return; | 141 | return; |
147 | 142 | ||
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 203de979d305..39d66dc2b8e9 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -36,67 +36,17 @@ static int __init hash_setup(char *str) | |||
36 | } | 36 | } |
37 | __setup("ima_hash=", hash_setup); | 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 | 42 | * Only invalidate the PCR for measured files: |
92 | * invalidate the PCR for measured files: | ||
93 | * - Opening a file for write when already open for read, | 43 | * - Opening a file for write when already open for read, |
94 | * results in a time of measure, time of use (ToMToU) error. | 44 | * results in a time of measure, time of use (ToMToU) error. |
95 | * - Opening a file for read when already open for write, | 45 | * - Opening a file for read when already open for write, |
96 | * could result in a file measurement error. | 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 | struct dentry *dentry = file->f_path.dentry; | 51 | struct dentry *dentry = file->f_path.dentry; |
102 | struct inode *inode = dentry->d_inode; | 52 | struct inode *inode = dentry->d_inode; |
@@ -104,32 +54,25 @@ void ima_counts_get(struct file *file) | |||
104 | int rc; | 54 | int rc; |
105 | bool send_tomtou = false, send_writers = false; | 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 | return; | 58 | return; |
109 | 59 | ||
110 | spin_lock(&inode->i_lock); | 60 | mutex_lock(&inode->i_mutex); /* file metadata: permissions, xattr */ |
111 | |||
112 | if (!ima_initialized) | ||
113 | goto out; | ||
114 | 61 | ||
115 | if (mode & FMODE_WRITE) { | 62 | if (mode & FMODE_WRITE) { |
116 | if (inode->i_readcount && IS_IMA(inode)) | 63 | if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) |
117 | send_tomtou = true; | 64 | send_tomtou = true; |
118 | goto out; | 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 | if (rc < 0) | 69 | if (rc < 0) |
123 | goto out; | 70 | goto out; |
124 | 71 | ||
125 | if (atomic_read(&inode->i_writecount) > 0) | 72 | if (atomic_read(&inode->i_writecount) > 0) |
126 | send_writers = true; | 73 | send_writers = true; |
127 | out: | 74 | out: |
128 | /* remember the vfs deals with i_writecount */ | 75 | mutex_unlock(&inode->i_mutex); |
129 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | ||
130 | inode->i_readcount++; | ||
131 | |||
132 | spin_unlock(&inode->i_lock); | ||
133 | 76 | ||
134 | if (send_tomtou) | 77 | if (send_tomtou) |
135 | ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", | 78 | ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", |
@@ -139,71 +82,25 @@ out: | |||
139 | "open_writers"); | 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 | static void ima_check_last_writer(struct ima_iint_cache *iint, | 85 | static void ima_check_last_writer(struct ima_iint_cache *iint, |
165 | struct inode *inode, | 86 | struct inode *inode, |
166 | struct file *file) | 87 | struct file *file) |
167 | { | 88 | { |
168 | mode_t mode = file->f_mode; | 89 | mode_t mode = file->f_mode; |
169 | 90 | ||
170 | BUG_ON(!mutex_is_locked(&iint->mutex)); | 91 | mutex_lock(&iint->mutex); |
171 | assert_spin_locked(&inode->i_lock); | ||
172 | |||
173 | if (mode & FMODE_WRITE && | 92 | if (mode & FMODE_WRITE && |
174 | atomic_read(&inode->i_writecount) == 1 && | 93 | atomic_read(&inode->i_writecount) == 1 && |
175 | iint->version != inode->i_version) | 94 | iint->version != inode->i_version) |
176 | iint->flags &= ~IMA_MEASURED; | 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 | mutex_unlock(&iint->mutex); | 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 | * ima_file_free - called on __fput() | 100 | * ima_file_free - called on __fput() |
203 | * @file: pointer to file structure being freed | 101 | * @file: pointer to file structure being freed |
204 | * | 102 | * |
205 | * Flag files that changed, based on i_version; | 103 | * Flag files that changed, based on i_version |
206 | * and decrement the i_readcount. | ||
207 | */ | 104 | */ |
208 | void ima_file_free(struct file *file) | 105 | void ima_file_free(struct file *file) |
209 | { | 106 | { |
@@ -214,12 +111,10 @@ void ima_file_free(struct file *file) | |||
214 | return; | 111 | return; |
215 | 112 | ||
216 | iint = ima_iint_find(inode); | 113 | iint = ima_iint_find(inode); |
114 | if (!iint) | ||
115 | return; | ||
217 | 116 | ||
218 | if (iint) | 117 | ima_check_last_writer(iint, inode, file); |
219 | ima_file_free_iint(iint, inode, file); | ||
220 | else | ||
221 | ima_file_free_noiint(inode, file); | ||
222 | |||
223 | } | 118 | } |
224 | 119 | ||
225 | static int process_measurement(struct file *file, const unsigned char *filename, | 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, | |||
232 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 127 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
233 | return 0; | 128 | return 0; |
234 | 129 | ||
235 | rc = ima_must_measure(NULL, inode, mask, function); | 130 | rc = ima_must_measure(inode, mask, function); |
236 | if (rc != 0) | 131 | if (rc != 0) |
237 | return rc; | 132 | return rc; |
238 | retry: | 133 | retry: |
@@ -246,7 +141,7 @@ retry: | |||
246 | 141 | ||
247 | mutex_lock(&iint->mutex); | 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 | if (rc != 0) | 145 | if (rc != 0) |
251 | goto out; | 146 | goto out; |
252 | 147 | ||
@@ -317,6 +212,7 @@ int ima_file_check(struct file *file, int mask) | |||
317 | { | 212 | { |
318 | int rc; | 213 | int rc; |
319 | 214 | ||
215 | ima_rdwr_violation_check(file); | ||
320 | rc = process_measurement(file, file->f_dentry->d_name.name, | 216 | rc = process_measurement(file, file->f_dentry->d_name.name, |
321 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), | 217 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), |
322 | FILE_CHECK); | 218 | FILE_CHECK); |
diff --git a/security/keys/compat.c b/security/keys/compat.c index 07a5f35e3970..338b510e9027 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c | |||
@@ -12,9 +12,52 @@ | |||
12 | #include <linux/syscalls.h> | 12 | #include <linux/syscalls.h> |
13 | #include <linux/keyctl.h> | 13 | #include <linux/keyctl.h> |
14 | #include <linux/compat.h> | 14 | #include <linux/compat.h> |
15 | #include <linux/slab.h> | ||
15 | #include "internal.h" | 16 | #include "internal.h" |
16 | 17 | ||
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 | |||
60 | /* | ||
18 | * The key control system call, 32-bit compatibility version for 64-bit archs | 61 | * The key control system call, 32-bit compatibility version for 64-bit archs |
19 | * | 62 | * |
20 | * This should only be called if the 64-bit arch uses weird pointers in 32-bit | 63 | * This should only be called if the 64-bit arch uses weird pointers in 32-bit |
@@ -85,6 +128,13 @@ asmlinkage long compat_sys_keyctl(u32 option, | |||
85 | case KEYCTL_SESSION_TO_PARENT: | 128 | case KEYCTL_SESSION_TO_PARENT: |
86 | return keyctl_session_to_parent(); | 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 | default: | 138 | default: |
89 | return -EOPNOTSUPP; | 139 | return -EOPNOTSUPP; |
90 | } | 140 | } |
diff --git a/security/keys/encrypted.c b/security/keys/encrypted.c index 9e7e4ce3fae8..69907a58a683 100644 --- a/security/keys/encrypted.c +++ b/security/keys/encrypted.c | |||
@@ -765,8 +765,7 @@ static long encrypted_read(const struct key *key, char __user *buffer, | |||
765 | size_t asciiblob_len; | 765 | size_t asciiblob_len; |
766 | int ret; | 766 | int ret; |
767 | 767 | ||
768 | epayload = rcu_dereference_protected(key->payload.data, | 768 | epayload = rcu_dereference_key(key); |
769 | rwsem_is_locked(&((struct key *)key)->sem)); | ||
770 | 769 | ||
771 | /* returns the hex encoded iv, encrypted-data, and hmac as ascii */ | 770 | /* returns the hex encoded iv, encrypted-data, and hmac as ascii */ |
772 | asciiblob_len = epayload->datablob_len + ivsize + 1 | 771 | asciiblob_len = epayload->datablob_len + ivsize + 1 |
diff --git a/security/keys/internal.h b/security/keys/internal.h index a52aa7c88b41..07a025f81902 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -214,6 +214,14 @@ extern long keyctl_assume_authority(key_serial_t); | |||
214 | extern long keyctl_get_security(key_serial_t keyid, char __user *buffer, | 214 | extern long keyctl_get_security(key_serial_t keyid, char __user *buffer, |
215 | size_t buflen); | 215 | size_t buflen); |
216 | extern long keyctl_session_to_parent(void); | 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 | * Debugging key validation | 227 | * Debugging key validation |
diff --git a/security/keys/key.c b/security/keys/key.c index 1c2d43dc5107..f7f9d93f08d9 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -249,6 +249,14 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
249 | if (!desc || !*desc) | 249 | if (!desc || !*desc) |
250 | goto error; | 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 | desclen = strlen(desc) + 1; | 260 | desclen = strlen(desc) + 1; |
253 | quotalen = desclen + type->def_datalen; | 261 | quotalen = desclen + type->def_datalen; |
254 | 262 | ||
@@ -503,26 +511,29 @@ int key_instantiate_and_link(struct key *key, | |||
503 | EXPORT_SYMBOL(key_instantiate_and_link); | 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 | * @key: The key to instantiate. | 515 | * @key: The key to instantiate. |
508 | * @timeout: The timeout on the negative key. | 516 | * @timeout: The timeout on the negative key. |
517 | * @error: The error to return when the key is hit. | ||
509 | * @keyring: Keyring to create a link in on success (or NULL). | 518 | * @keyring: Keyring to create a link in on success (or NULL). |
510 | * @authkey: The authorisation token permitting instantiation. | 519 | * @authkey: The authorisation token permitting instantiation. |
511 | * | 520 | * |
512 | * Negatively instantiate a key that's in the uninstantiated state and, if | 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 | 522 | * successful, set its timeout and stored error and link it in to the |
514 | * is supplied. The key and any links to the key will be automatically garbage | 523 | * destination keyring if one is supplied. The key and any links to the key |
515 | * collected after the timeout expires. | 524 | * will be automatically garbage collected after the timeout expires. |
516 | * | 525 | * |
517 | * Negative keys are used to rate limit repeated request_key() calls by causing | 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 | * If successful, 0 is returned, the authorisation token is revoked and anyone | 530 | * If successful, 0 is returned, the authorisation token is revoked and anyone |
521 | * waiting for the key is woken up. If the key was already instantiated, | 531 | * waiting for the key is woken up. If the key was already instantiated, |
522 | * -EBUSY will be returned. | 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 | unsigned timeout, | 535 | unsigned timeout, |
536 | unsigned error, | ||
526 | struct key *keyring, | 537 | struct key *keyring, |
527 | struct key *authkey) | 538 | struct key *authkey) |
528 | { | 539 | { |
@@ -548,6 +559,7 @@ int key_negate_and_link(struct key *key, | |||
548 | atomic_inc(&key->user->nikeys); | 559 | atomic_inc(&key->user->nikeys); |
549 | set_bit(KEY_FLAG_NEGATIVE, &key->flags); | 560 | set_bit(KEY_FLAG_NEGATIVE, &key->flags); |
550 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); | 561 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); |
562 | key->type_data.reject_error = -error; | ||
551 | now = current_kernel_time(); | 563 | now = current_kernel_time(); |
552 | key->expiry = now.tv_sec + timeout; | 564 | key->expiry = now.tv_sec + timeout; |
553 | key_schedule_gc(key->expiry + key_gc_delay); | 565 | key_schedule_gc(key->expiry + key_gc_delay); |
@@ -577,8 +589,7 @@ int key_negate_and_link(struct key *key, | |||
577 | 589 | ||
578 | return ret == 0 ? link_ret : ret; | 590 | return ret == 0 ? link_ret : ret; |
579 | } | 591 | } |
580 | 592 | EXPORT_SYMBOL(key_reject_and_link); | |
581 | EXPORT_SYMBOL(key_negate_and_link); | ||
582 | 593 | ||
583 | /* | 594 | /* |
584 | * Garbage collect keys in process context so that we don't have to disable | 595 | * Garbage collect keys in process context so that we don't have to disable |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 31a0fd8189f1..427fddcaeb19 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -913,6 +913,21 @@ static int keyctl_change_reqkey_auth(struct key *key) | |||
913 | } | 913 | } |
914 | 914 | ||
915 | /* | 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 | |||
930 | /* | ||
916 | * Instantiate a key with the specified payload and link the key into the | 931 | * Instantiate a key with the specified payload and link the key into the |
917 | * destination keyring if one is given. | 932 | * destination keyring if one is given. |
918 | * | 933 | * |
@@ -921,10 +936,11 @@ static int keyctl_change_reqkey_auth(struct key *key) | |||
921 | * | 936 | * |
922 | * If successful, 0 will be returned. | 937 | * If successful, 0 will be returned. |
923 | */ | 938 | */ |
924 | long keyctl_instantiate_key(key_serial_t id, | 939 | long keyctl_instantiate_key_common(key_serial_t id, |
925 | const void __user *_payload, | 940 | const struct iovec *payload_iov, |
926 | size_t plen, | 941 | unsigned ioc, |
927 | key_serial_t ringid) | 942 | size_t plen, |
943 | key_serial_t ringid) | ||
928 | { | 944 | { |
929 | const struct cred *cred = current_cred(); | 945 | const struct cred *cred = current_cred(); |
930 | struct request_key_auth *rka; | 946 | struct request_key_auth *rka; |
@@ -953,7 +969,7 @@ long keyctl_instantiate_key(key_serial_t id, | |||
953 | /* pull the payload in if one was supplied */ | 969 | /* pull the payload in if one was supplied */ |
954 | payload = NULL; | 970 | payload = NULL; |
955 | 971 | ||
956 | if (_payload) { | 972 | if (payload_iov) { |
957 | ret = -ENOMEM; | 973 | ret = -ENOMEM; |
958 | payload = kmalloc(plen, GFP_KERNEL); | 974 | payload = kmalloc(plen, GFP_KERNEL); |
959 | if (!payload) { | 975 | if (!payload) { |
@@ -965,8 +981,8 @@ long keyctl_instantiate_key(key_serial_t id, | |||
965 | goto error; | 981 | goto error; |
966 | } | 982 | } |
967 | 983 | ||
968 | ret = -EFAULT; | 984 | ret = copy_from_user_iovec(payload, payload_iov, ioc); |
969 | if (copy_from_user(payload, _payload, plen) != 0) | 985 | if (ret < 0) |
970 | goto error2; | 986 | goto error2; |
971 | } | 987 | } |
972 | 988 | ||
@@ -997,6 +1013,72 @@ error: | |||
997 | } | 1013 | } |
998 | 1014 | ||
999 | /* | 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 | |||
1081 | /* | ||
1000 | * Negatively instantiate the key with the given timeout (in seconds) and link | 1082 | * Negatively instantiate the key with the given timeout (in seconds) and link |
1001 | * the key into the destination keyring if one is given. | 1083 | * the key into the destination keyring if one is given. |
1002 | * | 1084 | * |
@@ -1013,12 +1095,42 @@ error: | |||
1013 | */ | 1095 | */ |
1014 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | 1096 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) |
1015 | { | 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) | ||
1118 | { | ||
1016 | const struct cred *cred = current_cred(); | 1119 | const struct cred *cred = current_cred(); |
1017 | struct request_key_auth *rka; | 1120 | struct request_key_auth *rka; |
1018 | struct key *instkey, *dest_keyring; | 1121 | struct key *instkey, *dest_keyring; |
1019 | long ret; | 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 | /* the appropriate instantiation authorisation key must have been | 1135 | /* the appropriate instantiation authorisation key must have been |
1024 | * assumed before calling this */ | 1136 | * assumed before calling this */ |
@@ -1038,7 +1150,7 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
1038 | goto error; | 1150 | goto error; |
1039 | 1151 | ||
1040 | /* instantiate the key and link it into a keyring */ | 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 | dest_keyring, instkey); | 1154 | dest_keyring, instkey); |
1043 | 1155 | ||
1044 | key_put(dest_keyring); | 1156 | key_put(dest_keyring); |
@@ -1492,6 +1604,19 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
1492 | case KEYCTL_SESSION_TO_PARENT: | 1604 | case KEYCTL_SESSION_TO_PARENT: |
1493 | return keyctl_session_to_parent(); | 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 | default: | 1620 | default: |
1496 | return -EOPNOTSUPP; | 1621 | return -EOPNOTSUPP; |
1497 | } | 1622 | } |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 5620f084dede..cdd2f3f88c88 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -352,7 +352,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
352 | goto error_2; | 352 | goto error_2; |
353 | if (key->expiry && now.tv_sec >= key->expiry) | 353 | if (key->expiry && now.tv_sec >= key->expiry) |
354 | goto error_2; | 354 | goto error_2; |
355 | key_ref = ERR_PTR(-ENOKEY); | 355 | key_ref = ERR_PTR(key->type_data.reject_error); |
356 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) | 356 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) |
357 | goto error_2; | 357 | goto error_2; |
358 | goto found; | 358 | goto found; |
@@ -401,7 +401,7 @@ descend: | |||
401 | 401 | ||
402 | /* we set a different error code if we pass a negative key */ | 402 | /* we set a different error code if we pass a negative key */ |
403 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) { | 403 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) { |
404 | err = -ENOKEY; | 404 | err = key->type_data.reject_error; |
405 | continue; | 405 | continue; |
406 | } | 406 | } |
407 | 407 | ||
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index a3dc0d460def..df3c0417ee40 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -585,7 +585,7 @@ int wait_for_key_construction(struct key *key, bool intr) | |||
585 | if (ret < 0) | 585 | if (ret < 0) |
586 | return ret; | 586 | return ret; |
587 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) | 587 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) |
588 | return -ENOKEY; | 588 | return key->type_data.reject_error; |
589 | return key_validate(key); | 589 | return key_validate(key); |
590 | } | 590 | } |
591 | EXPORT_SYMBOL(wait_for_key_construction); | 591 | EXPORT_SYMBOL(wait_for_key_construction); |
diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 83fc92e297cd..c99b9368368c 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c | |||
@@ -1076,8 +1076,7 @@ static long trusted_read(const struct key *key, char __user *buffer, | |||
1076 | char *bufp; | 1076 | char *bufp; |
1077 | int i; | 1077 | int i; |
1078 | 1078 | ||
1079 | p = rcu_dereference_protected(key->payload.data, | 1079 | p = rcu_dereference_key(key); |
1080 | rwsem_is_locked(&((struct key *)key)->sem)); | ||
1081 | if (!p) | 1080 | if (!p) |
1082 | return -EINVAL; | 1081 | return -EINVAL; |
1083 | if (!buffer || buflen <= 0) | 1082 | if (!buffer || buflen <= 0) |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 02807fb16340..c6ca8662a468 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -184,8 +184,7 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen) | |||
184 | struct user_key_payload *upayload; | 184 | struct user_key_payload *upayload; |
185 | long ret; | 185 | long ret; |
186 | 186 | ||
187 | upayload = rcu_dereference_protected( | 187 | upayload = rcu_dereference_key(key); |
188 | key->payload.data, rwsem_is_locked(&((struct key *)key)->sem)); | ||
189 | ret = upayload->datalen; | 188 | ret = upayload->datalen; |
190 | 189 | ||
191 | /* we can return the data as is */ | 190 | /* we can return the data as is */ |
diff --git a/security/security.c b/security/security.c index 7b7308ace8c5..47b8a447118f 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -181,11 +181,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap) | |||
181 | return ret; | 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 | int security_quotactl(int cmds, int type, int id, struct super_block *sb) | 184 | int security_quotactl(int cmds, int type, int id, struct super_block *sb) |
190 | { | 185 | { |
191 | return security_ops->quotactl(cmds, type, id, sb); | 186 | return security_ops->quotactl(cmds, type, id, sb); |
@@ -271,6 +266,11 @@ int security_sb_copy_data(char *orig, char *copy) | |||
271 | } | 266 | } |
272 | EXPORT_SYMBOL(security_sb_copy_data); | 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 | int security_sb_kern_mount(struct super_block *sb, int flags, void *data) | 274 | int security_sb_kern_mount(struct super_block *sb, int flags, void *data) |
275 | { | 275 | { |
276 | return security_ops->sb_kern_mount(sb, flags, data); | 276 | return security_ops->sb_kern_mount(sb, flags, data); |
@@ -335,11 +335,13 @@ void security_inode_free(struct inode *inode) | |||
335 | } | 335 | } |
336 | 336 | ||
337 | int security_inode_init_security(struct inode *inode, struct inode *dir, | 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 | if (unlikely(IS_PRIVATE(inode))) | 341 | if (unlikely(IS_PRIVATE(inode))) |
341 | return -EOPNOTSUPP; | 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 | EXPORT_SYMBOL(security_inode_init_security); | 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) | |||
359 | return 0; | 361 | return 0; |
360 | return security_ops->path_mkdir(dir, dentry, mode); | 362 | return security_ops->path_mkdir(dir, dentry, mode); |
361 | } | 363 | } |
364 | EXPORT_SYMBOL(security_path_mkdir); | ||
362 | 365 | ||
363 | int security_path_rmdir(struct path *dir, struct dentry *dentry) | 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) | |||
373 | return 0; | 376 | return 0; |
374 | return security_ops->path_unlink(dir, dentry); | 377 | return security_ops->path_unlink(dir, dentry); |
375 | } | 378 | } |
379 | EXPORT_SYMBOL(security_path_unlink); | ||
376 | 380 | ||
377 | int security_path_symlink(struct path *dir, struct dentry *dentry, | 381 | int security_path_symlink(struct path *dir, struct dentry *dentry, |
378 | const char *old_name) | 382 | const char *old_name) |
@@ -399,6 +403,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry, | |||
399 | return security_ops->path_rename(old_dir, old_dentry, new_dir, | 403 | return security_ops->path_rename(old_dir, old_dentry, new_dir, |
400 | new_dentry); | 404 | new_dentry); |
401 | } | 405 | } |
406 | EXPORT_SYMBOL(security_path_rename); | ||
402 | 407 | ||
403 | int security_path_truncate(struct path *path) | 408 | int security_path_truncate(struct path *path) |
404 | { | 409 | { |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c8d699270687..d52a92507412 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -24,9 +24,11 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/kd.h> | ||
27 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
28 | #include <linux/tracehook.h> | 29 | #include <linux/tracehook.h> |
29 | #include <linux/errno.h> | 30 | #include <linux/errno.h> |
31 | #include <linux/ext2_fs.h> | ||
30 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
31 | #include <linux/security.h> | 33 | #include <linux/security.h> |
32 | #include <linux/xattr.h> | 34 | #include <linux/xattr.h> |
@@ -36,14 +38,15 @@ | |||
36 | #include <linux/mman.h> | 38 | #include <linux/mman.h> |
37 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
38 | #include <linux/pagemap.h> | 40 | #include <linux/pagemap.h> |
41 | #include <linux/proc_fs.h> | ||
39 | #include <linux/swap.h> | 42 | #include <linux/swap.h> |
40 | #include <linux/spinlock.h> | 43 | #include <linux/spinlock.h> |
41 | #include <linux/syscalls.h> | 44 | #include <linux/syscalls.h> |
45 | #include <linux/dcache.h> | ||
42 | #include <linux/file.h> | 46 | #include <linux/file.h> |
43 | #include <linux/fdtable.h> | 47 | #include <linux/fdtable.h> |
44 | #include <linux/namei.h> | 48 | #include <linux/namei.h> |
45 | #include <linux/mount.h> | 49 | #include <linux/mount.h> |
46 | #include <linux/proc_fs.h> | ||
47 | #include <linux/netfilter_ipv4.h> | 50 | #include <linux/netfilter_ipv4.h> |
48 | #include <linux/netfilter_ipv6.h> | 51 | #include <linux/netfilter_ipv6.h> |
49 | #include <linux/tty.h> | 52 | #include <linux/tty.h> |
@@ -70,7 +73,6 @@ | |||
70 | #include <net/ipv6.h> | 73 | #include <net/ipv6.h> |
71 | #include <linux/hugetlb.h> | 74 | #include <linux/hugetlb.h> |
72 | #include <linux/personality.h> | 75 | #include <linux/personality.h> |
73 | #include <linux/sysctl.h> | ||
74 | #include <linux/audit.h> | 76 | #include <linux/audit.h> |
75 | #include <linux/string.h> | 77 | #include <linux/string.h> |
76 | #include <linux/selinux.h> | 78 | #include <linux/selinux.h> |
@@ -1120,39 +1122,35 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc | |||
1120 | } | 1122 | } |
1121 | 1123 | ||
1122 | #ifdef CONFIG_PROC_FS | 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 | u16 tclass, | 1126 | u16 tclass, |
1125 | u32 *sid) | 1127 | u32 *sid) |
1126 | { | 1128 | { |
1127 | int buflen, rc; | 1129 | int rc; |
1128 | char *buffer, *path, *end; | 1130 | char *buffer, *path; |
1129 | 1131 | ||
1130 | buffer = (char *)__get_free_page(GFP_KERNEL); | 1132 | buffer = (char *)__get_free_page(GFP_KERNEL); |
1131 | if (!buffer) | 1133 | if (!buffer) |
1132 | return -ENOMEM; | 1134 | return -ENOMEM; |
1133 | 1135 | ||
1134 | buflen = PAGE_SIZE; | 1136 | path = dentry_path_raw(dentry, buffer, PAGE_SIZE); |
1135 | end = buffer+buflen; | 1137 | if (IS_ERR(path)) |
1136 | *--end = '\0'; | 1138 | rc = PTR_ERR(path); |
1137 | buflen--; | 1139 | else { |
1138 | path = end-1; | 1140 | /* each process gets a /proc/PID/ entry. Strip off the |
1139 | *path = '/'; | 1141 | * PID part to get a valid selinux labeling. |
1140 | while (de && de != de->parent) { | 1142 | * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ |
1141 | buflen -= de->namelen + 1; | 1143 | while (path[1] >= '0' && path[1] <= '9') { |
1142 | if (buflen < 0) | 1144 | path[1] = '/'; |
1143 | break; | 1145 | path++; |
1144 | end -= de->namelen; | 1146 | } |
1145 | memcpy(end, de->name, de->namelen); | 1147 | rc = security_genfs_sid("proc", path, tclass, sid); |
1146 | *--end = '/'; | ||
1147 | path = end; | ||
1148 | de = de->parent; | ||
1149 | } | 1148 | } |
1150 | rc = security_genfs_sid("proc", path, tclass, sid); | ||
1151 | free_page((unsigned long)buffer); | 1149 | free_page((unsigned long)buffer); |
1152 | return rc; | 1150 | return rc; |
1153 | } | 1151 | } |
1154 | #else | 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 | u16 tclass, | 1154 | u16 tclass, |
1157 | u32 *sid) | 1155 | u32 *sid) |
1158 | { | 1156 | { |
@@ -1300,10 +1298,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1300 | 1298 | ||
1301 | /* Try to obtain a transition SID. */ | 1299 | /* Try to obtain a transition SID. */ |
1302 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 1300 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
1303 | rc = security_transition_sid(isec->task_sid, | 1301 | rc = security_transition_sid(isec->task_sid, sbsec->sid, |
1304 | sbsec->sid, | 1302 | isec->sclass, NULL, &sid); |
1305 | isec->sclass, | ||
1306 | &sid); | ||
1307 | if (rc) | 1303 | if (rc) |
1308 | goto out_unlock; | 1304 | goto out_unlock; |
1309 | isec->sid = sid; | 1305 | isec->sid = sid; |
@@ -1316,10 +1312,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1316 | isec->sid = sbsec->sid; | 1312 | isec->sid = sbsec->sid; |
1317 | 1313 | ||
1318 | if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { | 1314 | if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { |
1319 | struct proc_inode *proci = PROC_I(inode); | 1315 | if (opt_dentry) { |
1320 | if (proci->pde) { | ||
1321 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 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 | isec->sclass, | 1318 | isec->sclass, |
1324 | &sid); | 1319 | &sid); |
1325 | if (rc) | 1320 | if (rc) |
@@ -1578,7 +1573,7 @@ static int may_create(struct inode *dir, | |||
1578 | return rc; | 1573 | return rc; |
1579 | 1574 | ||
1580 | if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { | 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 | if (rc) | 1577 | if (rc) |
1583 | return rc; | 1578 | return rc; |
1584 | } | 1579 | } |
@@ -1862,82 +1857,6 @@ static int selinux_capable(struct task_struct *tsk, const struct cred *cred, | |||
1862 | return task_has_capability(tsk, cred, cap, audit); | 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 | static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) | 1860 | static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) |
1942 | { | 1861 | { |
1943 | const struct cred *cred = current_cred(); | 1862 | const struct cred *cred = current_cred(); |
@@ -2060,7 +1979,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2060 | } else { | 1979 | } else { |
2061 | /* Check for a default transition on this program. */ | 1980 | /* Check for a default transition on this program. */ |
2062 | rc = security_transition_sid(old_tsec->sid, isec->sid, | 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 | if (rc) | 1984 | if (rc) |
2065 | return rc; | 1985 | return rc; |
2066 | } | 1986 | } |
@@ -2443,6 +2363,91 @@ out: | |||
2443 | return rc; | 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 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | 2451 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) |
2447 | { | 2452 | { |
2448 | const struct cred *cred = current_cred(); | 2453 | const struct cred *cred = current_cred(); |
@@ -2509,8 +2514,8 @@ static void selinux_inode_free_security(struct inode *inode) | |||
2509 | } | 2514 | } |
2510 | 2515 | ||
2511 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | 2516 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, |
2512 | char **name, void **value, | 2517 | const struct qstr *qstr, char **name, |
2513 | size_t *len) | 2518 | void **value, size_t *len) |
2514 | { | 2519 | { |
2515 | const struct task_security_struct *tsec = current_security(); | 2520 | const struct task_security_struct *tsec = current_security(); |
2516 | struct inode_security_struct *dsec; | 2521 | struct inode_security_struct *dsec; |
@@ -2531,7 +2536,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
2531 | else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { | 2536 | else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { |
2532 | rc = security_transition_sid(sid, dsec->sid, | 2537 | rc = security_transition_sid(sid, dsec->sid, |
2533 | inode_mode_to_security_class(inode->i_mode), | 2538 | inode_mode_to_security_class(inode->i_mode), |
2534 | &newsid); | 2539 | qstr, &newsid); |
2535 | if (rc) { | 2540 | if (rc) { |
2536 | printk(KERN_WARNING "%s: " | 2541 | printk(KERN_WARNING "%s: " |
2537 | "security_transition_sid failed, rc=%d (dev=%s " | 2542 | "security_transition_sid failed, rc=%d (dev=%s " |
@@ -2932,16 +2937,47 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
2932 | unsigned long arg) | 2937 | unsigned long arg) |
2933 | { | 2938 | { |
2934 | const struct cred *cred = current_cred(); | 2939 | const struct cred *cred = current_cred(); |
2935 | u32 av = 0; | 2940 | int error = 0; |
2936 | 2941 | ||
2937 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 2942 | switch (cmd) { |
2938 | av |= FILE__WRITE; | 2943 | case FIONREAD: |
2939 | if (_IOC_DIR(cmd) & _IOC_READ) | 2944 | /* fall through */ |
2940 | av |= FILE__READ; | 2945 | case FIBMAP: |
2941 | if (!av) | 2946 | /* fall through */ |
2942 | av = FILE__IOCTL; | 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 | static int default_noexec; | 2983 | static int default_noexec; |
@@ -3644,9 +3680,16 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
3644 | 3680 | ||
3645 | /* socket security operations */ | 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 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) | 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, | |||
3670 | const struct task_security_struct *tsec = current_security(); | 3713 | const struct task_security_struct *tsec = current_security(); |
3671 | u32 newsid; | 3714 | u32 newsid; |
3672 | u16 secclass; | 3715 | u16 secclass; |
3716 | int rc; | ||
3673 | 3717 | ||
3674 | if (kern) | 3718 | if (kern) |
3675 | return 0; | 3719 | return 0; |
3676 | 3720 | ||
3677 | newsid = socket_sockcreate_sid(tsec); | ||
3678 | secclass = socket_type_to_security_class(family, type, protocol); | 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 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); | 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, | |||
3687 | struct sk_security_struct *sksec; | 3734 | struct sk_security_struct *sksec; |
3688 | int err = 0; | 3735 | int err = 0; |
3689 | 3736 | ||
3737 | isec->sclass = socket_type_to_security_class(family, type, protocol); | ||
3738 | |||
3690 | if (kern) | 3739 | if (kern) |
3691 | isec->sid = SECINITSID_KERNEL; | 3740 | isec->sid = SECINITSID_KERNEL; |
3692 | else | 3741 | else { |
3693 | isec->sid = socket_sockcreate_sid(tsec); | 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 | isec->initialized = 1; | 3747 | isec->initialized = 1; |
3697 | 3748 | ||
3698 | if (sock->sk) { | 3749 | if (sock->sk) { |
@@ -4002,7 +4053,6 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4002 | { | 4053 | { |
4003 | int err = 0; | 4054 | int err = 0; |
4004 | struct sk_security_struct *sksec = sk->sk_security; | 4055 | struct sk_security_struct *sksec = sk->sk_security; |
4005 | u32 peer_sid; | ||
4006 | u32 sk_sid = sksec->sid; | 4056 | u32 sk_sid = sksec->sid; |
4007 | struct common_audit_data ad; | 4057 | struct common_audit_data ad; |
4008 | char *addrp; | 4058 | char *addrp; |
@@ -4021,20 +4071,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4021 | return err; | 4071 | return err; |
4022 | } | 4072 | } |
4023 | 4073 | ||
4024 | if (selinux_policycap_netpeer) { | 4074 | err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); |
4025 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); | 4075 | if (err) |
4026 | if (err) | 4076 | return err; |
4027 | return err; | 4077 | err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); |
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 | } | ||
4038 | 4078 | ||
4039 | return err; | 4079 | return err; |
4040 | } | 4080 | } |
@@ -4529,9 +4569,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4529 | SECCLASS_PACKET, PACKET__SEND, &ad)) | 4569 | SECCLASS_PACKET, PACKET__SEND, &ad)) |
4530 | return NF_DROP_ERR(-ECONNREFUSED); | 4570 | return NF_DROP_ERR(-ECONNREFUSED); |
4531 | 4571 | ||
4532 | if (selinux_policycap_netpeer) | 4572 | if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) |
4533 | if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) | 4573 | return NF_DROP_ERR(-ECONNREFUSED); |
4534 | return NF_DROP_ERR(-ECONNREFUSED); | ||
4535 | 4574 | ||
4536 | return NF_ACCEPT; | 4575 | return NF_ACCEPT; |
4537 | } | 4576 | } |
@@ -4574,27 +4613,14 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4574 | * from the sending socket, otherwise use the kernel's sid */ | 4613 | * from the sending socket, otherwise use the kernel's sid */ |
4575 | sk = skb->sk; | 4614 | sk = skb->sk; |
4576 | if (sk == NULL) { | 4615 | if (sk == NULL) { |
4577 | switch (family) { | 4616 | if (skb->skb_iif) { |
4578 | case PF_INET: | 4617 | secmark_perm = PACKET__FORWARD_OUT; |
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) { | ||
4594 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) | 4618 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) |
4595 | return NF_DROP; | 4619 | return NF_DROP; |
4596 | } else | 4620 | } else { |
4621 | secmark_perm = PACKET__SEND; | ||
4597 | peer_sid = SECINITSID_KERNEL; | 4622 | peer_sid = SECINITSID_KERNEL; |
4623 | } | ||
4598 | } else { | 4624 | } else { |
4599 | struct sk_security_struct *sksec = sk->sk_security; | 4625 | struct sk_security_struct *sksec = sk->sk_security; |
4600 | peer_sid = sksec->sid; | 4626 | peer_sid = sksec->sid; |
@@ -4848,7 +4874,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4848 | * message queue this message will be stored in | 4874 | * message queue this message will be stored in |
4849 | */ | 4875 | */ |
4850 | rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG, | 4876 | rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG, |
4851 | &msec->sid); | 4877 | NULL, &msec->sid); |
4852 | if (rc) | 4878 | if (rc) |
4853 | return rc; | 4879 | return rc; |
4854 | } | 4880 | } |
@@ -5402,7 +5428,6 @@ static struct security_operations selinux_ops = { | |||
5402 | .ptrace_traceme = selinux_ptrace_traceme, | 5428 | .ptrace_traceme = selinux_ptrace_traceme, |
5403 | .capget = selinux_capget, | 5429 | .capget = selinux_capget, |
5404 | .capset = selinux_capset, | 5430 | .capset = selinux_capset, |
5405 | .sysctl = selinux_sysctl, | ||
5406 | .capable = selinux_capable, | 5431 | .capable = selinux_capable, |
5407 | .quotactl = selinux_quotactl, | 5432 | .quotactl = selinux_quotactl, |
5408 | .quota_on = selinux_quota_on, | 5433 | .quota_on = selinux_quota_on, |
@@ -5420,6 +5445,7 @@ static struct security_operations selinux_ops = { | |||
5420 | .sb_alloc_security = selinux_sb_alloc_security, | 5445 | .sb_alloc_security = selinux_sb_alloc_security, |
5421 | .sb_free_security = selinux_sb_free_security, | 5446 | .sb_free_security = selinux_sb_free_security, |
5422 | .sb_copy_data = selinux_sb_copy_data, | 5447 | .sb_copy_data = selinux_sb_copy_data, |
5448 | .sb_remount = selinux_sb_remount, | ||
5423 | .sb_kern_mount = selinux_sb_kern_mount, | 5449 | .sb_kern_mount = selinux_sb_kern_mount, |
5424 | .sb_show_options = selinux_sb_show_options, | 5450 | .sb_show_options = selinux_sb_show_options, |
5425 | .sb_statfs = selinux_sb_statfs, | 5451 | .sb_statfs = selinux_sb_statfs, |
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 7ed3663332ec..b8c53723e09b 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h | |||
@@ -12,6 +12,10 @@ | |||
12 | #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \ | 12 | #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \ |
13 | "write", "associate", "unix_read", "unix_write" | 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 | struct security_class_mapping secclass_map[] = { | 19 | struct security_class_mapping secclass_map[] = { |
16 | { "security", | 20 | { "security", |
17 | { "compute_av", "compute_create", "compute_member", | 21 | { "compute_av", "compute_create", "compute_member", |
@@ -132,8 +136,7 @@ struct security_class_mapping secclass_map[] = { | |||
132 | { "appletalk_socket", | 136 | { "appletalk_socket", |
133 | { COMMON_SOCK_PERMS, NULL } }, | 137 | { COMMON_SOCK_PERMS, NULL } }, |
134 | { "packet", | 138 | { "packet", |
135 | { "send", "recv", "relabelto", "flow_in", "flow_out", | 139 | { "send", "recv", "relabelto", "forward_in", "forward_out", NULL } }, |
136 | "forward_in", "forward_out", NULL } }, | ||
137 | { "key", | 140 | { "key", |
138 | { "view", "read", "write", "search", "link", "setattr", "create", | 141 | { "view", "read", "write", "search", "link", "setattr", "create", |
139 | NULL } }, | 142 | NULL } }, |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 671273eb1115..348eb00cb668 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #ifndef _SELINUX_SECURITY_H_ | 8 | #ifndef _SELINUX_SECURITY_H_ |
9 | #define _SELINUX_SECURITY_H_ | 9 | #define _SELINUX_SECURITY_H_ |
10 | 10 | ||
11 | #include <linux/dcache.h> | ||
11 | #include <linux/magic.h> | 12 | #include <linux/magic.h> |
12 | #include <linux/types.h> | 13 | #include <linux/types.h> |
13 | #include "flask.h" | 14 | #include "flask.h" |
@@ -28,13 +29,14 @@ | |||
28 | #define POLICYDB_VERSION_POLCAP 22 | 29 | #define POLICYDB_VERSION_POLCAP 22 |
29 | #define POLICYDB_VERSION_PERMISSIVE 23 | 30 | #define POLICYDB_VERSION_PERMISSIVE 23 |
30 | #define POLICYDB_VERSION_BOUNDARY 24 | 31 | #define POLICYDB_VERSION_BOUNDARY 24 |
32 | #define POLICYDB_VERSION_FILENAME_TRANS 25 | ||
31 | 33 | ||
32 | /* Range of policy versions we understand*/ | 34 | /* Range of policy versions we understand*/ |
33 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE | 35 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
34 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX | 36 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX |
35 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE | 37 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE |
36 | #else | 38 | #else |
37 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY | 39 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_FILENAME_TRANS |
38 | #endif | 40 | #endif |
39 | 41 | ||
40 | /* Mask for just the mount related flags */ | 42 | /* Mask for just the mount related flags */ |
@@ -106,8 +108,8 @@ void security_compute_av(u32 ssid, u32 tsid, | |||
106 | void security_compute_av_user(u32 ssid, u32 tsid, | 108 | void security_compute_av_user(u32 ssid, u32 tsid, |
107 | u16 tclass, struct av_decision *avd); | 109 | u16 tclass, struct av_decision *avd); |
108 | 110 | ||
109 | int security_transition_sid(u32 ssid, u32 tsid, | 111 | int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, |
110 | u16 tclass, u32 *out_sid); | 112 | const struct qstr *qstr, u32 *out_sid); |
111 | 113 | ||
112 | int security_transition_sid_user(u32 ssid, u32 tsid, | 114 | int security_transition_sid_user(u32 ssid, u32 tsid, |
113 | u16 tclass, u32 *out_sid); | 115 | u16 tclass, u32 *out_sid); |
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index dff0c75345c1..63ce2f9e441d 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h | |||
@@ -14,7 +14,7 @@ | |||
14 | * | 14 | * |
15 | * Copyright (C) 2003 Tresys Technology, LLC | 15 | * Copyright (C) 2003 Tresys Technology, LLC |
16 | * This program is free software; you can redistribute it and/or modify | 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 | * the Free Software Foundation, version 2. | 18 | * the Free Software Foundation, version 2. |
19 | * | 19 | * |
20 | * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp> | 20 | * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp> |
@@ -27,16 +27,16 @@ struct avtab_key { | |||
27 | u16 source_type; /* source type */ | 27 | u16 source_type; /* source type */ |
28 | u16 target_type; /* target type */ | 28 | u16 target_type; /* target type */ |
29 | u16 target_class; /* target object class */ | 29 | u16 target_class; /* target object class */ |
30 | #define AVTAB_ALLOWED 1 | 30 | #define AVTAB_ALLOWED 0x0001 |
31 | #define AVTAB_AUDITALLOW 2 | 31 | #define AVTAB_AUDITALLOW 0x0002 |
32 | #define AVTAB_AUDITDENY 4 | 32 | #define AVTAB_AUDITDENY 0x0004 |
33 | #define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) | 33 | #define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) |
34 | #define AVTAB_TRANSITION 16 | 34 | #define AVTAB_TRANSITION 0x0010 |
35 | #define AVTAB_MEMBER 32 | 35 | #define AVTAB_MEMBER 0x0020 |
36 | #define AVTAB_CHANGE 64 | 36 | #define AVTAB_CHANGE 0x0040 |
37 | #define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) | 37 | #define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) |
38 | #define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ | 38 | #define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ |
39 | #define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ | 39 | #define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ |
40 | u16 specified; /* what field is specified */ | 40 | u16 specified; /* what field is specified */ |
41 | }; | 41 | }; |
42 | 42 | ||
@@ -86,7 +86,6 @@ void avtab_cache_destroy(void); | |||
86 | 86 | ||
87 | #define MAX_AVTAB_HASH_BITS 11 | 87 | #define MAX_AVTAB_HASH_BITS 11 |
88 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) | 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 | #endif /* _SS_AVTAB_H_ */ | 90 | #endif /* _SS_AVTAB_H_ */ |
92 | 91 | ||
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index 1f4e93c2ae86..922f8afa89dd 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h | |||
@@ -36,7 +36,6 @@ struct ebitmap { | |||
36 | }; | 36 | }; |
37 | 37 | ||
38 | #define ebitmap_length(e) ((e)->highbit) | 38 | #define ebitmap_length(e) ((e)->highbit) |
39 | #define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) | ||
40 | 39 | ||
41 | static inline unsigned int ebitmap_start_positive(struct ebitmap *e, | 40 | static inline unsigned int ebitmap_start_positive(struct ebitmap *e, |
42 | struct ebitmap_node **n) | 41 | struct ebitmap_node **n) |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 1ef8e4e89880..e96174216bc9 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -512,7 +512,8 @@ int mls_compute_sid(struct context *scontext, | |||
512 | struct context *tcontext, | 512 | struct context *tcontext, |
513 | u16 tclass, | 513 | u16 tclass, |
514 | u32 specified, | 514 | u32 specified, |
515 | struct context *newcontext) | 515 | struct context *newcontext, |
516 | bool sock) | ||
516 | { | 517 | { |
517 | struct range_trans rtr; | 518 | struct range_trans rtr; |
518 | struct mls_range *r; | 519 | struct mls_range *r; |
@@ -531,7 +532,7 @@ int mls_compute_sid(struct context *scontext, | |||
531 | return mls_range_set(newcontext, r); | 532 | return mls_range_set(newcontext, r); |
532 | /* Fallthrough */ | 533 | /* Fallthrough */ |
533 | case AVTAB_CHANGE: | 534 | case AVTAB_CHANGE: |
534 | if (tclass == policydb.process_class) | 535 | if ((tclass == policydb.process_class) || (sock == true)) |
535 | /* Use the process MLS attributes. */ | 536 | /* Use the process MLS attributes. */ |
536 | return mls_context_cpy(newcontext, scontext); | 537 | return mls_context_cpy(newcontext, scontext); |
537 | else | 538 | else |
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index cd9152632e54..037bf9d82d41 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h | |||
@@ -49,7 +49,8 @@ int mls_compute_sid(struct context *scontext, | |||
49 | struct context *tcontext, | 49 | struct context *tcontext, |
50 | u16 tclass, | 50 | u16 tclass, |
51 | u32 specified, | 51 | u32 specified, |
52 | struct context *newcontext); | 52 | struct context *newcontext, |
53 | bool sock); | ||
53 | 54 | ||
54 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, | 55 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, |
55 | struct context *usercon); | 56 | struct context *usercon); |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 57363562f0f8..e7b850ad57ee 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -123,6 +123,11 @@ static struct policydb_compat_info policydb_compat[] = { | |||
123 | .sym_num = SYM_NUM, | 123 | .sym_num = SYM_NUM, |
124 | .ocon_num = OCON_NUM, | 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 | static struct policydb_compat_info *policydb_lookup_compat(int version) | 133 | static struct policydb_compat_info *policydb_lookup_compat(int version) |
@@ -704,6 +709,7 @@ void policydb_destroy(struct policydb *p) | |||
704 | int i; | 709 | int i; |
705 | struct role_allow *ra, *lra = NULL; | 710 | struct role_allow *ra, *lra = NULL; |
706 | struct role_trans *tr, *ltr = NULL; | 711 | struct role_trans *tr, *ltr = NULL; |
712 | struct filename_trans *ft, *nft; | ||
707 | 713 | ||
708 | for (i = 0; i < SYM_NUM; i++) { | 714 | for (i = 0; i < SYM_NUM; i++) { |
709 | cond_resched(); | 715 | cond_resched(); |
@@ -781,6 +787,15 @@ void policydb_destroy(struct policydb *p) | |||
781 | } | 787 | } |
782 | flex_array_free(p->type_attr_map_array); | 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 | ebitmap_destroy(&p->policycaps); | 799 | ebitmap_destroy(&p->policycaps); |
785 | ebitmap_destroy(&p->permissive_map); | 800 | ebitmap_destroy(&p->permissive_map); |
786 | 801 | ||
@@ -1788,6 +1803,76 @@ out: | |||
1788 | return rc; | 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 | static int genfs_read(struct policydb *p, void *fp) | 1876 | static int genfs_read(struct policydb *p, void *fp) |
1792 | { | 1877 | { |
1793 | int i, j, rc; | 1878 | int i, j, rc; |
@@ -2251,6 +2336,10 @@ int policydb_read(struct policydb *p, void *fp) | |||
2251 | lra = ra; | 2336 | lra = ra; |
2252 | } | 2337 | } |
2253 | 2338 | ||
2339 | rc = filename_trans_read(p, fp); | ||
2340 | if (rc) | ||
2341 | goto bad; | ||
2342 | |||
2254 | rc = policydb_index(p); | 2343 | rc = policydb_index(p); |
2255 | if (rc) | 2344 | if (rc) |
2256 | goto bad; | 2345 | goto bad; |
@@ -3025,6 +3114,43 @@ static int range_write(struct policydb *p, void *fp) | |||
3025 | return 0; | 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 | * Write the configuration data in a policy database | 3155 | * Write the configuration data in a policy database |
3030 | * structure to a policy database binary representation | 3156 | * structure to a policy database binary representation |
@@ -3135,6 +3261,10 @@ int policydb_write(struct policydb *p, void *fp) | |||
3135 | if (rc) | 3261 | if (rc) |
3136 | return rc; | 3262 | return rc; |
3137 | 3263 | ||
3264 | rc = filename_trans_write(p, fp); | ||
3265 | if (rc) | ||
3266 | return rc; | ||
3267 | |||
3138 | rc = ocontext_write(p, info, fp); | 3268 | rc = ocontext_write(p, info, fp); |
3139 | if (rc) | 3269 | if (rc) |
3140 | return rc; | 3270 | return rc; |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 4e3ab9d0b315..732ea4a68682 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -77,6 +77,15 @@ struct role_trans { | |||
77 | struct role_trans *next; | 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 | struct role_allow { | 89 | struct role_allow { |
81 | u32 role; /* current role */ | 90 | u32 role; /* current role */ |
82 | u32 new_role; /* new role */ | 91 | u32 new_role; /* new role */ |
@@ -217,6 +226,9 @@ struct policydb { | |||
217 | /* role transitions */ | 226 | /* role transitions */ |
218 | struct role_trans *role_tr; | 227 | struct role_trans *role_tr; |
219 | 228 | ||
229 | /* file transitions with the last path component */ | ||
230 | struct filename_trans *filename_trans; | ||
231 | |||
220 | /* bools indexed by (value - 1) */ | 232 | /* bools indexed by (value - 1) */ |
221 | struct cond_bool_datum **bool_val_to_struct; | 233 | struct cond_bool_datum **bool_val_to_struct; |
222 | /* type enforcement conditional access vectors and transitions */ | 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) | |||
302 | return 0; | 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 | size_t len = bytes * num; | 319 | size_t len = bytes * num; |
308 | 320 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index a03cfaf0ee07..3e7544d2a07b 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -201,6 +201,21 @@ static u16 unmap_class(u16 tclass) | |||
201 | return tclass; | 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 | static void map_decision(u16 tclass, struct av_decision *avd, | 219 | static void map_decision(u16 tclass, struct av_decision *avd, |
205 | int allow_unknown) | 220 | int allow_unknown) |
206 | { | 221 | { |
@@ -1343,10 +1358,27 @@ out: | |||
1343 | return -EACCES; | 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 | static int security_compute_sid(u32 ssid, | 1377 | static int security_compute_sid(u32 ssid, |
1347 | u32 tsid, | 1378 | u32 tsid, |
1348 | u16 orig_tclass, | 1379 | u16 orig_tclass, |
1349 | u32 specified, | 1380 | u32 specified, |
1381 | const struct qstr *qstr, | ||
1350 | u32 *out_sid, | 1382 | u32 *out_sid, |
1351 | bool kern) | 1383 | bool kern) |
1352 | { | 1384 | { |
@@ -1357,6 +1389,7 @@ static int security_compute_sid(u32 ssid, | |||
1357 | struct avtab_node *node; | 1389 | struct avtab_node *node; |
1358 | u16 tclass; | 1390 | u16 tclass; |
1359 | int rc = 0; | 1391 | int rc = 0; |
1392 | bool sock; | ||
1360 | 1393 | ||
1361 | if (!ss_initialized) { | 1394 | if (!ss_initialized) { |
1362 | switch (orig_tclass) { | 1395 | switch (orig_tclass) { |
@@ -1374,10 +1407,13 @@ static int security_compute_sid(u32 ssid, | |||
1374 | 1407 | ||
1375 | read_lock(&policy_rwlock); | 1408 | read_lock(&policy_rwlock); |
1376 | 1409 | ||
1377 | if (kern) | 1410 | if (kern) { |
1378 | tclass = unmap_class(orig_tclass); | 1411 | tclass = unmap_class(orig_tclass); |
1379 | else | 1412 | sock = security_is_socket_class(orig_tclass); |
1413 | } else { | ||
1380 | tclass = orig_tclass; | 1414 | tclass = orig_tclass; |
1415 | sock = security_is_socket_class(map_class(tclass)); | ||
1416 | } | ||
1381 | 1417 | ||
1382 | scontext = sidtab_search(&sidtab, ssid); | 1418 | scontext = sidtab_search(&sidtab, ssid); |
1383 | if (!scontext) { | 1419 | if (!scontext) { |
@@ -1408,7 +1444,7 @@ static int security_compute_sid(u32 ssid, | |||
1408 | } | 1444 | } |
1409 | 1445 | ||
1410 | /* Set the role and type to default values. */ | 1446 | /* Set the role and type to default values. */ |
1411 | if (tclass == policydb.process_class) { | 1447 | if ((tclass == policydb.process_class) || (sock == true)) { |
1412 | /* Use the current role and type of process. */ | 1448 | /* Use the current role and type of process. */ |
1413 | newcontext.role = scontext->role; | 1449 | newcontext.role = scontext->role; |
1414 | newcontext.type = scontext->type; | 1450 | newcontext.type = scontext->type; |
@@ -1442,6 +1478,11 @@ static int security_compute_sid(u32 ssid, | |||
1442 | newcontext.type = avdatum->data; | 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 | /* Check for class-specific changes. */ | 1486 | /* Check for class-specific changes. */ |
1446 | if (tclass == policydb.process_class) { | 1487 | if (tclass == policydb.process_class) { |
1447 | if (specified & AVTAB_TRANSITION) { | 1488 | if (specified & AVTAB_TRANSITION) { |
@@ -1460,7 +1501,8 @@ static int security_compute_sid(u32 ssid, | |||
1460 | 1501 | ||
1461 | /* Set the MLS attributes. | 1502 | /* Set the MLS attributes. |
1462 | This is done last because it may allocate memory. */ | 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 | if (rc) | 1506 | if (rc) |
1465 | goto out_unlock; | 1507 | goto out_unlock; |
1466 | 1508 | ||
@@ -1495,22 +1537,17 @@ out: | |||
1495 | * if insufficient memory is available, or %0 if the new SID was | 1537 | * if insufficient memory is available, or %0 if the new SID was |
1496 | * computed successfully. | 1538 | * computed successfully. |
1497 | */ | 1539 | */ |
1498 | int security_transition_sid(u32 ssid, | 1540 | int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, |
1499 | u32 tsid, | 1541 | const struct qstr *qstr, u32 *out_sid) |
1500 | u16 tclass, | ||
1501 | u32 *out_sid) | ||
1502 | { | 1542 | { |
1503 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | 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, | 1547 | int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid) |
1508 | u32 tsid, | ||
1509 | u16 tclass, | ||
1510 | u32 *out_sid) | ||
1511 | { | 1548 | { |
1512 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | 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, | |||
1531 | u16 tclass, | 1568 | u16 tclass, |
1532 | u32 *out_sid) | 1569 | u32 *out_sid) |
1533 | { | 1570 | { |
1534 | return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid, | 1571 | return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, NULL, |
1535 | false); | 1572 | out_sid, false); |
1536 | } | 1573 | } |
1537 | 1574 | ||
1538 | /** | 1575 | /** |
@@ -1553,8 +1590,8 @@ int security_change_sid(u32 ssid, | |||
1553 | u16 tclass, | 1590 | u16 tclass, |
1554 | u32 *out_sid) | 1591 | u32 *out_sid) |
1555 | { | 1592 | { |
1556 | return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid, | 1593 | return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL, |
1557 | false); | 1594 | out_sid, false); |
1558 | } | 1595 | } |
1559 | 1596 | ||
1560 | /* Clone the SID into the new SID table. */ | 1597 | /* Clone the SID into the new SID table. */ |
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index fff78d3b51a2..728c57e3d65d 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
@@ -208,7 +208,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, | |||
208 | if (!uctx) | 208 | if (!uctx) |
209 | goto not_from_user; | 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 | return -EINVAL; | 212 | return -EINVAL; |
213 | 213 | ||
214 | str_len = uctx->ctx_len; | 214 | str_len = uctx->ctx_len; |
diff --git a/security/smack/smack.h b/security/smack/smack.h index 129c4eb8ffb1..b449cfdad21c 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -52,13 +52,16 @@ struct socket_smack { | |||
52 | struct inode_smack { | 52 | struct inode_smack { |
53 | char *smk_inode; /* label of the fso */ | 53 | char *smk_inode; /* label of the fso */ |
54 | char *smk_task; /* label of the task */ | 54 | char *smk_task; /* label of the task */ |
55 | char *smk_mmap; /* label of the mmap domain */ | ||
55 | struct mutex smk_lock; /* initialization lock */ | 56 | struct mutex smk_lock; /* initialization lock */ |
56 | int smk_flags; /* smack inode flags */ | 57 | int smk_flags; /* smack inode flags */ |
57 | }; | 58 | }; |
58 | 59 | ||
59 | struct task_smack { | 60 | struct task_smack { |
60 | char *smk_task; /* label used for access control */ | 61 | char *smk_task; /* label for access control */ |
61 | char *smk_forked; /* label when forked */ | 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 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ | 67 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ |
@@ -152,12 +155,6 @@ struct smack_known { | |||
152 | #define SMACK_MAGIC 0x43415d53 /* "SMAC" */ | 155 | #define SMACK_MAGIC 0x43415d53 /* "SMAC" */ |
153 | 156 | ||
154 | /* | 157 | /* |
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 | /* | ||
161 | * CIPSO defaults. | 158 | * CIPSO defaults. |
162 | */ | 159 | */ |
163 | #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ | 160 | #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ |
@@ -174,9 +171,7 @@ struct smack_known { | |||
174 | /* | 171 | /* |
175 | * Just to make the common cases easier to deal with | 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 | #define MAY_ANYREAD (MAY_READ | MAY_EXEC) | 174 | #define MAY_ANYREAD (MAY_READ | MAY_EXEC) |
179 | #define MAY_ANYWRITE (MAY_WRITE | MAY_APPEND) | ||
180 | #define MAY_READWRITE (MAY_READ | MAY_WRITE) | 175 | #define MAY_READWRITE (MAY_READ | MAY_WRITE) |
181 | #define MAY_NOT 0 | 176 | #define MAY_NOT 0 |
182 | 177 | ||
@@ -202,7 +197,7 @@ struct inode_smack *new_inode_smack(char *); | |||
202 | /* | 197 | /* |
203 | * These functions are in smack_access.c | 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 | int smk_access(char *, char *, int, struct smk_audit_info *); | 201 | int smk_access(char *, char *, int, struct smk_audit_info *); |
207 | int smk_curacc(char *, u32, struct smk_audit_info *); | 202 | int smk_curacc(char *, u32, struct smk_audit_info *); |
208 | int smack_to_cipso(const char *, struct smack_cipso *); | 203 | int smack_to_cipso(const char *, struct smack_cipso *); |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 7ba8478f599e..86453db4333d 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -70,10 +70,11 @@ int log_policy = SMACK_AUDIT_DENIED; | |||
70 | * smk_access_entry - look up matching access rule | 70 | * smk_access_entry - look up matching access rule |
71 | * @subject_label: a pointer to the subject's Smack label | 71 | * @subject_label: a pointer to the subject's Smack label |
72 | * @object_label: a pointer to the object's Smack label | 72 | * @object_label: a pointer to the object's Smack label |
73 | * @rule_list: the list of rules to search | ||
73 | * | 74 | * |
74 | * This function looks up the subject/object pair in the | 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 | * access rule list and returns the access mode. If no |
76 | * NULL otherwise. | 77 | * entry is found returns -ENOENT. |
77 | * | 78 | * |
78 | * NOTE: | 79 | * NOTE: |
79 | * Even though Smack labels are usually shared on smack_list | 80 | * Even though Smack labels are usually shared on smack_list |
@@ -85,13 +86,13 @@ int log_policy = SMACK_AUDIT_DENIED; | |||
85 | * will be on the list, so checking the pointers may be a worthwhile | 86 | * will be on the list, so checking the pointers may be a worthwhile |
86 | * optimization. | 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 | struct smack_rule *srp; | 93 | struct smack_rule *srp; |
92 | 94 | ||
93 | rcu_read_lock(); | 95 | list_for_each_entry_rcu(srp, rule_list, list) { |
94 | list_for_each_entry_rcu(srp, &smack_rule_list, list) { | ||
95 | if (srp->smk_subject == subject_label || | 96 | if (srp->smk_subject == subject_label || |
96 | strcmp(srp->smk_subject, subject_label) == 0) { | 97 | strcmp(srp->smk_subject, subject_label) == 0) { |
97 | if (srp->smk_object == object_label || | 98 | if (srp->smk_object == object_label || |
@@ -101,7 +102,6 @@ int smk_access_entry(char *subject_label, char *object_label) | |||
101 | } | 102 | } |
102 | } | 103 | } |
103 | } | 104 | } |
104 | rcu_read_unlock(); | ||
105 | 105 | ||
106 | return may; | 106 | return may; |
107 | } | 107 | } |
@@ -129,7 +129,7 @@ int smk_access_entry(char *subject_label, char *object_label) | |||
129 | int smk_access(char *subject_label, char *object_label, int request, | 129 | int smk_access(char *subject_label, char *object_label, int request, |
130 | struct smk_audit_info *a) | 130 | struct smk_audit_info *a) |
131 | { | 131 | { |
132 | u32 may = MAY_NOT; | 132 | int may = MAY_NOT; |
133 | int rc = 0; | 133 | int rc = 0; |
134 | 134 | ||
135 | /* | 135 | /* |
@@ -181,13 +181,14 @@ int smk_access(char *subject_label, char *object_label, int request, | |||
181 | * Beyond here an explicit relationship is required. | 181 | * Beyond here an explicit relationship is required. |
182 | * If the requested access is contained in the available | 182 | * If the requested access is contained in the available |
183 | * access (e.g. read is included in readwrite) it's | 183 | * access (e.g. read is included in readwrite) it's |
184 | * good. | 184 | * good. A negative response from smk_access_entry() |
185 | */ | 185 | * indicates there is no entry for this pair. |
186 | may = smk_access_entry(subject_label, object_label); | ||
187 | /* | ||
188 | * This is a bit map operation. | ||
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 | goto out_audit; | 192 | goto out_audit; |
192 | 193 | ||
193 | rc = -EACCES; | 194 | rc = -EACCES; |
@@ -212,12 +213,27 @@ out_audit: | |||
212 | */ | 213 | */ |
213 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | 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 | int rc; | 219 | int rc; |
216 | char *sp = smk_of_current(); | ||
217 | 220 | ||
221 | /* | ||
222 | * Check the global rule list | ||
223 | */ | ||
218 | rc = smk_access(sp, obj_label, mode, NULL); | 224 | rc = smk_access(sp, obj_label, mode, NULL); |
219 | if (rc == 0) | 225 | if (rc == 0) { |
220 | goto out_audit; | 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 | * Return if a specific label has been designated as the | 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) | |||
228 | goto out_audit; | 244 | goto out_audit; |
229 | 245 | ||
230 | if (capable(CAP_MAC_OVERRIDE)) | 246 | if (capable(CAP_MAC_OVERRIDE)) |
231 | return 0; | 247 | rc = 0; |
232 | 248 | ||
233 | out_audit: | 249 | out_audit: |
234 | #ifdef CONFIG_AUDIT | 250 | #ifdef CONFIG_AUDIT |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 533bf3255d7f..23c7a6d0c80c 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <net/cipso_ipv4.h> | 33 | #include <net/cipso_ipv4.h> |
34 | #include <linux/audit.h> | 34 | #include <linux/audit.h> |
35 | #include <linux/magic.h> | 35 | #include <linux/magic.h> |
36 | #include <linux/dcache.h> | ||
36 | #include "smack.h" | 37 | #include "smack.h" |
37 | 38 | ||
38 | #define task_security(task) (task_cred_xxx((task), security)) | 39 | #define task_security(task) (task_cred_xxx((task), security)) |
@@ -84,6 +85,56 @@ struct inode_smack *new_inode_smack(char *smack) | |||
84 | return isp; | 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 | * LSM hooks. | 139 | * LSM hooks. |
89 | * We he, that is fun! | 140 | * We he, that is fun! |
@@ -102,23 +153,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
102 | { | 153 | { |
103 | int rc; | 154 | int rc; |
104 | struct smk_audit_info ad; | 155 | struct smk_audit_info ad; |
105 | char *sp, *tsp; | 156 | char *tsp; |
106 | 157 | ||
107 | rc = cap_ptrace_access_check(ctp, mode); | 158 | rc = cap_ptrace_access_check(ctp, mode); |
108 | if (rc != 0) | 159 | if (rc != 0) |
109 | return rc; | 160 | return rc; |
110 | 161 | ||
111 | sp = smk_of_current(); | ||
112 | tsp = smk_of_task(task_security(ctp)); | 162 | tsp = smk_of_task(task_security(ctp)); |
113 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 163 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
114 | smk_ad_setfield_u_tsk(&ad, ctp); | 164 | smk_ad_setfield_u_tsk(&ad, ctp); |
115 | 165 | ||
116 | /* we won't log here, because rc can be overriden */ | 166 | rc = smk_curacc(tsp, MAY_READWRITE, &ad); |
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); | ||
122 | return rc; | 167 | return rc; |
123 | } | 168 | } |
124 | 169 | ||
@@ -134,23 +179,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
134 | { | 179 | { |
135 | int rc; | 180 | int rc; |
136 | struct smk_audit_info ad; | 181 | struct smk_audit_info ad; |
137 | char *sp, *tsp; | 182 | char *tsp; |
138 | 183 | ||
139 | rc = cap_ptrace_traceme(ptp); | 184 | rc = cap_ptrace_traceme(ptp); |
140 | if (rc != 0) | 185 | if (rc != 0) |
141 | return rc; | 186 | return rc; |
142 | 187 | ||
188 | tsp = smk_of_task(task_security(ptp)); | ||
143 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 189 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
144 | smk_ad_setfield_u_tsk(&ad, ptp); | 190 | smk_ad_setfield_u_tsk(&ad, ptp); |
145 | 191 | ||
146 | sp = smk_of_current(); | 192 | rc = smk_curacc(tsp, MAY_READWRITE, &ad); |
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); | ||
154 | return rc; | 193 | return rc; |
155 | } | 194 | } |
156 | 195 | ||
@@ -463,6 +502,7 @@ static void smack_inode_free_security(struct inode *inode) | |||
463 | * smack_inode_init_security - copy out the smack from an inode | 502 | * smack_inode_init_security - copy out the smack from an inode |
464 | * @inode: the inode | 503 | * @inode: the inode |
465 | * @dir: unused | 504 | * @dir: unused |
505 | * @qstr: unused | ||
466 | * @name: where to put the attribute name | 506 | * @name: where to put the attribute name |
467 | * @value: where to put the attribute value | 507 | * @value: where to put the attribute value |
468 | * @len: where to put the length of the attribute | 508 | * @len: where to put the length of the attribute |
@@ -470,11 +510,12 @@ static void smack_inode_free_security(struct inode *inode) | |||
470 | * Returns 0 if it all works out, -ENOMEM if there's no memory | 510 | * Returns 0 if it all works out, -ENOMEM if there's no memory |
471 | */ | 511 | */ |
472 | static int smack_inode_init_security(struct inode *inode, struct inode *dir, | 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 | char *isp = smk_of_inode(inode); | 516 | char *isp = smk_of_inode(inode); |
476 | char *dsp = smk_of_inode(dir); | 517 | char *dsp = smk_of_inode(dir); |
477 | u32 may; | 518 | int may; |
478 | 519 | ||
479 | if (name) { | 520 | if (name) { |
480 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); | 521 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); |
@@ -483,14 +524,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
483 | } | 524 | } |
484 | 525 | ||
485 | if (value) { | 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 | * If the access rule allows transmutation and | 532 | * If the access rule allows transmutation and |
490 | * the directory requests transmutation then | 533 | * the directory requests transmutation then |
491 | * by all means transmute. | 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 | isp = dsp; | 538 | isp = dsp; |
495 | 539 | ||
496 | *value = kstrdup(isp, GFP_KERNEL); | 540 | *value = kstrdup(isp, GFP_KERNEL); |
@@ -716,7 +760,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
716 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 760 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
717 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 761 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
718 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || | 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 | if (!capable(CAP_MAC_ADMIN)) | 765 | if (!capable(CAP_MAC_ADMIN)) |
721 | rc = -EPERM; | 766 | rc = -EPERM; |
722 | /* | 767 | /* |
@@ -773,6 +818,12 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
773 | isp->smk_task = nsp; | 818 | isp->smk_task = nsp; |
774 | else | 819 | else |
775 | isp->smk_task = smack_known_invalid.smk_known; | 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 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) | 827 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) |
777 | isp->smk_flags |= SMK_INODE_TRANSMUTE; | 828 | isp->smk_flags |= SMK_INODE_TRANSMUTE; |
778 | 829 | ||
@@ -815,7 +866,8 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
815 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 866 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
816 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || | 867 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
817 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | 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 | if (!capable(CAP_MAC_ADMIN)) | 871 | if (!capable(CAP_MAC_ADMIN)) |
820 | rc = -EPERM; | 872 | rc = -EPERM; |
821 | } else | 873 | } else |
@@ -829,6 +881,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
829 | if (rc == 0) { | 881 | if (rc == 0) { |
830 | isp = dentry->d_inode->i_security; | 882 | isp = dentry->d_inode->i_security; |
831 | isp->smk_task = NULL; | 883 | isp->smk_task = NULL; |
884 | isp->smk_mmap = NULL; | ||
832 | } | 885 | } |
833 | 886 | ||
834 | return rc; | 887 | return rc; |
@@ -1060,6 +1113,126 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1060 | } | 1113 | } |
1061 | 1114 | ||
1062 | /** | 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 | |||
1235 | /** | ||
1063 | * smack_file_set_fowner - set the file security blob value | 1236 | * smack_file_set_fowner - set the file security blob value |
1064 | * @file: object in question | 1237 | * @file: object in question |
1065 | * | 1238 | * |
@@ -1095,6 +1268,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, | |||
1095 | * struct fown_struct is never outside the context of a struct file | 1268 | * struct fown_struct is never outside the context of a struct file |
1096 | */ | 1269 | */ |
1097 | file = container_of(fown, struct file, f_owner); | 1270 | file = container_of(fown, struct file, f_owner); |
1271 | |||
1098 | /* we don't log here as rc can be overriden */ | 1272 | /* we don't log here as rc can be overriden */ |
1099 | rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); | 1273 | rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); |
1100 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) | 1274 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) |
@@ -1145,9 +1319,14 @@ static int smack_file_receive(struct file *file) | |||
1145 | */ | 1319 | */ |
1146 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 1320 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
1147 | { | 1321 | { |
1148 | cred->security = kzalloc(sizeof(struct task_smack), gfp); | 1322 | struct task_smack *tsp; |
1149 | if (cred->security == NULL) | 1323 | |
1324 | tsp = new_task_smack(NULL, NULL, gfp); | ||
1325 | if (tsp == NULL) | ||
1150 | return -ENOMEM; | 1326 | return -ENOMEM; |
1327 | |||
1328 | cred->security = tsp; | ||
1329 | |||
1151 | return 0; | 1330 | return 0; |
1152 | } | 1331 | } |
1153 | 1332 | ||
@@ -1156,13 +1335,24 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | |||
1156 | * smack_cred_free - "free" task-level security credentials | 1335 | * smack_cred_free - "free" task-level security credentials |
1157 | * @cred: the credentials in question | 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 | static void smack_cred_free(struct cred *cred) | 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, | |||
1178 | { | 1368 | { |
1179 | struct task_smack *old_tsp = old->security; | 1369 | struct task_smack *old_tsp = old->security; |
1180 | struct task_smack *new_tsp; | 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 | if (new_tsp == NULL) | 1374 | if (new_tsp == NULL) |
1184 | return -ENOMEM; | 1375 | return -ENOMEM; |
1185 | 1376 | ||
1186 | new_tsp->smk_task = old_tsp->smk_task; | 1377 | rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp); |
1187 | new_tsp->smk_forked = old_tsp->smk_task; | 1378 | if (rc != 0) |
1379 | return rc; | ||
1380 | |||
1188 | new->security = new_tsp; | 1381 | new->security = new_tsp; |
1189 | return 0; | 1382 | return 0; |
1190 | } | 1383 | } |
@@ -1203,6 +1396,11 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) | |||
1203 | 1396 | ||
1204 | new_tsp->smk_task = old_tsp->smk_task; | 1397 | new_tsp->smk_task = old_tsp->smk_task; |
1205 | new_tsp->smk_forked = old_tsp->smk_task; | 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) | |||
2419 | } | 2617 | } |
2420 | } | 2618 | } |
2421 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); | 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 | dput(dp); | 2622 | dput(dp); |
2424 | break; | 2623 | break; |
@@ -2478,6 +2677,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
2478 | static int smack_setprocattr(struct task_struct *p, char *name, | 2677 | static int smack_setprocattr(struct task_struct *p, char *name, |
2479 | void *value, size_t size) | 2678 | void *value, size_t size) |
2480 | { | 2679 | { |
2680 | int rc; | ||
2481 | struct task_smack *tsp; | 2681 | struct task_smack *tsp; |
2482 | struct task_smack *oldtsp; | 2682 | struct task_smack *oldtsp; |
2483 | struct cred *new; | 2683 | struct cred *new; |
@@ -2513,13 +2713,16 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2513 | new = prepare_creds(); | 2713 | new = prepare_creds(); |
2514 | if (new == NULL) | 2714 | if (new == NULL) |
2515 | return -ENOMEM; | 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 | if (tsp == NULL) { | 2718 | if (tsp == NULL) { |
2518 | kfree(new); | 2719 | kfree(new); |
2519 | return -ENOMEM; | 2720 | return -ENOMEM; |
2520 | } | 2721 | } |
2521 | tsp->smk_task = newsmack; | 2722 | rc = smk_copy_rules(&tsp->smk_rules, &oldtsp->smk_rules, GFP_KERNEL); |
2522 | tsp->smk_forked = oldtsp->smk_forked; | 2723 | if (rc != 0) |
2724 | return rc; | ||
2725 | |||
2523 | new->security = tsp; | 2726 | new->security = tsp; |
2524 | commit_creds(new); | 2727 | commit_creds(new); |
2525 | return size; | 2728 | return size; |
@@ -3221,6 +3424,7 @@ struct security_operations smack_ops = { | |||
3221 | .file_ioctl = smack_file_ioctl, | 3424 | .file_ioctl = smack_file_ioctl, |
3222 | .file_lock = smack_file_lock, | 3425 | .file_lock = smack_file_lock, |
3223 | .file_fcntl = smack_file_fcntl, | 3426 | .file_fcntl = smack_file_fcntl, |
3427 | .file_mmap = smack_file_mmap, | ||
3224 | .file_set_fowner = smack_file_set_fowner, | 3428 | .file_set_fowner = smack_file_set_fowner, |
3225 | .file_send_sigiotask = smack_file_send_sigiotask, | 3429 | .file_send_sigiotask = smack_file_send_sigiotask, |
3226 | .file_receive = smack_file_receive, | 3430 | .file_receive = smack_file_receive, |
@@ -3334,23 +3538,20 @@ static __init int smack_init(void) | |||
3334 | struct cred *cred; | 3538 | struct cred *cred; |
3335 | struct task_smack *tsp; | 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 | if (tsp == NULL) | 3546 | if (tsp == NULL) |
3339 | return -ENOMEM; | 3547 | return -ENOMEM; |
3340 | 3548 | ||
3341 | if (!security_module_enable(&smack_ops)) { | ||
3342 | kfree(tsp); | ||
3343 | return 0; | ||
3344 | } | ||
3345 | |||
3346 | printk(KERN_INFO "Smack: Initializing.\n"); | 3549 | printk(KERN_INFO "Smack: Initializing.\n"); |
3347 | 3550 | ||
3348 | /* | 3551 | /* |
3349 | * Set the security state for the initial task. | 3552 | * Set the security state for the initial task. |
3350 | */ | 3553 | */ |
3351 | cred = (struct cred *) current->cred; | 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 | cred->security = tsp; | 3555 | cred->security = tsp; |
3355 | 3556 | ||
3356 | /* initialize the smack_know_list */ | 3557 | /* initialize the smack_know_list */ |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 362d5eda948b..90d1bbaaa6f3 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -43,6 +43,7 @@ enum smk_inos { | |||
43 | SMK_NETLBLADDR = 8, /* single label hosts */ | 43 | SMK_NETLBLADDR = 8, /* single label hosts */ |
44 | SMK_ONLYCAP = 9, /* the only "capable" label */ | 44 | SMK_ONLYCAP = 9, /* the only "capable" label */ |
45 | SMK_LOGGING = 10, /* logging */ | 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) | |||
135 | #define SMK_NETLBLADDRMIN 9 | 136 | #define SMK_NETLBLADDRMIN 9 |
136 | #define SMK_NETLBLADDRMAX 42 | 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 | * smk_set_access - add a rule to the rule list | 140 | * smk_set_access - add a rule to the rule list |
217 | * @srp: the new rule to add | 141 | * @srp: the new rule to add |
142 | * @rule_list: the list of rules | ||
143 | * @rule_lock: the rule list lock | ||
218 | * | 144 | * |
219 | * Looks through the current subject/object/access list for | 145 | * Looks through the current subject/object/access list for |
220 | * the subject/object pair and replaces the access that was | 146 | * the subject/object pair and replaces the access that was |
221 | * there. If the pair isn't found add it with the specified | 147 | * there. If the pair isn't found add it with the specified |
222 | * access. | 148 | * access. |
223 | * | 149 | * |
150 | * Returns 1 if a rule was found to exist already, 0 if it is new | ||
224 | * Returns 0 if nothing goes wrong or -ENOMEM if it fails | 151 | * Returns 0 if nothing goes wrong or -ENOMEM if it fails |
225 | * during the allocation of the new pair to add. | 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 | struct smack_rule *sp; | 157 | struct smack_rule *sp; |
230 | int ret = 0; | 158 | int found = 0; |
231 | int found; | ||
232 | mutex_lock(&smack_list_lock); | ||
233 | 159 | ||
234 | found = 0; | 160 | mutex_lock(rule_lock); |
235 | list_for_each_entry_rcu(sp, &smack_rule_list, list) { | 161 | |
162 | list_for_each_entry_rcu(sp, rule_list, list) { | ||
236 | if (sp->smk_subject == srp->smk_subject && | 163 | if (sp->smk_subject == srp->smk_subject && |
237 | sp->smk_object == srp->smk_object) { | 164 | sp->smk_object == srp->smk_object) { |
238 | found = 1; | 165 | found = 1; |
@@ -241,19 +168,21 @@ static int smk_set_access(struct smack_rule *srp) | |||
241 | } | 168 | } |
242 | } | 169 | } |
243 | if (found == 0) | 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 | * @file: file pointer, not actually used | 180 | * @file: file pointer, not actually used |
254 | * @buf: where to get the data from | 181 | * @buf: where to get the data from |
255 | * @count: bytes sent | 182 | * @count: bytes sent |
256 | * @ppos: where to start - must be 0 | 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 | * Get one smack access rule from above. | 187 | * Get one smack access rule from above. |
259 | * The format is exactly: | 188 | * The format is exactly: |
@@ -263,21 +192,19 @@ static int smk_set_access(struct smack_rule *srp) | |||
263 | * | 192 | * |
264 | * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes. | 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, | 195 | static ssize_t smk_write_load_list(struct file *file, const char __user *buf, |
267 | size_t count, loff_t *ppos) | 196 | size_t count, loff_t *ppos, |
197 | struct list_head *rule_list, | ||
198 | struct mutex *rule_lock) | ||
268 | { | 199 | { |
269 | struct smack_rule *rule; | 200 | struct smack_rule *rule; |
270 | char *data; | 201 | char *data; |
271 | int rc = -EINVAL; | 202 | int rc = -EINVAL; |
272 | 203 | ||
273 | /* | 204 | /* |
274 | * Must have privilege. | ||
275 | * No partial writes. | 205 | * No partial writes. |
276 | * Enough data must be present. | 206 | * Enough data must be present. |
277 | */ | 207 | */ |
278 | if (!capable(CAP_MAC_ADMIN)) | ||
279 | return -EPERM; | ||
280 | |||
281 | if (*ppos != 0) | 208 | if (*ppos != 0) |
282 | return -EINVAL; | 209 | return -EINVAL; |
283 | /* | 210 | /* |
@@ -372,11 +299,13 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf, | |||
372 | goto out_free_rule; | 299 | goto out_free_rule; |
373 | } | 300 | } |
374 | 301 | ||
375 | rc = smk_set_access(rule); | 302 | rc = count; |
376 | 303 | /* | |
377 | if (!rc) | 304 | * smk_set_access returns true if there was already a rule |
378 | rc = count; | 305 | * for the subject/object pair, and false if it was new. |
379 | goto out; | 306 | */ |
307 | if (!smk_set_access(rule, rule_list, rule_lock)) | ||
308 | goto out; | ||
380 | 309 | ||
381 | out_free_rule: | 310 | out_free_rule: |
382 | kfree(rule); | 311 | kfree(rule); |
@@ -385,6 +314,108 @@ out: | |||
385 | return rc; | 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 | static const struct file_operations smk_load_ops = { | 419 | static const struct file_operations smk_load_ops = { |
389 | .open = smk_open_load, | 420 | .open = smk_open_load, |
390 | .read = seq_read, | 421 | .read = seq_read, |
@@ -1288,6 +1319,112 @@ static const struct file_operations smk_logging_ops = { | |||
1288 | .write = smk_write_logging, | 1319 | .write = smk_write_logging, |
1289 | .llseek = default_llseek, | 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 | * smk_fill_super - fill the /smackfs superblock | 1429 | * smk_fill_super - fill the /smackfs superblock |
1293 | * @sb: the empty superblock | 1430 | * @sb: the empty superblock |
@@ -1304,23 +1441,26 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
1304 | struct inode *root_inode; | 1441 | struct inode *root_inode; |
1305 | 1442 | ||
1306 | static struct tree_descr smack_files[] = { | 1443 | static struct tree_descr smack_files[] = { |
1307 | [SMK_LOAD] = | 1444 | [SMK_LOAD] = { |
1308 | {"load", &smk_load_ops, S_IRUGO|S_IWUSR}, | 1445 | "load", &smk_load_ops, S_IRUGO|S_IWUSR}, |
1309 | [SMK_CIPSO] = | 1446 | [SMK_CIPSO] = { |
1310 | {"cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR}, | 1447 | "cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR}, |
1311 | [SMK_DOI] = | 1448 | [SMK_DOI] = { |
1312 | {"doi", &smk_doi_ops, S_IRUGO|S_IWUSR}, | 1449 | "doi", &smk_doi_ops, S_IRUGO|S_IWUSR}, |
1313 | [SMK_DIRECT] = | 1450 | [SMK_DIRECT] = { |
1314 | {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, | 1451 | "direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, |
1315 | [SMK_AMBIENT] = | 1452 | [SMK_AMBIENT] = { |
1316 | {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, | 1453 | "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, |
1317 | [SMK_NETLBLADDR] = | 1454 | [SMK_NETLBLADDR] = { |
1318 | {"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR}, | 1455 | "netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR}, |
1319 | [SMK_ONLYCAP] = | 1456 | [SMK_ONLYCAP] = { |
1320 | {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, | 1457 | "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, |
1321 | [SMK_LOGGING] = | 1458 | [SMK_LOGGING] = { |
1322 | {"logging", &smk_logging_ops, S_IRUGO|S_IWUSR}, | 1459 | "logging", &smk_logging_ops, S_IRUGO|S_IWUSR}, |
1323 | /* last one */ {""} | 1460 | [SMK_LOAD_SELF] = { |
1461 | "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO}, | ||
1462 | /* last one */ | ||
1463 | {""} | ||
1324 | }; | 1464 | }; |
1325 | 1465 | ||
1326 | rc = simple_fill_super(sb, SMACK_MAGIC, smack_files); | 1466 | rc = simple_fill_super(sb, SMACK_MAGIC, smack_files); |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 9d32f182301e..cb09f1fce910 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -927,7 +927,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
927 | struct path *path, const int flag) | 927 | struct path *path, const int flag) |
928 | { | 928 | { |
929 | const u8 acc_mode = ACC_MODE(flag); | 929 | const u8 acc_mode = ACC_MODE(flag); |
930 | int error = -ENOMEM; | 930 | int error = 0; |
931 | struct tomoyo_path_info buf; | 931 | struct tomoyo_path_info buf; |
932 | struct tomoyo_request_info r; | 932 | struct tomoyo_request_info r; |
933 | int idx; | 933 | int idx; |
@@ -938,9 +938,6 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
938 | buf.name = NULL; | 938 | buf.name = NULL; |
939 | r.mode = TOMOYO_CONFIG_DISABLED; | 939 | r.mode = TOMOYO_CONFIG_DISABLED; |
940 | idx = tomoyo_read_lock(); | 940 | idx = tomoyo_read_lock(); |
941 | if (!tomoyo_get_realpath(&buf, path)) | ||
942 | goto out; | ||
943 | error = 0; | ||
944 | /* | 941 | /* |
945 | * If the filename is specified by "deny_rewrite" keyword, | 942 | * If the filename is specified by "deny_rewrite" keyword, |
946 | * we need to check "allow_rewrite" permission when the filename is not | 943 | * we need to check "allow_rewrite" permission when the filename is not |