diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-24 16:38:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-24 16:38:19 -0400 |
commit | b0ca118dbacbc6c35e15f216e25e95cca7aedf5b (patch) | |
tree | 6c61c91ff0174c8774d4010b892ecf0bed560910 | |
parent | 2bb732cdb48d271ff7a910260ffb851fb4bc8a28 (diff) | |
parent | b7b57551bbda1390959207f79f2038aa7adb72ae (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (43 commits)
TOMOYO: Fix wrong domainname validation.
SELINUX: add /sys/fs/selinux mount point to put selinuxfs
CRED: Fix load_flat_shared_library() to initialise bprm correctly
SELinux: introduce path_has_perm
flex_array: allow 0 length elements
flex_arrays: allow zero length flex arrays
flex_array: flex_array_prealloc takes a number of elements, not an end
SELinux: pass last path component in may_create
SELinux: put name based create rules in a hashtable
SELinux: generic hashtab entry counter
SELinux: calculate and print hashtab stats with a generic function
SELinux: skip filename trans rules if ttype does not match parent dir
SELinux: rename filename_compute_type argument to *type instead of *con
SELinux: fix comment to state filename_compute_type takes an objname not a qstr
SMACK: smack_file_lock can use the struct path
LSM: separate LSM_AUDIT_DATA_DENTRY from LSM_AUDIT_DATA_PATH
LSM: split LSM_AUDIT_DATA_FS into _PATH and _INODE
SELINUX: Make selinux cache VFS RCU walks safe
SECURITY: Move exec_permission RCU checks into security modules
SELinux: security_read_policy should take a size_t not ssize_t
...
39 files changed, 603 insertions, 284 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index b64825ddaf32..98c324b07a16 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5592,10 +5592,11 @@ M: James Morris <jmorris@namei.org> | |||
5592 | M: Eric Paris <eparis@parisplace.org> | 5592 | M: Eric Paris <eparis@parisplace.org> |
5593 | L: selinux@tycho.nsa.gov (subscribers-only, general discussion) | 5593 | L: selinux@tycho.nsa.gov (subscribers-only, general discussion) |
5594 | W: http://selinuxproject.org | 5594 | W: http://selinuxproject.org |
5595 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git | 5595 | T: git git://git.infradead.org/users/eparis/selinux.git |
5596 | S: Supported | 5596 | S: Supported |
5597 | F: include/linux/selinux* | 5597 | F: include/linux/selinux* |
5598 | F: security/selinux/ | 5598 | F: security/selinux/ |
5599 | F: scripts/selinux/ | ||
5599 | 5600 | ||
5600 | APPARMOR SECURITY MODULE | 5601 | APPARMOR SECURITY MODULE |
5601 | M: John Johansen <john.johansen@canonical.com> | 5602 | M: John Johansen <john.johansen@canonical.com> |
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 397d3057d336..1bffbe0ed778 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -820,6 +820,8 @@ static int load_flat_shared_library(int id, struct lib_info *libs) | |||
820 | int res; | 820 | int res; |
821 | char buf[16]; | 821 | char buf[16]; |
822 | 822 | ||
823 | memset(&bprm, 0, sizeof(bprm)); | ||
824 | |||
823 | /* Create the file name */ | 825 | /* Create the file name */ |
824 | sprintf(buf, "/lib/lib%d.so", id); | 826 | sprintf(buf, "/lib/lib%d.so", id); |
825 | 827 | ||
@@ -835,6 +837,12 @@ static int load_flat_shared_library(int id, struct lib_info *libs) | |||
835 | if (!bprm.cred) | 837 | if (!bprm.cred) |
836 | goto out; | 838 | goto out; |
837 | 839 | ||
840 | /* We don't really care about recalculating credentials at this point | ||
841 | * as we're past the point of no return and are dealing with shared | ||
842 | * libraries. | ||
843 | */ | ||
844 | bprm.cred_prepared = 1; | ||
845 | |||
838 | res = prepare_binprm(&bprm); | 846 | res = prepare_binprm(&bprm); |
839 | 847 | ||
840 | if (!IS_ERR_VALUE(res)) | 848 | if (!IS_ERR_VALUE(res)) |
diff --git a/include/linux/capability.h b/include/linux/capability.h index 4554db0cde86..c42112350003 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h | |||
@@ -417,7 +417,6 @@ extern const kernel_cap_t __cap_init_eff_set; | |||
417 | 417 | ||
418 | # define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }}) | 418 | # define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }}) |
419 | # define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }}) | 419 | # define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }}) |
420 | # define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }}) | ||
421 | # define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ | 420 | # define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ |
422 | | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \ | 421 | | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \ |
423 | CAP_FS_MASK_B1 } }) | 422 | CAP_FS_MASK_B1 } }) |
@@ -427,11 +426,7 @@ extern const kernel_cap_t __cap_init_eff_set; | |||
427 | 426 | ||
428 | #endif /* _KERNEL_CAPABILITY_U32S != 2 */ | 427 | #endif /* _KERNEL_CAPABILITY_U32S != 2 */ |
429 | 428 | ||
430 | #define CAP_INIT_INH_SET CAP_EMPTY_SET | ||
431 | |||
432 | # define cap_clear(c) do { (c) = __cap_empty_set; } while (0) | 429 | # define cap_clear(c) do { (c) = __cap_empty_set; } while (0) |
433 | # define cap_set_full(c) do { (c) = __cap_full_set; } while (0) | ||
434 | # define cap_set_init_eff(c) do { (c) = __cap_init_eff_set; } while (0) | ||
435 | 430 | ||
436 | #define cap_raise(c, flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag)) | 431 | #define cap_raise(c, flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag)) |
437 | #define cap_lower(c, flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag)) | 432 | #define cap_lower(c, flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag)) |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 689496bb6654..bafc58c00fc3 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -83,13 +83,6 @@ extern struct group_info init_groups; | |||
83 | #define INIT_IDS | 83 | #define INIT_IDS |
84 | #endif | 84 | #endif |
85 | 85 | ||
86 | /* | ||
87 | * Because of the reduced scope of CAP_SETPCAP when filesystem | ||
88 | * capabilities are in effect, it is safe to allow CAP_SETPCAP to | ||
89 | * be available in the default configuration. | ||
90 | */ | ||
91 | # define CAP_INIT_BSET CAP_FULL_SET | ||
92 | |||
93 | #ifdef CONFIG_RCU_BOOST | 86 | #ifdef CONFIG_RCU_BOOST |
94 | #define INIT_TASK_RCU_BOOST() \ | 87 | #define INIT_TASK_RCU_BOOST() \ |
95 | .rcu_boost_mutex = NULL, | 88 | .rcu_boost_mutex = NULL, |
diff --git a/include/linux/key.h b/include/linux/key.h index b2bb01719561..ef19b99aff98 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -276,6 +276,19 @@ static inline key_serial_t key_serial(struct key *key) | |||
276 | return key ? key->serial : 0; | 276 | return key ? key->serial : 0; |
277 | } | 277 | } |
278 | 278 | ||
279 | /** | ||
280 | * key_is_instantiated - Determine if a key has been positively instantiated | ||
281 | * @key: The key to check. | ||
282 | * | ||
283 | * Return true if the specified key has been positively instantiated, false | ||
284 | * otherwise. | ||
285 | */ | ||
286 | static inline bool key_is_instantiated(const struct key *key) | ||
287 | { | ||
288 | return test_bit(KEY_FLAG_INSTANTIATED, &key->flags) && | ||
289 | !test_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
290 | } | ||
291 | |||
279 | #define rcu_dereference_key(KEY) \ | 292 | #define rcu_dereference_key(KEY) \ |
280 | (rcu_dereference_protected((KEY)->payload.rcudata, \ | 293 | (rcu_dereference_protected((KEY)->payload.rcudata, \ |
281 | rwsem_is_locked(&((struct key *)(KEY))->sem))) | 294 | rwsem_is_locked(&((struct key *)(KEY))->sem))) |
diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 310231823852..d4a5c84c503d 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/compiler.h> | 25 | #include <linux/compiler.h> |
26 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
27 | #include <linux/sysctl.h> | ||
27 | 28 | ||
28 | #define KMOD_PATH_LEN 256 | 29 | #define KMOD_PATH_LEN 256 |
29 | 30 | ||
@@ -109,6 +110,8 @@ call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait) | |||
109 | NULL, NULL, NULL); | 110 | NULL, NULL, NULL); |
110 | } | 111 | } |
111 | 112 | ||
113 | extern struct ctl_table usermodehelper_table[]; | ||
114 | |||
112 | extern void usermodehelper_init(void); | 115 | extern void usermodehelper_init(void); |
113 | 116 | ||
114 | extern int usermodehelper_disable(void); | 117 | extern int usermodehelper_disable(void); |
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h index 112a55033352..88e78dedc2e8 100644 --- a/include/linux/lsm_audit.h +++ b/include/linux/lsm_audit.h | |||
@@ -27,7 +27,7 @@ | |||
27 | /* Auxiliary data to use in generating the audit record. */ | 27 | /* Auxiliary data to use in generating the audit record. */ |
28 | struct common_audit_data { | 28 | struct common_audit_data { |
29 | char type; | 29 | char type; |
30 | #define LSM_AUDIT_DATA_FS 1 | 30 | #define LSM_AUDIT_DATA_PATH 1 |
31 | #define LSM_AUDIT_DATA_NET 2 | 31 | #define LSM_AUDIT_DATA_NET 2 |
32 | #define LSM_AUDIT_DATA_CAP 3 | 32 | #define LSM_AUDIT_DATA_CAP 3 |
33 | #define LSM_AUDIT_DATA_IPC 4 | 33 | #define LSM_AUDIT_DATA_IPC 4 |
@@ -35,12 +35,13 @@ struct common_audit_data { | |||
35 | #define LSM_AUDIT_DATA_KEY 6 | 35 | #define LSM_AUDIT_DATA_KEY 6 |
36 | #define LSM_AUDIT_DATA_NONE 7 | 36 | #define LSM_AUDIT_DATA_NONE 7 |
37 | #define LSM_AUDIT_DATA_KMOD 8 | 37 | #define LSM_AUDIT_DATA_KMOD 8 |
38 | #define LSM_AUDIT_DATA_INODE 9 | ||
39 | #define LSM_AUDIT_DATA_DENTRY 10 | ||
38 | struct task_struct *tsk; | 40 | struct task_struct *tsk; |
39 | union { | 41 | union { |
40 | struct { | 42 | struct path path; |
41 | struct path path; | 43 | struct dentry *dentry; |
42 | struct inode *inode; | 44 | struct inode *inode; |
43 | } fs; | ||
44 | struct { | 45 | struct { |
45 | int netif; | 46 | int netif; |
46 | struct sock *sk; | 47 | struct sock *sk; |
diff --git a/kernel/capability.c b/kernel/capability.c index 32a80e08ff4b..283c529f8b1c 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
@@ -22,12 +22,8 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET; | 24 | const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET; |
25 | const kernel_cap_t __cap_full_set = CAP_FULL_SET; | ||
26 | const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET; | ||
27 | 25 | ||
28 | EXPORT_SYMBOL(__cap_empty_set); | 26 | EXPORT_SYMBOL(__cap_empty_set); |
29 | EXPORT_SYMBOL(__cap_full_set); | ||
30 | EXPORT_SYMBOL(__cap_init_eff_set); | ||
31 | 27 | ||
32 | int file_caps_enabled = 1; | 28 | int file_caps_enabled = 1; |
33 | 29 | ||
diff --git a/kernel/cred.c b/kernel/cred.c index 8093c16b84b1..e12c8af793f8 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
@@ -49,10 +49,10 @@ struct cred init_cred = { | |||
49 | .magic = CRED_MAGIC, | 49 | .magic = CRED_MAGIC, |
50 | #endif | 50 | #endif |
51 | .securebits = SECUREBITS_DEFAULT, | 51 | .securebits = SECUREBITS_DEFAULT, |
52 | .cap_inheritable = CAP_INIT_INH_SET, | 52 | .cap_inheritable = CAP_EMPTY_SET, |
53 | .cap_permitted = CAP_FULL_SET, | 53 | .cap_permitted = CAP_FULL_SET, |
54 | .cap_effective = CAP_INIT_EFF_SET, | 54 | .cap_effective = CAP_FULL_SET, |
55 | .cap_bset = CAP_INIT_BSET, | 55 | .cap_bset = CAP_FULL_SET, |
56 | .user = INIT_USER, | 56 | .user = INIT_USER, |
57 | .user_ns = &init_user_ns, | 57 | .user_ns = &init_user_ns, |
58 | .group_info = &init_groups, | 58 | .group_info = &init_groups, |
diff --git a/kernel/kmod.c b/kernel/kmod.c index 5ae0ff38425f..ad6a81c58b44 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/kmod.h> | 25 | #include <linux/kmod.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/completion.h> | 27 | #include <linux/completion.h> |
28 | #include <linux/cred.h> | ||
28 | #include <linux/file.h> | 29 | #include <linux/file.h> |
29 | #include <linux/fdtable.h> | 30 | #include <linux/fdtable.h> |
30 | #include <linux/workqueue.h> | 31 | #include <linux/workqueue.h> |
@@ -43,6 +44,13 @@ extern int max_threads; | |||
43 | 44 | ||
44 | static struct workqueue_struct *khelper_wq; | 45 | static struct workqueue_struct *khelper_wq; |
45 | 46 | ||
47 | #define CAP_BSET (void *)1 | ||
48 | #define CAP_PI (void *)2 | ||
49 | |||
50 | static kernel_cap_t usermodehelper_bset = CAP_FULL_SET; | ||
51 | static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET; | ||
52 | static DEFINE_SPINLOCK(umh_sysctl_lock); | ||
53 | |||
46 | #ifdef CONFIG_MODULES | 54 | #ifdef CONFIG_MODULES |
47 | 55 | ||
48 | /* | 56 | /* |
@@ -132,6 +140,7 @@ EXPORT_SYMBOL(__request_module); | |||
132 | static int ____call_usermodehelper(void *data) | 140 | static int ____call_usermodehelper(void *data) |
133 | { | 141 | { |
134 | struct subprocess_info *sub_info = data; | 142 | struct subprocess_info *sub_info = data; |
143 | struct cred *new; | ||
135 | int retval; | 144 | int retval; |
136 | 145 | ||
137 | spin_lock_irq(¤t->sighand->siglock); | 146 | spin_lock_irq(¤t->sighand->siglock); |
@@ -153,6 +162,19 @@ static int ____call_usermodehelper(void *data) | |||
153 | goto fail; | 162 | goto fail; |
154 | } | 163 | } |
155 | 164 | ||
165 | retval = -ENOMEM; | ||
166 | new = prepare_kernel_cred(current); | ||
167 | if (!new) | ||
168 | goto fail; | ||
169 | |||
170 | spin_lock(&umh_sysctl_lock); | ||
171 | new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset); | ||
172 | new->cap_inheritable = cap_intersect(usermodehelper_inheritable, | ||
173 | new->cap_inheritable); | ||
174 | spin_unlock(&umh_sysctl_lock); | ||
175 | |||
176 | commit_creds(new); | ||
177 | |||
156 | retval = kernel_execve(sub_info->path, | 178 | retval = kernel_execve(sub_info->path, |
157 | (const char *const *)sub_info->argv, | 179 | (const char *const *)sub_info->argv, |
158 | (const char *const *)sub_info->envp); | 180 | (const char *const *)sub_info->envp); |
@@ -420,6 +442,84 @@ unlock: | |||
420 | } | 442 | } |
421 | EXPORT_SYMBOL(call_usermodehelper_exec); | 443 | EXPORT_SYMBOL(call_usermodehelper_exec); |
422 | 444 | ||
445 | static int proc_cap_handler(struct ctl_table *table, int write, | ||
446 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
447 | { | ||
448 | struct ctl_table t; | ||
449 | unsigned long cap_array[_KERNEL_CAPABILITY_U32S]; | ||
450 | kernel_cap_t new_cap; | ||
451 | int err, i; | ||
452 | |||
453 | if (write && (!capable(CAP_SETPCAP) || | ||
454 | !capable(CAP_SYS_MODULE))) | ||
455 | return -EPERM; | ||
456 | |||
457 | /* | ||
458 | * convert from the global kernel_cap_t to the ulong array to print to | ||
459 | * userspace if this is a read. | ||
460 | */ | ||
461 | spin_lock(&umh_sysctl_lock); | ||
462 | for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++) { | ||
463 | if (table->data == CAP_BSET) | ||
464 | cap_array[i] = usermodehelper_bset.cap[i]; | ||
465 | else if (table->data == CAP_PI) | ||
466 | cap_array[i] = usermodehelper_inheritable.cap[i]; | ||
467 | else | ||
468 | BUG(); | ||
469 | } | ||
470 | spin_unlock(&umh_sysctl_lock); | ||
471 | |||
472 | t = *table; | ||
473 | t.data = &cap_array; | ||
474 | |||
475 | /* | ||
476 | * actually read or write and array of ulongs from userspace. Remember | ||
477 | * these are least significant 32 bits first | ||
478 | */ | ||
479 | err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos); | ||
480 | if (err < 0) | ||
481 | return err; | ||
482 | |||
483 | /* | ||
484 | * convert from the sysctl array of ulongs to the kernel_cap_t | ||
485 | * internal representation | ||
486 | */ | ||
487 | for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++) | ||
488 | new_cap.cap[i] = cap_array[i]; | ||
489 | |||
490 | /* | ||
491 | * Drop everything not in the new_cap (but don't add things) | ||
492 | */ | ||
493 | spin_lock(&umh_sysctl_lock); | ||
494 | if (write) { | ||
495 | if (table->data == CAP_BSET) | ||
496 | usermodehelper_bset = cap_intersect(usermodehelper_bset, new_cap); | ||
497 | if (table->data == CAP_PI) | ||
498 | usermodehelper_inheritable = cap_intersect(usermodehelper_inheritable, new_cap); | ||
499 | } | ||
500 | spin_unlock(&umh_sysctl_lock); | ||
501 | |||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | struct ctl_table usermodehelper_table[] = { | ||
506 | { | ||
507 | .procname = "bset", | ||
508 | .data = CAP_BSET, | ||
509 | .maxlen = _KERNEL_CAPABILITY_U32S * sizeof(unsigned long), | ||
510 | .mode = 0600, | ||
511 | .proc_handler = proc_cap_handler, | ||
512 | }, | ||
513 | { | ||
514 | .procname = "inheritable", | ||
515 | .data = CAP_PI, | ||
516 | .maxlen = _KERNEL_CAPABILITY_U32S * sizeof(unsigned long), | ||
517 | .mode = 0600, | ||
518 | .proc_handler = proc_cap_handler, | ||
519 | }, | ||
520 | { } | ||
521 | }; | ||
522 | |||
423 | void __init usermodehelper_init(void) | 523 | void __init usermodehelper_init(void) |
424 | { | 524 | { |
425 | khelper_wq = create_singlethread_workqueue("khelper"); | 525 | khelper_wq = create_singlethread_workqueue("khelper"); |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3dd0c46fa3bb..4bffd62c2f13 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/kprobes.h> | 56 | #include <linux/kprobes.h> |
57 | #include <linux/pipe_fs_i.h> | 57 | #include <linux/pipe_fs_i.h> |
58 | #include <linux/oom.h> | 58 | #include <linux/oom.h> |
59 | #include <linux/kmod.h> | ||
59 | 60 | ||
60 | #include <asm/uaccess.h> | 61 | #include <asm/uaccess.h> |
61 | #include <asm/processor.h> | 62 | #include <asm/processor.h> |
@@ -616,6 +617,11 @@ static struct ctl_table kern_table[] = { | |||
616 | .child = random_table, | 617 | .child = random_table, |
617 | }, | 618 | }, |
618 | { | 619 | { |
620 | .procname = "usermodehelper", | ||
621 | .mode = 0555, | ||
622 | .child = usermodehelper_table, | ||
623 | }, | ||
624 | { | ||
619 | .procname = "overflowuid", | 625 | .procname = "overflowuid", |
620 | .data = &overflowuid, | 626 | .data = &overflowuid, |
621 | .maxlen = sizeof(int), | 627 | .maxlen = sizeof(int), |
diff --git a/lib/flex_array.c b/lib/flex_array.c index 854b57bd7d9d..cab7621f98aa 100644 --- a/lib/flex_array.c +++ b/lib/flex_array.c | |||
@@ -88,8 +88,11 @@ struct flex_array *flex_array_alloc(int element_size, unsigned int total, | |||
88 | gfp_t flags) | 88 | gfp_t flags) |
89 | { | 89 | { |
90 | struct flex_array *ret; | 90 | struct flex_array *ret; |
91 | int max_size = FLEX_ARRAY_NR_BASE_PTRS * | 91 | int max_size = 0; |
92 | FLEX_ARRAY_ELEMENTS_PER_PART(element_size); | 92 | |
93 | if (element_size) | ||
94 | max_size = FLEX_ARRAY_NR_BASE_PTRS * | ||
95 | FLEX_ARRAY_ELEMENTS_PER_PART(element_size); | ||
93 | 96 | ||
94 | /* max_size will end up 0 if element_size > PAGE_SIZE */ | 97 | /* max_size will end up 0 if element_size > PAGE_SIZE */ |
95 | if (total > max_size) | 98 | if (total > max_size) |
@@ -183,15 +186,18 @@ __fa_get_part(struct flex_array *fa, int part_nr, gfp_t flags) | |||
183 | int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src, | 186 | int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src, |
184 | gfp_t flags) | 187 | gfp_t flags) |
185 | { | 188 | { |
186 | int part_nr = fa_element_to_part_nr(fa, element_nr); | 189 | int part_nr; |
187 | struct flex_array_part *part; | 190 | struct flex_array_part *part; |
188 | void *dst; | 191 | void *dst; |
189 | 192 | ||
190 | if (element_nr >= fa->total_nr_elements) | 193 | if (element_nr >= fa->total_nr_elements) |
191 | return -ENOSPC; | 194 | return -ENOSPC; |
195 | if (!fa->element_size) | ||
196 | return 0; | ||
192 | if (elements_fit_in_base(fa)) | 197 | if (elements_fit_in_base(fa)) |
193 | part = (struct flex_array_part *)&fa->parts[0]; | 198 | part = (struct flex_array_part *)&fa->parts[0]; |
194 | else { | 199 | else { |
200 | part_nr = fa_element_to_part_nr(fa, element_nr); | ||
195 | part = __fa_get_part(fa, part_nr, flags); | 201 | part = __fa_get_part(fa, part_nr, flags); |
196 | if (!part) | 202 | if (!part) |
197 | return -ENOMEM; | 203 | return -ENOMEM; |
@@ -211,15 +217,18 @@ EXPORT_SYMBOL(flex_array_put); | |||
211 | */ | 217 | */ |
212 | int flex_array_clear(struct flex_array *fa, unsigned int element_nr) | 218 | int flex_array_clear(struct flex_array *fa, unsigned int element_nr) |
213 | { | 219 | { |
214 | int part_nr = fa_element_to_part_nr(fa, element_nr); | 220 | int part_nr; |
215 | struct flex_array_part *part; | 221 | struct flex_array_part *part; |
216 | void *dst; | 222 | void *dst; |
217 | 223 | ||
218 | if (element_nr >= fa->total_nr_elements) | 224 | if (element_nr >= fa->total_nr_elements) |
219 | return -ENOSPC; | 225 | return -ENOSPC; |
226 | if (!fa->element_size) | ||
227 | return 0; | ||
220 | if (elements_fit_in_base(fa)) | 228 | if (elements_fit_in_base(fa)) |
221 | part = (struct flex_array_part *)&fa->parts[0]; | 229 | part = (struct flex_array_part *)&fa->parts[0]; |
222 | else { | 230 | else { |
231 | part_nr = fa_element_to_part_nr(fa, element_nr); | ||
223 | part = fa->parts[part_nr]; | 232 | part = fa->parts[part_nr]; |
224 | if (!part) | 233 | if (!part) |
225 | return -EINVAL; | 234 | return -EINVAL; |
@@ -264,6 +273,8 @@ int flex_array_prealloc(struct flex_array *fa, unsigned int start, | |||
264 | 273 | ||
265 | if (end >= fa->total_nr_elements) | 274 | if (end >= fa->total_nr_elements) |
266 | return -ENOSPC; | 275 | return -ENOSPC; |
276 | if (!fa->element_size) | ||
277 | return 0; | ||
267 | if (elements_fit_in_base(fa)) | 278 | if (elements_fit_in_base(fa)) |
268 | return 0; | 279 | return 0; |
269 | start_part = fa_element_to_part_nr(fa, start); | 280 | start_part = fa_element_to_part_nr(fa, start); |
@@ -291,14 +302,17 @@ EXPORT_SYMBOL(flex_array_prealloc); | |||
291 | */ | 302 | */ |
292 | void *flex_array_get(struct flex_array *fa, unsigned int element_nr) | 303 | void *flex_array_get(struct flex_array *fa, unsigned int element_nr) |
293 | { | 304 | { |
294 | int part_nr = fa_element_to_part_nr(fa, element_nr); | 305 | int part_nr; |
295 | struct flex_array_part *part; | 306 | struct flex_array_part *part; |
296 | 307 | ||
308 | if (!fa->element_size) | ||
309 | return NULL; | ||
297 | if (element_nr >= fa->total_nr_elements) | 310 | if (element_nr >= fa->total_nr_elements) |
298 | return NULL; | 311 | return NULL; |
299 | if (elements_fit_in_base(fa)) | 312 | if (elements_fit_in_base(fa)) |
300 | part = (struct flex_array_part *)&fa->parts[0]; | 313 | part = (struct flex_array_part *)&fa->parts[0]; |
301 | else { | 314 | else { |
315 | part_nr = fa_element_to_part_nr(fa, element_nr); | ||
302 | part = fa->parts[part_nr]; | 316 | part = fa->parts[part_nr]; |
303 | if (!part) | 317 | if (!part) |
304 | return NULL; | 318 | return NULL; |
@@ -353,7 +367,7 @@ int flex_array_shrink(struct flex_array *fa) | |||
353 | int part_nr; | 367 | int part_nr; |
354 | int ret = 0; | 368 | int ret = 0; |
355 | 369 | ||
356 | if (!fa->total_nr_elements) | 370 | if (!fa->total_nr_elements || !fa->element_size) |
357 | return 0; | 371 | return 0; |
358 | if (elements_fit_in_base(fa)) | 372 | if (elements_fit_in_base(fa)) |
359 | return ret; | 373 | return ret; |
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index cfa7a5e1c5c9..fa000d26dc60 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c | |||
@@ -212,10 +212,12 @@ static void dns_resolver_describe(const struct key *key, struct seq_file *m) | |||
212 | int err = key->type_data.x[0]; | 212 | int err = key->type_data.x[0]; |
213 | 213 | ||
214 | seq_puts(m, key->description); | 214 | seq_puts(m, key->description); |
215 | if (err) | 215 | if (key_is_instantiated(key)) { |
216 | seq_printf(m, ": %d", err); | 216 | if (err) |
217 | else | 217 | seq_printf(m, ": %d", err); |
218 | seq_printf(m, ": %u", key->datalen); | 218 | else |
219 | seq_printf(m, ": %u", key->datalen); | ||
220 | } | ||
219 | } | 221 | } |
220 | 222 | ||
221 | /* | 223 | /* |
diff --git a/security/Kconfig b/security/Kconfig index 95accd442d55..e0f08b52e4ab 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
@@ -167,6 +167,7 @@ config INTEL_TXT | |||
167 | config LSM_MMAP_MIN_ADDR | 167 | config LSM_MMAP_MIN_ADDR |
168 | int "Low address space for LSM to protect from user allocation" | 168 | int "Low address space for LSM to protect from user allocation" |
169 | depends on SECURITY && SECURITY_SELINUX | 169 | depends on SECURITY && SECURITY_SELINUX |
170 | default 32768 if ARM | ||
170 | default 65536 | 171 | default 65536 |
171 | help | 172 | help |
172 | This is the portion of low virtual memory which should be protected | 173 | This is the portion of low virtual memory which should be protected |
diff --git a/security/commoncap.c b/security/commoncap.c index f20e984ccfb4..a93b3b733079 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -529,15 +529,10 @@ skip: | |||
529 | new->suid = new->fsuid = new->euid; | 529 | new->suid = new->fsuid = new->euid; |
530 | new->sgid = new->fsgid = new->egid; | 530 | new->sgid = new->fsgid = new->egid; |
531 | 531 | ||
532 | /* For init, we want to retain the capabilities set in the initial | 532 | if (effective) |
533 | * task. Thus we skip the usual capability rules | 533 | new->cap_effective = new->cap_permitted; |
534 | */ | 534 | else |
535 | if (!is_global_init(current)) { | 535 | cap_clear(new->cap_effective); |
536 | if (effective) | ||
537 | new->cap_effective = new->cap_permitted; | ||
538 | else | ||
539 | cap_clear(new->cap_effective); | ||
540 | } | ||
541 | bprm->cap_effective = effective; | 536 | bprm->cap_effective = effective; |
542 | 537 | ||
543 | /* | 538 | /* |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 07a025f81902..f375152a2500 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -109,11 +109,13 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
109 | const struct cred *cred, | 109 | const struct cred *cred, |
110 | struct key_type *type, | 110 | struct key_type *type, |
111 | const void *description, | 111 | const void *description, |
112 | key_match_func_t match); | 112 | key_match_func_t match, |
113 | bool no_state_check); | ||
113 | 114 | ||
114 | extern key_ref_t search_my_process_keyrings(struct key_type *type, | 115 | extern key_ref_t search_my_process_keyrings(struct key_type *type, |
115 | const void *description, | 116 | const void *description, |
116 | key_match_func_t match, | 117 | key_match_func_t match, |
118 | bool no_state_check, | ||
117 | const struct cred *cred); | 119 | const struct cred *cred); |
118 | extern key_ref_t search_process_keyrings(struct key_type *type, | 120 | extern key_ref_t search_process_keyrings(struct key_type *type, |
119 | const void *description, | 121 | const void *description, |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 427fddcaeb19..eca51918c951 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -206,8 +206,14 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type, | |||
206 | goto error5; | 206 | goto error5; |
207 | } | 207 | } |
208 | 208 | ||
209 | /* wait for the key to finish being constructed */ | ||
210 | ret = wait_for_key_construction(key, 1); | ||
211 | if (ret < 0) | ||
212 | goto error6; | ||
213 | |||
209 | ret = key->serial; | 214 | ret = key->serial; |
210 | 215 | ||
216 | error6: | ||
211 | key_put(key); | 217 | key_put(key); |
212 | error5: | 218 | error5: |
213 | key_type_put(ktype); | 219 | key_type_put(ktype); |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index cdd2f3f88c88..a06ffab38568 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -176,13 +176,15 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) | |||
176 | else | 176 | else |
177 | seq_puts(m, "[anon]"); | 177 | seq_puts(m, "[anon]"); |
178 | 178 | ||
179 | rcu_read_lock(); | 179 | if (key_is_instantiated(keyring)) { |
180 | klist = rcu_dereference(keyring->payload.subscriptions); | 180 | rcu_read_lock(); |
181 | if (klist) | 181 | klist = rcu_dereference(keyring->payload.subscriptions); |
182 | seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); | 182 | if (klist) |
183 | else | 183 | seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); |
184 | seq_puts(m, ": empty"); | 184 | else |
185 | rcu_read_unlock(); | 185 | seq_puts(m, ": empty"); |
186 | rcu_read_unlock(); | ||
187 | } | ||
186 | } | 188 | } |
187 | 189 | ||
188 | /* | 190 | /* |
@@ -271,6 +273,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
271 | * @type: The type of key to search for. | 273 | * @type: The type of key to search for. |
272 | * @description: Parameter for @match. | 274 | * @description: Parameter for @match. |
273 | * @match: Function to rule on whether or not a key is the one required. | 275 | * @match: Function to rule on whether or not a key is the one required. |
276 | * @no_state_check: Don't check if a matching key is bad | ||
274 | * | 277 | * |
275 | * Search the supplied keyring tree for a key that matches the criteria given. | 278 | * Search the supplied keyring tree for a key that matches the criteria given. |
276 | * The root keyring and any linked keyrings must grant Search permission to the | 279 | * The root keyring and any linked keyrings must grant Search permission to the |
@@ -303,7 +306,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
303 | const struct cred *cred, | 306 | const struct cred *cred, |
304 | struct key_type *type, | 307 | struct key_type *type, |
305 | const void *description, | 308 | const void *description, |
306 | key_match_func_t match) | 309 | key_match_func_t match, |
310 | bool no_state_check) | ||
307 | { | 311 | { |
308 | struct { | 312 | struct { |
309 | struct keyring_list *keylist; | 313 | struct keyring_list *keylist; |
@@ -345,6 +349,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
345 | kflags = keyring->flags; | 349 | kflags = keyring->flags; |
346 | if (keyring->type == type && match(keyring, description)) { | 350 | if (keyring->type == type && match(keyring, description)) { |
347 | key = keyring; | 351 | key = keyring; |
352 | if (no_state_check) | ||
353 | goto found; | ||
348 | 354 | ||
349 | /* check it isn't negative and hasn't expired or been | 355 | /* check it isn't negative and hasn't expired or been |
350 | * revoked */ | 356 | * revoked */ |
@@ -384,11 +390,13 @@ descend: | |||
384 | continue; | 390 | continue; |
385 | 391 | ||
386 | /* skip revoked keys and expired keys */ | 392 | /* skip revoked keys and expired keys */ |
387 | if (kflags & (1 << KEY_FLAG_REVOKED)) | 393 | if (!no_state_check) { |
388 | continue; | 394 | if (kflags & (1 << KEY_FLAG_REVOKED)) |
395 | continue; | ||
389 | 396 | ||
390 | if (key->expiry && now.tv_sec >= key->expiry) | 397 | if (key->expiry && now.tv_sec >= key->expiry) |
391 | continue; | 398 | continue; |
399 | } | ||
392 | 400 | ||
393 | /* keys that don't match */ | 401 | /* keys that don't match */ |
394 | if (!match(key, description)) | 402 | if (!match(key, description)) |
@@ -399,6 +407,9 @@ descend: | |||
399 | cred, KEY_SEARCH) < 0) | 407 | cred, KEY_SEARCH) < 0) |
400 | continue; | 408 | continue; |
401 | 409 | ||
410 | if (no_state_check) | ||
411 | goto found; | ||
412 | |||
402 | /* we set a different error code if we pass a negative key */ | 413 | /* we set a different error code if we pass a negative key */ |
403 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) { | 414 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) { |
404 | err = key->type_data.reject_error; | 415 | err = key->type_data.reject_error; |
@@ -478,7 +489,7 @@ key_ref_t keyring_search(key_ref_t keyring, | |||
478 | return ERR_PTR(-ENOKEY); | 489 | return ERR_PTR(-ENOKEY); |
479 | 490 | ||
480 | return keyring_search_aux(keyring, current->cred, | 491 | return keyring_search_aux(keyring, current->cred, |
481 | type, description, type->match); | 492 | type, description, type->match, false); |
482 | } | 493 | } |
483 | EXPORT_SYMBOL(keyring_search); | 494 | EXPORT_SYMBOL(keyring_search); |
484 | 495 | ||
diff --git a/security/keys/proc.c b/security/keys/proc.c index 525cf8a29cdd..49bbc97943ad 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -199,7 +199,7 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
199 | if (key->perm & KEY_POS_VIEW) { | 199 | if (key->perm & KEY_POS_VIEW) { |
200 | skey_ref = search_my_process_keyrings(key->type, key, | 200 | skey_ref = search_my_process_keyrings(key->type, key, |
201 | lookup_user_key_possessed, | 201 | lookup_user_key_possessed, |
202 | cred); | 202 | true, cred); |
203 | if (!IS_ERR(skey_ref)) { | 203 | if (!IS_ERR(skey_ref)) { |
204 | key_ref_put(skey_ref); | 204 | key_ref_put(skey_ref); |
205 | key_ref = make_key_ref(key, 1); | 205 | key_ref = make_key_ref(key, 1); |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 930634e45149..6c0480db8885 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -331,6 +331,7 @@ void key_fsgid_changed(struct task_struct *tsk) | |||
331 | key_ref_t search_my_process_keyrings(struct key_type *type, | 331 | key_ref_t search_my_process_keyrings(struct key_type *type, |
332 | const void *description, | 332 | const void *description, |
333 | key_match_func_t match, | 333 | key_match_func_t match, |
334 | bool no_state_check, | ||
334 | const struct cred *cred) | 335 | const struct cred *cred) |
335 | { | 336 | { |
336 | key_ref_t key_ref, ret, err; | 337 | key_ref_t key_ref, ret, err; |
@@ -350,7 +351,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
350 | if (cred->thread_keyring) { | 351 | if (cred->thread_keyring) { |
351 | key_ref = keyring_search_aux( | 352 | key_ref = keyring_search_aux( |
352 | make_key_ref(cred->thread_keyring, 1), | 353 | make_key_ref(cred->thread_keyring, 1), |
353 | cred, type, description, match); | 354 | cred, type, description, match, no_state_check); |
354 | if (!IS_ERR(key_ref)) | 355 | if (!IS_ERR(key_ref)) |
355 | goto found; | 356 | goto found; |
356 | 357 | ||
@@ -371,7 +372,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
371 | if (cred->tgcred->process_keyring) { | 372 | if (cred->tgcred->process_keyring) { |
372 | key_ref = keyring_search_aux( | 373 | key_ref = keyring_search_aux( |
373 | make_key_ref(cred->tgcred->process_keyring, 1), | 374 | make_key_ref(cred->tgcred->process_keyring, 1), |
374 | cred, type, description, match); | 375 | cred, type, description, match, no_state_check); |
375 | if (!IS_ERR(key_ref)) | 376 | if (!IS_ERR(key_ref)) |
376 | goto found; | 377 | goto found; |
377 | 378 | ||
@@ -395,7 +396,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
395 | make_key_ref(rcu_dereference( | 396 | make_key_ref(rcu_dereference( |
396 | cred->tgcred->session_keyring), | 397 | cred->tgcred->session_keyring), |
397 | 1), | 398 | 1), |
398 | cred, type, description, match); | 399 | cred, type, description, match, no_state_check); |
399 | rcu_read_unlock(); | 400 | rcu_read_unlock(); |
400 | 401 | ||
401 | if (!IS_ERR(key_ref)) | 402 | if (!IS_ERR(key_ref)) |
@@ -417,7 +418,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
417 | else if (cred->user->session_keyring) { | 418 | else if (cred->user->session_keyring) { |
418 | key_ref = keyring_search_aux( | 419 | key_ref = keyring_search_aux( |
419 | make_key_ref(cred->user->session_keyring, 1), | 420 | make_key_ref(cred->user->session_keyring, 1), |
420 | cred, type, description, match); | 421 | cred, type, description, match, no_state_check); |
421 | if (!IS_ERR(key_ref)) | 422 | if (!IS_ERR(key_ref)) |
422 | goto found; | 423 | goto found; |
423 | 424 | ||
@@ -459,7 +460,8 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
459 | 460 | ||
460 | might_sleep(); | 461 | might_sleep(); |
461 | 462 | ||
462 | key_ref = search_my_process_keyrings(type, description, match, cred); | 463 | key_ref = search_my_process_keyrings(type, description, match, |
464 | false, cred); | ||
463 | if (!IS_ERR(key_ref)) | 465 | if (!IS_ERR(key_ref)) |
464 | goto found; | 466 | goto found; |
465 | err = key_ref; | 467 | err = key_ref; |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index df3c0417ee40..b18a71745901 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -530,8 +530,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
530 | dest_keyring, flags); | 530 | dest_keyring, flags); |
531 | 531 | ||
532 | /* search all the process keyrings for a key */ | 532 | /* search all the process keyrings for a key */ |
533 | key_ref = search_process_keyrings(type, description, type->match, | 533 | key_ref = search_process_keyrings(type, description, type->match, cred); |
534 | cred); | ||
535 | 534 | ||
536 | if (!IS_ERR(key_ref)) { | 535 | if (!IS_ERR(key_ref)) { |
537 | key = key_ref_to_ptr(key_ref); | 536 | key = key_ref_to_ptr(key_ref); |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 68164031a74e..f6337c9082eb 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -59,7 +59,8 @@ static void request_key_auth_describe(const struct key *key, | |||
59 | 59 | ||
60 | seq_puts(m, "key:"); | 60 | seq_puts(m, "key:"); |
61 | seq_puts(m, key->description); | 61 | seq_puts(m, key->description); |
62 | seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); | 62 | if (key_is_instantiated(key)) |
63 | seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); | ||
63 | } | 64 | } |
64 | 65 | ||
65 | /* | 66 | /* |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index f66baf44f32d..5b366d7af3c4 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -157,8 +157,8 @@ EXPORT_SYMBOL_GPL(user_destroy); | |||
157 | void user_describe(const struct key *key, struct seq_file *m) | 157 | void user_describe(const struct key *key, struct seq_file *m) |
158 | { | 158 | { |
159 | seq_puts(m, key->description); | 159 | seq_puts(m, key->description); |
160 | 160 | if (key_is_instantiated(key)) | |
161 | seq_printf(m, ": %u", key->datalen); | 161 | seq_printf(m, ": %u", key->datalen); |
162 | } | 162 | } |
163 | 163 | ||
164 | EXPORT_SYMBOL_GPL(user_describe); | 164 | EXPORT_SYMBOL_GPL(user_describe); |
diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 908aa712816a..893af8a2fa1e 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c | |||
@@ -210,7 +210,6 @@ static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr, | |||
210 | static void dump_common_audit_data(struct audit_buffer *ab, | 210 | static void dump_common_audit_data(struct audit_buffer *ab, |
211 | struct common_audit_data *a) | 211 | struct common_audit_data *a) |
212 | { | 212 | { |
213 | struct inode *inode = NULL; | ||
214 | struct task_struct *tsk = current; | 213 | struct task_struct *tsk = current; |
215 | 214 | ||
216 | if (a->tsk) | 215 | if (a->tsk) |
@@ -229,33 +228,47 @@ static void dump_common_audit_data(struct audit_buffer *ab, | |||
229 | case LSM_AUDIT_DATA_CAP: | 228 | case LSM_AUDIT_DATA_CAP: |
230 | audit_log_format(ab, " capability=%d ", a->u.cap); | 229 | audit_log_format(ab, " capability=%d ", a->u.cap); |
231 | break; | 230 | break; |
232 | case LSM_AUDIT_DATA_FS: | 231 | case LSM_AUDIT_DATA_PATH: { |
233 | if (a->u.fs.path.dentry) { | 232 | struct inode *inode; |
234 | struct dentry *dentry = a->u.fs.path.dentry; | 233 | |
235 | if (a->u.fs.path.mnt) { | 234 | audit_log_d_path(ab, "path=", &a->u.path); |
236 | audit_log_d_path(ab, "path=", &a->u.fs.path); | 235 | |
237 | } else { | 236 | inode = a->u.path.dentry->d_inode; |
238 | audit_log_format(ab, " name="); | ||
239 | audit_log_untrustedstring(ab, | ||
240 | dentry->d_name.name); | ||
241 | } | ||
242 | inode = dentry->d_inode; | ||
243 | } else if (a->u.fs.inode) { | ||
244 | struct dentry *dentry; | ||
245 | inode = a->u.fs.inode; | ||
246 | dentry = d_find_alias(inode); | ||
247 | if (dentry) { | ||
248 | audit_log_format(ab, " name="); | ||
249 | audit_log_untrustedstring(ab, | ||
250 | dentry->d_name.name); | ||
251 | dput(dentry); | ||
252 | } | ||
253 | } | ||
254 | if (inode) | 237 | if (inode) |
255 | audit_log_format(ab, " dev=%s ino=%lu", | 238 | audit_log_format(ab, " dev=%s ino=%lu", |
256 | inode->i_sb->s_id, | 239 | inode->i_sb->s_id, |
257 | inode->i_ino); | 240 | inode->i_ino); |
258 | break; | 241 | break; |
242 | } | ||
243 | case LSM_AUDIT_DATA_DENTRY: { | ||
244 | struct inode *inode; | ||
245 | |||
246 | audit_log_format(ab, " name="); | ||
247 | audit_log_untrustedstring(ab, a->u.dentry->d_name.name); | ||
248 | |||
249 | inode = a->u.dentry->d_inode; | ||
250 | if (inode) | ||
251 | audit_log_format(ab, " dev=%s ino=%lu", | ||
252 | inode->i_sb->s_id, | ||
253 | inode->i_ino); | ||
254 | break; | ||
255 | } | ||
256 | case LSM_AUDIT_DATA_INODE: { | ||
257 | struct dentry *dentry; | ||
258 | struct inode *inode; | ||
259 | |||
260 | inode = a->u.inode; | ||
261 | dentry = d_find_alias(inode); | ||
262 | if (dentry) { | ||
263 | audit_log_format(ab, " name="); | ||
264 | audit_log_untrustedstring(ab, | ||
265 | dentry->d_name.name); | ||
266 | dput(dentry); | ||
267 | } | ||
268 | audit_log_format(ab, " dev=%s ino=%lu", inode->i_sb->s_id, | ||
269 | inode->i_ino); | ||
270 | break; | ||
271 | } | ||
259 | case LSM_AUDIT_DATA_TASK: | 272 | case LSM_AUDIT_DATA_TASK: |
260 | tsk = a->u.tsk; | 273 | tsk = a->u.tsk; |
261 | if (tsk && tsk->pid) { | 274 | if (tsk && tsk->pid) { |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 3d2715fd35ea..fcb89cb0f223 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -526,7 +526,7 @@ int avc_audit(u32 ssid, u32 tsid, | |||
526 | * during retry. However this is logically just as if the operation | 526 | * during retry. However this is logically just as if the operation |
527 | * happened a little later. | 527 | * happened a little later. |
528 | */ | 528 | */ |
529 | if ((a->type == LSM_AUDIT_DATA_FS) && | 529 | if ((a->type == LSM_AUDIT_DATA_INODE) && |
530 | (flags & IPERM_FLAG_RCU)) | 530 | (flags & IPERM_FLAG_RCU)) |
531 | return -ECHILD; | 531 | return -ECHILD; |
532 | 532 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8fb248843009..a0d38459d650 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -990,6 +990,7 @@ static void selinux_write_opts(struct seq_file *m, | |||
990 | continue; | 990 | continue; |
991 | default: | 991 | default: |
992 | BUG(); | 992 | BUG(); |
993 | return; | ||
993 | }; | 994 | }; |
994 | /* we need a comma before each option */ | 995 | /* we need a comma before each option */ |
995 | seq_putc(m, ','); | 996 | seq_putc(m, ','); |
@@ -1443,6 +1444,7 @@ static int task_has_capability(struct task_struct *tsk, | |||
1443 | printk(KERN_ERR | 1444 | printk(KERN_ERR |
1444 | "SELinux: out of range capability %d\n", cap); | 1445 | "SELinux: out of range capability %d\n", cap); |
1445 | BUG(); | 1446 | BUG(); |
1447 | return -EINVAL; | ||
1446 | } | 1448 | } |
1447 | 1449 | ||
1448 | rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); | 1450 | rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); |
@@ -1487,8 +1489,8 @@ static int inode_has_perm(const struct cred *cred, | |||
1487 | 1489 | ||
1488 | if (!adp) { | 1490 | if (!adp) { |
1489 | adp = &ad; | 1491 | adp = &ad; |
1490 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 1492 | COMMON_AUDIT_DATA_INIT(&ad, INODE); |
1491 | ad.u.fs.inode = inode; | 1493 | ad.u.inode = inode; |
1492 | } | 1494 | } |
1493 | 1495 | ||
1494 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); | 1496 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); |
@@ -1498,16 +1500,29 @@ static int inode_has_perm(const struct cred *cred, | |||
1498 | the dentry to help the auditing code to more easily generate the | 1500 | the dentry to help the auditing code to more easily generate the |
1499 | pathname if needed. */ | 1501 | pathname if needed. */ |
1500 | static inline int dentry_has_perm(const struct cred *cred, | 1502 | static inline int dentry_has_perm(const struct cred *cred, |
1501 | struct vfsmount *mnt, | ||
1502 | struct dentry *dentry, | 1503 | struct dentry *dentry, |
1503 | u32 av) | 1504 | u32 av) |
1504 | { | 1505 | { |
1505 | struct inode *inode = dentry->d_inode; | 1506 | struct inode *inode = dentry->d_inode; |
1506 | struct common_audit_data ad; | 1507 | struct common_audit_data ad; |
1507 | 1508 | ||
1508 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 1509 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1509 | ad.u.fs.path.mnt = mnt; | 1510 | ad.u.dentry = dentry; |
1510 | ad.u.fs.path.dentry = dentry; | 1511 | return inode_has_perm(cred, inode, av, &ad, 0); |
1512 | } | ||
1513 | |||
1514 | /* Same as inode_has_perm, but pass explicit audit data containing | ||
1515 | the path to help the auditing code to more easily generate the | ||
1516 | pathname if needed. */ | ||
1517 | static inline int path_has_perm(const struct cred *cred, | ||
1518 | struct path *path, | ||
1519 | u32 av) | ||
1520 | { | ||
1521 | struct inode *inode = path->dentry->d_inode; | ||
1522 | struct common_audit_data ad; | ||
1523 | |||
1524 | COMMON_AUDIT_DATA_INIT(&ad, PATH); | ||
1525 | ad.u.path = *path; | ||
1511 | return inode_has_perm(cred, inode, av, &ad, 0); | 1526 | return inode_has_perm(cred, inode, av, &ad, 0); |
1512 | } | 1527 | } |
1513 | 1528 | ||
@@ -1529,8 +1544,8 @@ static int file_has_perm(const struct cred *cred, | |||
1529 | u32 sid = cred_sid(cred); | 1544 | u32 sid = cred_sid(cred); |
1530 | int rc; | 1545 | int rc; |
1531 | 1546 | ||
1532 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 1547 | COMMON_AUDIT_DATA_INIT(&ad, PATH); |
1533 | ad.u.fs.path = file->f_path; | 1548 | ad.u.path = file->f_path; |
1534 | 1549 | ||
1535 | if (sid != fsec->sid) { | 1550 | if (sid != fsec->sid) { |
1536 | rc = avc_has_perm(sid, fsec->sid, | 1551 | rc = avc_has_perm(sid, fsec->sid, |
@@ -1568,8 +1583,8 @@ static int may_create(struct inode *dir, | |||
1568 | sid = tsec->sid; | 1583 | sid = tsec->sid; |
1569 | newsid = tsec->create_sid; | 1584 | newsid = tsec->create_sid; |
1570 | 1585 | ||
1571 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 1586 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1572 | ad.u.fs.path.dentry = dentry; | 1587 | ad.u.dentry = dentry; |
1573 | 1588 | ||
1574 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1589 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
1575 | DIR__ADD_NAME | DIR__SEARCH, | 1590 | DIR__ADD_NAME | DIR__SEARCH, |
@@ -1621,8 +1636,8 @@ static int may_link(struct inode *dir, | |||
1621 | dsec = dir->i_security; | 1636 | dsec = dir->i_security; |
1622 | isec = dentry->d_inode->i_security; | 1637 | isec = dentry->d_inode->i_security; |
1623 | 1638 | ||
1624 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 1639 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1625 | ad.u.fs.path.dentry = dentry; | 1640 | ad.u.dentry = dentry; |
1626 | 1641 | ||
1627 | av = DIR__SEARCH; | 1642 | av = DIR__SEARCH; |
1628 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); | 1643 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); |
@@ -1667,9 +1682,9 @@ static inline int may_rename(struct inode *old_dir, | |||
1667 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 1682 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
1668 | new_dsec = new_dir->i_security; | 1683 | new_dsec = new_dir->i_security; |
1669 | 1684 | ||
1670 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 1685 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1671 | 1686 | ||
1672 | ad.u.fs.path.dentry = old_dentry; | 1687 | ad.u.dentry = old_dentry; |
1673 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 1688 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, |
1674 | DIR__REMOVE_NAME | DIR__SEARCH, &ad); | 1689 | DIR__REMOVE_NAME | DIR__SEARCH, &ad); |
1675 | if (rc) | 1690 | if (rc) |
@@ -1685,7 +1700,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1685 | return rc; | 1700 | return rc; |
1686 | } | 1701 | } |
1687 | 1702 | ||
1688 | ad.u.fs.path.dentry = new_dentry; | 1703 | ad.u.dentry = new_dentry; |
1689 | av = DIR__ADD_NAME | DIR__SEARCH; | 1704 | av = DIR__ADD_NAME | DIR__SEARCH; |
1690 | if (new_dentry->d_inode) | 1705 | if (new_dentry->d_inode) |
1691 | av |= DIR__REMOVE_NAME; | 1706 | av |= DIR__REMOVE_NAME; |
@@ -1895,7 +1910,7 @@ static int selinux_quota_on(struct dentry *dentry) | |||
1895 | { | 1910 | { |
1896 | const struct cred *cred = current_cred(); | 1911 | const struct cred *cred = current_cred(); |
1897 | 1912 | ||
1898 | return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON); | 1913 | return dentry_has_perm(cred, dentry, FILE__QUOTAON); |
1899 | } | 1914 | } |
1900 | 1915 | ||
1901 | static int selinux_syslog(int type) | 1916 | static int selinux_syslog(int type) |
@@ -1992,8 +2007,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
1992 | return rc; | 2007 | return rc; |
1993 | } | 2008 | } |
1994 | 2009 | ||
1995 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2010 | COMMON_AUDIT_DATA_INIT(&ad, PATH); |
1996 | ad.u.fs.path = bprm->file->f_path; | 2011 | ad.u.path = bprm->file->f_path; |
1997 | 2012 | ||
1998 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 2013 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) |
1999 | new_tsec->sid = old_tsec->sid; | 2014 | new_tsec->sid = old_tsec->sid; |
@@ -2121,7 +2136,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2121 | 2136 | ||
2122 | /* Revalidate access to inherited open files. */ | 2137 | /* Revalidate access to inherited open files. */ |
2123 | 2138 | ||
2124 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2139 | COMMON_AUDIT_DATA_INIT(&ad, INODE); |
2125 | 2140 | ||
2126 | spin_lock(&files->file_lock); | 2141 | spin_lock(&files->file_lock); |
2127 | for (;;) { | 2142 | for (;;) { |
@@ -2469,8 +2484,8 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2469 | if (flags & MS_KERNMOUNT) | 2484 | if (flags & MS_KERNMOUNT) |
2470 | return 0; | 2485 | return 0; |
2471 | 2486 | ||
2472 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2487 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
2473 | ad.u.fs.path.dentry = sb->s_root; | 2488 | ad.u.dentry = sb->s_root; |
2474 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); | 2489 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
2475 | } | 2490 | } |
2476 | 2491 | ||
@@ -2479,8 +2494,8 @@ static int selinux_sb_statfs(struct dentry *dentry) | |||
2479 | const struct cred *cred = current_cred(); | 2494 | const struct cred *cred = current_cred(); |
2480 | struct common_audit_data ad; | 2495 | struct common_audit_data ad; |
2481 | 2496 | ||
2482 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2497 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
2483 | ad.u.fs.path.dentry = dentry->d_sb->s_root; | 2498 | ad.u.dentry = dentry->d_sb->s_root; |
2484 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); | 2499 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); |
2485 | } | 2500 | } |
2486 | 2501 | ||
@@ -2496,8 +2511,7 @@ static int selinux_mount(char *dev_name, | |||
2496 | return superblock_has_perm(cred, path->mnt->mnt_sb, | 2511 | return superblock_has_perm(cred, path->mnt->mnt_sb, |
2497 | FILESYSTEM__REMOUNT, NULL); | 2512 | FILESYSTEM__REMOUNT, NULL); |
2498 | else | 2513 | else |
2499 | return dentry_has_perm(cred, path->mnt, path->dentry, | 2514 | return path_has_perm(cred, path, FILE__MOUNTON); |
2500 | FILE__MOUNTON); | ||
2501 | } | 2515 | } |
2502 | 2516 | ||
2503 | static int selinux_umount(struct vfsmount *mnt, int flags) | 2517 | static int selinux_umount(struct vfsmount *mnt, int flags) |
@@ -2630,14 +2644,14 @@ static int selinux_inode_readlink(struct dentry *dentry) | |||
2630 | { | 2644 | { |
2631 | const struct cred *cred = current_cred(); | 2645 | const struct cred *cred = current_cred(); |
2632 | 2646 | ||
2633 | return dentry_has_perm(cred, NULL, dentry, FILE__READ); | 2647 | return dentry_has_perm(cred, dentry, FILE__READ); |
2634 | } | 2648 | } |
2635 | 2649 | ||
2636 | static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata) | 2650 | static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata) |
2637 | { | 2651 | { |
2638 | const struct cred *cred = current_cred(); | 2652 | const struct cred *cred = current_cred(); |
2639 | 2653 | ||
2640 | return dentry_has_perm(cred, NULL, dentry, FILE__READ); | 2654 | return dentry_has_perm(cred, dentry, FILE__READ); |
2641 | } | 2655 | } |
2642 | 2656 | ||
2643 | static int selinux_inode_permission(struct inode *inode, int mask, unsigned flags) | 2657 | static int selinux_inode_permission(struct inode *inode, int mask, unsigned flags) |
@@ -2654,8 +2668,8 @@ static int selinux_inode_permission(struct inode *inode, int mask, unsigned flag | |||
2654 | if (!mask) | 2668 | if (!mask) |
2655 | return 0; | 2669 | return 0; |
2656 | 2670 | ||
2657 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2671 | COMMON_AUDIT_DATA_INIT(&ad, INODE); |
2658 | ad.u.fs.inode = inode; | 2672 | ad.u.inode = inode; |
2659 | 2673 | ||
2660 | if (from_access) | 2674 | if (from_access) |
2661 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; | 2675 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; |
@@ -2680,16 +2694,20 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | |||
2680 | 2694 | ||
2681 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | | 2695 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | |
2682 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) | 2696 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) |
2683 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); | 2697 | return dentry_has_perm(cred, dentry, FILE__SETATTR); |
2684 | 2698 | ||
2685 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); | 2699 | return dentry_has_perm(cred, dentry, FILE__WRITE); |
2686 | } | 2700 | } |
2687 | 2701 | ||
2688 | static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | 2702 | static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
2689 | { | 2703 | { |
2690 | const struct cred *cred = current_cred(); | 2704 | const struct cred *cred = current_cred(); |
2705 | struct path path; | ||
2706 | |||
2707 | path.dentry = dentry; | ||
2708 | path.mnt = mnt; | ||
2691 | 2709 | ||
2692 | return dentry_has_perm(cred, mnt, dentry, FILE__GETATTR); | 2710 | return path_has_perm(cred, &path, FILE__GETATTR); |
2693 | } | 2711 | } |
2694 | 2712 | ||
2695 | static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) | 2713 | static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) |
@@ -2710,7 +2728,7 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) | |||
2710 | 2728 | ||
2711 | /* Not an attribute we recognize, so just check the | 2729 | /* Not an attribute we recognize, so just check the |
2712 | ordinary setattr permission. */ | 2730 | ordinary setattr permission. */ |
2713 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); | 2731 | return dentry_has_perm(cred, dentry, FILE__SETATTR); |
2714 | } | 2732 | } |
2715 | 2733 | ||
2716 | static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | 2734 | static int selinux_inode_setxattr(struct dentry *dentry, const char *name, |
@@ -2733,8 +2751,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2733 | if (!inode_owner_or_capable(inode)) | 2751 | if (!inode_owner_or_capable(inode)) |
2734 | return -EPERM; | 2752 | return -EPERM; |
2735 | 2753 | ||
2736 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2754 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
2737 | ad.u.fs.path.dentry = dentry; | 2755 | ad.u.dentry = dentry; |
2738 | 2756 | ||
2739 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 2757 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
2740 | FILE__RELABELFROM, &ad); | 2758 | FILE__RELABELFROM, &ad); |
@@ -2797,14 +2815,14 @@ static int selinux_inode_getxattr(struct dentry *dentry, const char *name) | |||
2797 | { | 2815 | { |
2798 | const struct cred *cred = current_cred(); | 2816 | const struct cred *cred = current_cred(); |
2799 | 2817 | ||
2800 | return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR); | 2818 | return dentry_has_perm(cred, dentry, FILE__GETATTR); |
2801 | } | 2819 | } |
2802 | 2820 | ||
2803 | static int selinux_inode_listxattr(struct dentry *dentry) | 2821 | static int selinux_inode_listxattr(struct dentry *dentry) |
2804 | { | 2822 | { |
2805 | const struct cred *cred = current_cred(); | 2823 | const struct cred *cred = current_cred(); |
2806 | 2824 | ||
2807 | return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR); | 2825 | return dentry_has_perm(cred, dentry, FILE__GETATTR); |
2808 | } | 2826 | } |
2809 | 2827 | ||
2810 | static int selinux_inode_removexattr(struct dentry *dentry, const char *name) | 2828 | static int selinux_inode_removexattr(struct dentry *dentry, const char *name) |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 348eb00cb668..3ba4feba048a 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -30,13 +30,14 @@ | |||
30 | #define POLICYDB_VERSION_PERMISSIVE 23 | 30 | #define POLICYDB_VERSION_PERMISSIVE 23 |
31 | #define POLICYDB_VERSION_BOUNDARY 24 | 31 | #define POLICYDB_VERSION_BOUNDARY 24 |
32 | #define POLICYDB_VERSION_FILENAME_TRANS 25 | 32 | #define POLICYDB_VERSION_FILENAME_TRANS 25 |
33 | #define POLICYDB_VERSION_ROLETRANS 26 | ||
33 | 34 | ||
34 | /* Range of policy versions we understand*/ | 35 | /* Range of policy versions we understand*/ |
35 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE | 36 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
36 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX | 37 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX |
37 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE | 38 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE |
38 | #else | 39 | #else |
39 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_FILENAME_TRANS | 40 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_ROLETRANS |
40 | #endif | 41 | #endif |
41 | 42 | ||
42 | /* Mask for just the mount related flags */ | 43 | /* Mask for just the mount related flags */ |
@@ -85,7 +86,7 @@ extern int selinux_policycap_openperm; | |||
85 | int security_mls_enabled(void); | 86 | int security_mls_enabled(void); |
86 | 87 | ||
87 | int security_load_policy(void *data, size_t len); | 88 | int security_load_policy(void *data, size_t len); |
88 | int security_read_policy(void **data, ssize_t *len); | 89 | int security_read_policy(void **data, size_t *len); |
89 | size_t security_policydb_len(void); | 90 | size_t security_policydb_len(void); |
90 | 91 | ||
91 | int security_policycap_supported(unsigned int req_cap); | 92 | int security_policycap_supported(unsigned int req_cap); |
@@ -111,8 +112,8 @@ void security_compute_av_user(u32 ssid, u32 tsid, | |||
111 | int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, | 112 | int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, |
112 | const struct qstr *qstr, u32 *out_sid); | 113 | const struct qstr *qstr, u32 *out_sid); |
113 | 114 | ||
114 | int security_transition_sid_user(u32 ssid, u32 tsid, | 115 | int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, |
115 | u16 tclass, u32 *out_sid); | 116 | const char *objname, u32 *out_sid); |
116 | 117 | ||
117 | int security_member_sid(u32 ssid, u32 tsid, | 118 | int security_member_sid(u32 ssid, u32 tsid, |
118 | u16 tclass, u32 *out_sid); | 119 | u16 tclass, u32 *out_sid); |
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 65ebfe954f85..3618251d0fdb 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c | |||
@@ -141,6 +141,7 @@ static struct sel_netnode *sel_netnode_find(const void *addr, u16 family) | |||
141 | break; | 141 | break; |
142 | default: | 142 | default: |
143 | BUG(); | 143 | BUG(); |
144 | return NULL; | ||
144 | } | 145 | } |
145 | 146 | ||
146 | list_for_each_entry_rcu(node, &sel_netnode_hash[idx].list, list) | 147 | list_for_each_entry_rcu(node, &sel_netnode_hash[idx].list, list) |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 2d3373b2e256..77d44138864f 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/percpu.h> | 28 | #include <linux/percpu.h> |
29 | #include <linux/audit.h> | 29 | #include <linux/audit.h> |
30 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
31 | #include <linux/kobject.h> | ||
31 | 32 | ||
32 | /* selinuxfs pseudo filesystem for exporting the security policy API. | 33 | /* selinuxfs pseudo filesystem for exporting the security policy API. |
33 | Based on the proc code and the fs/nfsd/nfsctl.c code. */ | 34 | Based on the proc code and the fs/nfsd/nfsctl.c code. */ |
@@ -753,11 +754,13 @@ out: | |||
753 | static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | 754 | static ssize_t sel_write_create(struct file *file, char *buf, size_t size) |
754 | { | 755 | { |
755 | char *scon = NULL, *tcon = NULL; | 756 | char *scon = NULL, *tcon = NULL; |
757 | char *namebuf = NULL, *objname = NULL; | ||
756 | u32 ssid, tsid, newsid; | 758 | u32 ssid, tsid, newsid; |
757 | u16 tclass; | 759 | u16 tclass; |
758 | ssize_t length; | 760 | ssize_t length; |
759 | char *newcon = NULL; | 761 | char *newcon = NULL; |
760 | u32 len; | 762 | u32 len; |
763 | int nargs; | ||
761 | 764 | ||
762 | length = task_has_security(current, SECURITY__COMPUTE_CREATE); | 765 | length = task_has_security(current, SECURITY__COMPUTE_CREATE); |
763 | if (length) | 766 | if (length) |
@@ -773,9 +776,17 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
773 | if (!tcon) | 776 | if (!tcon) |
774 | goto out; | 777 | goto out; |
775 | 778 | ||
779 | length = -ENOMEM; | ||
780 | namebuf = kzalloc(size + 1, GFP_KERNEL); | ||
781 | if (!namebuf) | ||
782 | goto out; | ||
783 | |||
776 | length = -EINVAL; | 784 | length = -EINVAL; |
777 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 785 | nargs = sscanf(buf, "%s %s %hu %s", scon, tcon, &tclass, namebuf); |
786 | if (nargs < 3 || nargs > 4) | ||
778 | goto out; | 787 | goto out; |
788 | if (nargs == 4) | ||
789 | objname = namebuf; | ||
779 | 790 | ||
780 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); | 791 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
781 | if (length) | 792 | if (length) |
@@ -785,7 +796,8 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
785 | if (length) | 796 | if (length) |
786 | goto out; | 797 | goto out; |
787 | 798 | ||
788 | length = security_transition_sid_user(ssid, tsid, tclass, &newsid); | 799 | length = security_transition_sid_user(ssid, tsid, tclass, |
800 | objname, &newsid); | ||
789 | if (length) | 801 | if (length) |
790 | goto out; | 802 | goto out; |
791 | 803 | ||
@@ -804,6 +816,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
804 | length = len; | 816 | length = len; |
805 | out: | 817 | out: |
806 | kfree(newcon); | 818 | kfree(newcon); |
819 | kfree(namebuf); | ||
807 | kfree(tcon); | 820 | kfree(tcon); |
808 | kfree(scon); | 821 | kfree(scon); |
809 | return length; | 822 | return length; |
@@ -1901,6 +1914,7 @@ static struct file_system_type sel_fs_type = { | |||
1901 | }; | 1914 | }; |
1902 | 1915 | ||
1903 | struct vfsmount *selinuxfs_mount; | 1916 | struct vfsmount *selinuxfs_mount; |
1917 | static struct kobject *selinuxfs_kobj; | ||
1904 | 1918 | ||
1905 | static int __init init_sel_fs(void) | 1919 | static int __init init_sel_fs(void) |
1906 | { | 1920 | { |
@@ -1908,9 +1922,16 @@ static int __init init_sel_fs(void) | |||
1908 | 1922 | ||
1909 | if (!selinux_enabled) | 1923 | if (!selinux_enabled) |
1910 | return 0; | 1924 | return 0; |
1925 | |||
1926 | selinuxfs_kobj = kobject_create_and_add("selinux", fs_kobj); | ||
1927 | if (!selinuxfs_kobj) | ||
1928 | return -ENOMEM; | ||
1929 | |||
1911 | err = register_filesystem(&sel_fs_type); | 1930 | err = register_filesystem(&sel_fs_type); |
1912 | if (err) | 1931 | if (err) { |
1932 | kobject_put(selinuxfs_kobj); | ||
1913 | return err; | 1933 | return err; |
1934 | } | ||
1914 | 1935 | ||
1915 | selinuxfs_mount = kern_mount(&sel_fs_type); | 1936 | selinuxfs_mount = kern_mount(&sel_fs_type); |
1916 | if (IS_ERR(selinuxfs_mount)) { | 1937 | if (IS_ERR(selinuxfs_mount)) { |
@@ -1927,6 +1948,7 @@ __initcall(init_sel_fs); | |||
1927 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE | 1948 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE |
1928 | void exit_sel_fs(void) | 1949 | void exit_sel_fs(void) |
1929 | { | 1950 | { |
1951 | kobject_put(selinuxfs_kobj); | ||
1930 | unregister_filesystem(&sel_fs_type); | 1952 | unregister_filesystem(&sel_fs_type); |
1931 | } | 1953 | } |
1932 | #endif | 1954 | #endif |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 7102457661d6..102e9ec1b77a 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -128,6 +128,11 @@ static struct policydb_compat_info policydb_compat[] = { | |||
128 | .sym_num = SYM_NUM, | 128 | .sym_num = SYM_NUM, |
129 | .ocon_num = OCON_NUM, | 129 | .ocon_num = OCON_NUM, |
130 | }, | 130 | }, |
131 | { | ||
132 | .version = POLICYDB_VERSION_ROLETRANS, | ||
133 | .sym_num = SYM_NUM, | ||
134 | .ocon_num = OCON_NUM, | ||
135 | }, | ||
131 | }; | 136 | }; |
132 | 137 | ||
133 | static struct policydb_compat_info *policydb_lookup_compat(int version) | 138 | static struct policydb_compat_info *policydb_lookup_compat(int version) |
@@ -179,6 +184,43 @@ out: | |||
179 | return rc; | 184 | return rc; |
180 | } | 185 | } |
181 | 186 | ||
187 | static u32 filenametr_hash(struct hashtab *h, const void *k) | ||
188 | { | ||
189 | const struct filename_trans *ft = k; | ||
190 | unsigned long hash; | ||
191 | unsigned int byte_num; | ||
192 | unsigned char focus; | ||
193 | |||
194 | hash = ft->stype ^ ft->ttype ^ ft->tclass; | ||
195 | |||
196 | byte_num = 0; | ||
197 | while ((focus = ft->name[byte_num++])) | ||
198 | hash = partial_name_hash(focus, hash); | ||
199 | return hash & (h->size - 1); | ||
200 | } | ||
201 | |||
202 | static int filenametr_cmp(struct hashtab *h, const void *k1, const void *k2) | ||
203 | { | ||
204 | const struct filename_trans *ft1 = k1; | ||
205 | const struct filename_trans *ft2 = k2; | ||
206 | int v; | ||
207 | |||
208 | v = ft1->stype - ft2->stype; | ||
209 | if (v) | ||
210 | return v; | ||
211 | |||
212 | v = ft1->ttype - ft2->ttype; | ||
213 | if (v) | ||
214 | return v; | ||
215 | |||
216 | v = ft1->tclass - ft2->tclass; | ||
217 | if (v) | ||
218 | return v; | ||
219 | |||
220 | return strcmp(ft1->name, ft2->name); | ||
221 | |||
222 | } | ||
223 | |||
182 | static u32 rangetr_hash(struct hashtab *h, const void *k) | 224 | static u32 rangetr_hash(struct hashtab *h, const void *k) |
183 | { | 225 | { |
184 | const struct range_trans *key = k; | 226 | const struct range_trans *key = k; |
@@ -231,15 +273,22 @@ static int policydb_init(struct policydb *p) | |||
231 | if (rc) | 273 | if (rc) |
232 | goto out; | 274 | goto out; |
233 | 275 | ||
276 | p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, (1 << 10)); | ||
277 | if (!p->filename_trans) | ||
278 | goto out; | ||
279 | |||
234 | p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); | 280 | p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); |
235 | if (!p->range_tr) | 281 | if (!p->range_tr) |
236 | goto out; | 282 | goto out; |
237 | 283 | ||
284 | ebitmap_init(&p->filename_trans_ttypes); | ||
238 | ebitmap_init(&p->policycaps); | 285 | ebitmap_init(&p->policycaps); |
239 | ebitmap_init(&p->permissive_map); | 286 | ebitmap_init(&p->permissive_map); |
240 | 287 | ||
241 | return 0; | 288 | return 0; |
242 | out: | 289 | out: |
290 | hashtab_destroy(p->filename_trans); | ||
291 | hashtab_destroy(p->range_tr); | ||
243 | for (i = 0; i < SYM_NUM; i++) | 292 | for (i = 0; i < SYM_NUM; i++) |
244 | hashtab_destroy(p->symtab[i].table); | 293 | hashtab_destroy(p->symtab[i].table); |
245 | return rc; | 294 | return rc; |
@@ -417,32 +466,26 @@ static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) = | |||
417 | }; | 466 | }; |
418 | 467 | ||
419 | #ifdef DEBUG_HASHES | 468 | #ifdef DEBUG_HASHES |
420 | static void symtab_hash_eval(struct symtab *s) | 469 | static void hash_eval(struct hashtab *h, const char *hash_name) |
421 | { | 470 | { |
422 | int i; | 471 | struct hashtab_info info; |
423 | |||
424 | for (i = 0; i < SYM_NUM; i++) { | ||
425 | struct hashtab *h = s[i].table; | ||
426 | struct hashtab_info info; | ||
427 | 472 | ||
428 | hashtab_stat(h, &info); | 473 | hashtab_stat(h, &info); |
429 | printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, " | 474 | printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, " |
430 | "longest chain length %d\n", symtab_name[i], h->nel, | 475 | "longest chain length %d\n", hash_name, h->nel, |
431 | info.slots_used, h->size, info.max_chain_len); | 476 | info.slots_used, h->size, info.max_chain_len); |
432 | } | ||
433 | } | 477 | } |
434 | 478 | ||
435 | static void rangetr_hash_eval(struct hashtab *h) | 479 | static void symtab_hash_eval(struct symtab *s) |
436 | { | 480 | { |
437 | struct hashtab_info info; | 481 | int i; |
438 | 482 | ||
439 | hashtab_stat(h, &info); | 483 | for (i = 0; i < SYM_NUM; i++) |
440 | printk(KERN_DEBUG "SELinux: rangetr: %d entries and %d/%d buckets used, " | 484 | hash_eval(s[i].table, symtab_name[i]); |
441 | "longest chain length %d\n", h->nel, | ||
442 | info.slots_used, h->size, info.max_chain_len); | ||
443 | } | 485 | } |
486 | |||
444 | #else | 487 | #else |
445 | static inline void rangetr_hash_eval(struct hashtab *h) | 488 | static inline void hash_eval(struct hashtab *h, char *hash_name) |
446 | { | 489 | { |
447 | } | 490 | } |
448 | #endif | 491 | #endif |
@@ -675,6 +718,16 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = | |||
675 | cat_destroy, | 718 | cat_destroy, |
676 | }; | 719 | }; |
677 | 720 | ||
721 | static int filenametr_destroy(void *key, void *datum, void *p) | ||
722 | { | ||
723 | struct filename_trans *ft = key; | ||
724 | kfree(ft->name); | ||
725 | kfree(key); | ||
726 | kfree(datum); | ||
727 | cond_resched(); | ||
728 | return 0; | ||
729 | } | ||
730 | |||
678 | static int range_tr_destroy(void *key, void *datum, void *p) | 731 | static int range_tr_destroy(void *key, void *datum, void *p) |
679 | { | 732 | { |
680 | struct mls_range *rt = datum; | 733 | struct mls_range *rt = datum; |
@@ -709,7 +762,6 @@ void policydb_destroy(struct policydb *p) | |||
709 | int i; | 762 | int i; |
710 | struct role_allow *ra, *lra = NULL; | 763 | struct role_allow *ra, *lra = NULL; |
711 | struct role_trans *tr, *ltr = NULL; | 764 | struct role_trans *tr, *ltr = NULL; |
712 | struct filename_trans *ft, *nft; | ||
713 | 765 | ||
714 | for (i = 0; i < SYM_NUM; i++) { | 766 | for (i = 0; i < SYM_NUM; i++) { |
715 | cond_resched(); | 767 | cond_resched(); |
@@ -773,6 +825,9 @@ void policydb_destroy(struct policydb *p) | |||
773 | } | 825 | } |
774 | kfree(lra); | 826 | kfree(lra); |
775 | 827 | ||
828 | hashtab_map(p->filename_trans, filenametr_destroy, NULL); | ||
829 | hashtab_destroy(p->filename_trans); | ||
830 | |||
776 | hashtab_map(p->range_tr, range_tr_destroy, NULL); | 831 | hashtab_map(p->range_tr, range_tr_destroy, NULL); |
777 | hashtab_destroy(p->range_tr); | 832 | hashtab_destroy(p->range_tr); |
778 | 833 | ||
@@ -788,14 +843,7 @@ void policydb_destroy(struct policydb *p) | |||
788 | flex_array_free(p->type_attr_map_array); | 843 | flex_array_free(p->type_attr_map_array); |
789 | } | 844 | } |
790 | 845 | ||
791 | ft = p->filename_trans; | 846 | ebitmap_destroy(&p->filename_trans_ttypes); |
792 | while (ft) { | ||
793 | nft = ft->next; | ||
794 | kfree(ft->name); | ||
795 | kfree(ft); | ||
796 | ft = nft; | ||
797 | } | ||
798 | |||
799 | ebitmap_destroy(&p->policycaps); | 847 | ebitmap_destroy(&p->policycaps); |
800 | ebitmap_destroy(&p->permissive_map); | 848 | ebitmap_destroy(&p->permissive_map); |
801 | 849 | ||
@@ -1795,7 +1843,7 @@ static int range_read(struct policydb *p, void *fp) | |||
1795 | rt = NULL; | 1843 | rt = NULL; |
1796 | r = NULL; | 1844 | r = NULL; |
1797 | } | 1845 | } |
1798 | rangetr_hash_eval(p->range_tr); | 1846 | hash_eval(p->range_tr, "rangetr"); |
1799 | rc = 0; | 1847 | rc = 0; |
1800 | out: | 1848 | out: |
1801 | kfree(rt); | 1849 | kfree(rt); |
@@ -1805,9 +1853,10 @@ out: | |||
1805 | 1853 | ||
1806 | static int filename_trans_read(struct policydb *p, void *fp) | 1854 | static int filename_trans_read(struct policydb *p, void *fp) |
1807 | { | 1855 | { |
1808 | struct filename_trans *ft, *last; | 1856 | struct filename_trans *ft; |
1809 | u32 nel, len; | 1857 | struct filename_trans_datum *otype; |
1810 | char *name; | 1858 | char *name; |
1859 | u32 nel, len; | ||
1811 | __le32 buf[4]; | 1860 | __le32 buf[4]; |
1812 | int rc, i; | 1861 | int rc, i; |
1813 | 1862 | ||
@@ -1816,25 +1865,23 @@ static int filename_trans_read(struct policydb *p, void *fp) | |||
1816 | 1865 | ||
1817 | rc = next_entry(buf, fp, sizeof(u32)); | 1866 | rc = next_entry(buf, fp, sizeof(u32)); |
1818 | if (rc) | 1867 | if (rc) |
1819 | goto out; | 1868 | return rc; |
1820 | nel = le32_to_cpu(buf[0]); | 1869 | nel = le32_to_cpu(buf[0]); |
1821 | 1870 | ||
1822 | last = p->filename_trans; | ||
1823 | while (last && last->next) | ||
1824 | last = last->next; | ||
1825 | |||
1826 | for (i = 0; i < nel; i++) { | 1871 | for (i = 0; i < nel; i++) { |
1872 | ft = NULL; | ||
1873 | otype = NULL; | ||
1874 | name = NULL; | ||
1875 | |||
1827 | rc = -ENOMEM; | 1876 | rc = -ENOMEM; |
1828 | ft = kzalloc(sizeof(*ft), GFP_KERNEL); | 1877 | ft = kzalloc(sizeof(*ft), GFP_KERNEL); |
1829 | if (!ft) | 1878 | if (!ft) |
1830 | goto out; | 1879 | goto out; |
1831 | 1880 | ||
1832 | /* add it to the tail of the list */ | 1881 | rc = -ENOMEM; |
1833 | if (!last) | 1882 | otype = kmalloc(sizeof(*otype), GFP_KERNEL); |
1834 | p->filename_trans = ft; | 1883 | if (!otype) |
1835 | else | 1884 | goto out; |
1836 | last->next = ft; | ||
1837 | last = ft; | ||
1838 | 1885 | ||
1839 | /* length of the path component string */ | 1886 | /* length of the path component string */ |
1840 | rc = next_entry(buf, fp, sizeof(u32)); | 1887 | rc = next_entry(buf, fp, sizeof(u32)); |
@@ -1862,10 +1909,22 @@ static int filename_trans_read(struct policydb *p, void *fp) | |||
1862 | ft->stype = le32_to_cpu(buf[0]); | 1909 | ft->stype = le32_to_cpu(buf[0]); |
1863 | ft->ttype = le32_to_cpu(buf[1]); | 1910 | ft->ttype = le32_to_cpu(buf[1]); |
1864 | ft->tclass = le32_to_cpu(buf[2]); | 1911 | ft->tclass = le32_to_cpu(buf[2]); |
1865 | ft->otype = le32_to_cpu(buf[3]); | 1912 | |
1913 | otype->otype = le32_to_cpu(buf[3]); | ||
1914 | |||
1915 | rc = ebitmap_set_bit(&p->filename_trans_ttypes, ft->ttype, 1); | ||
1916 | if (rc) | ||
1917 | goto out; | ||
1918 | |||
1919 | hashtab_insert(p->filename_trans, ft, otype); | ||
1866 | } | 1920 | } |
1867 | rc = 0; | 1921 | hash_eval(p->filename_trans, "filenametr"); |
1922 | return 0; | ||
1868 | out: | 1923 | out: |
1924 | kfree(ft); | ||
1925 | kfree(name); | ||
1926 | kfree(otype); | ||
1927 | |||
1869 | return rc; | 1928 | return rc; |
1870 | } | 1929 | } |
1871 | 1930 | ||
@@ -2266,6 +2325,11 @@ int policydb_read(struct policydb *p, void *fp) | |||
2266 | p->symtab[i].nprim = nprim; | 2325 | p->symtab[i].nprim = nprim; |
2267 | } | 2326 | } |
2268 | 2327 | ||
2328 | rc = -EINVAL; | ||
2329 | p->process_class = string_to_security_class(p, "process"); | ||
2330 | if (!p->process_class) | ||
2331 | goto bad; | ||
2332 | |||
2269 | rc = avtab_read(&p->te_avtab, fp, p); | 2333 | rc = avtab_read(&p->te_avtab, fp, p); |
2270 | if (rc) | 2334 | if (rc) |
2271 | goto bad; | 2335 | goto bad; |
@@ -2298,8 +2362,17 @@ int policydb_read(struct policydb *p, void *fp) | |||
2298 | tr->role = le32_to_cpu(buf[0]); | 2362 | tr->role = le32_to_cpu(buf[0]); |
2299 | tr->type = le32_to_cpu(buf[1]); | 2363 | tr->type = le32_to_cpu(buf[1]); |
2300 | tr->new_role = le32_to_cpu(buf[2]); | 2364 | tr->new_role = le32_to_cpu(buf[2]); |
2365 | if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) { | ||
2366 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2367 | if (rc) | ||
2368 | goto bad; | ||
2369 | tr->tclass = le32_to_cpu(buf[0]); | ||
2370 | } else | ||
2371 | tr->tclass = p->process_class; | ||
2372 | |||
2301 | if (!policydb_role_isvalid(p, tr->role) || | 2373 | if (!policydb_role_isvalid(p, tr->role) || |
2302 | !policydb_type_isvalid(p, tr->type) || | 2374 | !policydb_type_isvalid(p, tr->type) || |
2375 | !policydb_class_isvalid(p, tr->tclass) || | ||
2303 | !policydb_role_isvalid(p, tr->new_role)) | 2376 | !policydb_role_isvalid(p, tr->new_role)) |
2304 | goto bad; | 2377 | goto bad; |
2305 | ltr = tr; | 2378 | ltr = tr; |
@@ -2341,11 +2414,6 @@ int policydb_read(struct policydb *p, void *fp) | |||
2341 | goto bad; | 2414 | goto bad; |
2342 | 2415 | ||
2343 | rc = -EINVAL; | 2416 | rc = -EINVAL; |
2344 | p->process_class = string_to_security_class(p, "process"); | ||
2345 | if (!p->process_class) | ||
2346 | goto bad; | ||
2347 | |||
2348 | rc = -EINVAL; | ||
2349 | p->process_trans_perms = string_to_av_perm(p, p->process_class, "transition"); | 2417 | p->process_trans_perms = string_to_av_perm(p, p->process_class, "transition"); |
2350 | p->process_trans_perms |= string_to_av_perm(p, p->process_class, "dyntransition"); | 2418 | p->process_trans_perms |= string_to_av_perm(p, p->process_class, "dyntransition"); |
2351 | if (!p->process_trans_perms) | 2419 | if (!p->process_trans_perms) |
@@ -2517,8 +2585,9 @@ static int cat_write(void *vkey, void *datum, void *ptr) | |||
2517 | return 0; | 2585 | return 0; |
2518 | } | 2586 | } |
2519 | 2587 | ||
2520 | static int role_trans_write(struct role_trans *r, void *fp) | 2588 | static int role_trans_write(struct policydb *p, void *fp) |
2521 | { | 2589 | { |
2590 | struct role_trans *r = p->role_tr; | ||
2522 | struct role_trans *tr; | 2591 | struct role_trans *tr; |
2523 | u32 buf[3]; | 2592 | u32 buf[3]; |
2524 | size_t nel; | 2593 | size_t nel; |
@@ -2538,6 +2607,12 @@ static int role_trans_write(struct role_trans *r, void *fp) | |||
2538 | rc = put_entry(buf, sizeof(u32), 3, fp); | 2607 | rc = put_entry(buf, sizeof(u32), 3, fp); |
2539 | if (rc) | 2608 | if (rc) |
2540 | return rc; | 2609 | return rc; |
2610 | if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) { | ||
2611 | buf[0] = cpu_to_le32(tr->tclass); | ||
2612 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
2613 | if (rc) | ||
2614 | return rc; | ||
2615 | } | ||
2541 | } | 2616 | } |
2542 | 2617 | ||
2543 | return 0; | 2618 | return 0; |
@@ -3045,7 +3120,7 @@ static int genfs_write(struct policydb *p, void *fp) | |||
3045 | return 0; | 3120 | return 0; |
3046 | } | 3121 | } |
3047 | 3122 | ||
3048 | static int range_count(void *key, void *data, void *ptr) | 3123 | static int hashtab_cnt(void *key, void *data, void *ptr) |
3049 | { | 3124 | { |
3050 | int *cnt = ptr; | 3125 | int *cnt = ptr; |
3051 | *cnt = *cnt + 1; | 3126 | *cnt = *cnt + 1; |
@@ -3093,7 +3168,7 @@ static int range_write(struct policydb *p, void *fp) | |||
3093 | 3168 | ||
3094 | /* count the number of entries in the hashtab */ | 3169 | /* count the number of entries in the hashtab */ |
3095 | nel = 0; | 3170 | nel = 0; |
3096 | rc = hashtab_map(p->range_tr, range_count, &nel); | 3171 | rc = hashtab_map(p->range_tr, hashtab_cnt, &nel); |
3097 | if (rc) | 3172 | if (rc) |
3098 | return rc; | 3173 | return rc; |
3099 | 3174 | ||
@@ -3110,43 +3185,60 @@ static int range_write(struct policydb *p, void *fp) | |||
3110 | return 0; | 3185 | return 0; |
3111 | } | 3186 | } |
3112 | 3187 | ||
3113 | static int filename_trans_write(struct policydb *p, void *fp) | 3188 | static int filename_write_helper(void *key, void *data, void *ptr) |
3114 | { | 3189 | { |
3115 | struct filename_trans *ft; | ||
3116 | u32 len, nel = 0; | ||
3117 | __le32 buf[4]; | 3190 | __le32 buf[4]; |
3191 | struct filename_trans *ft = key; | ||
3192 | struct filename_trans_datum *otype = data; | ||
3193 | void *fp = ptr; | ||
3118 | int rc; | 3194 | int rc; |
3195 | u32 len; | ||
3119 | 3196 | ||
3120 | for (ft = p->filename_trans; ft; ft = ft->next) | 3197 | len = strlen(ft->name); |
3121 | nel++; | 3198 | buf[0] = cpu_to_le32(len); |
3122 | |||
3123 | buf[0] = cpu_to_le32(nel); | ||
3124 | rc = put_entry(buf, sizeof(u32), 1, fp); | 3199 | rc = put_entry(buf, sizeof(u32), 1, fp); |
3125 | if (rc) | 3200 | if (rc) |
3126 | return rc; | 3201 | return rc; |
3127 | 3202 | ||
3128 | for (ft = p->filename_trans; ft; ft = ft->next) { | 3203 | rc = put_entry(ft->name, sizeof(char), len, fp); |
3129 | len = strlen(ft->name); | 3204 | if (rc) |
3130 | buf[0] = cpu_to_le32(len); | 3205 | return rc; |
3131 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
3132 | if (rc) | ||
3133 | return rc; | ||
3134 | 3206 | ||
3135 | rc = put_entry(ft->name, sizeof(char), len, fp); | 3207 | buf[0] = ft->stype; |
3136 | if (rc) | 3208 | buf[1] = ft->ttype; |
3137 | return rc; | 3209 | buf[2] = ft->tclass; |
3210 | buf[3] = otype->otype; | ||
3138 | 3211 | ||
3139 | buf[0] = ft->stype; | 3212 | rc = put_entry(buf, sizeof(u32), 4, fp); |
3140 | buf[1] = ft->ttype; | 3213 | if (rc) |
3141 | buf[2] = ft->tclass; | 3214 | return rc; |
3142 | buf[3] = ft->otype; | ||
3143 | 3215 | ||
3144 | rc = put_entry(buf, sizeof(u32), 4, fp); | ||
3145 | if (rc) | ||
3146 | return rc; | ||
3147 | } | ||
3148 | return 0; | 3216 | return 0; |
3149 | } | 3217 | } |
3218 | |||
3219 | static int filename_trans_write(struct policydb *p, void *fp) | ||
3220 | { | ||
3221 | u32 nel; | ||
3222 | __le32 buf[1]; | ||
3223 | int rc; | ||
3224 | |||
3225 | nel = 0; | ||
3226 | rc = hashtab_map(p->filename_trans, hashtab_cnt, &nel); | ||
3227 | if (rc) | ||
3228 | return rc; | ||
3229 | |||
3230 | buf[0] = cpu_to_le32(nel); | ||
3231 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
3232 | if (rc) | ||
3233 | return rc; | ||
3234 | |||
3235 | rc = hashtab_map(p->filename_trans, filename_write_helper, fp); | ||
3236 | if (rc) | ||
3237 | return rc; | ||
3238 | |||
3239 | return 0; | ||
3240 | } | ||
3241 | |||
3150 | /* | 3242 | /* |
3151 | * Write the configuration data in a policy database | 3243 | * Write the configuration data in a policy database |
3152 | * structure to a policy database binary representation | 3244 | * structure to a policy database binary representation |
@@ -3249,7 +3341,7 @@ int policydb_write(struct policydb *p, void *fp) | |||
3249 | if (rc) | 3341 | if (rc) |
3250 | return rc; | 3342 | return rc; |
3251 | 3343 | ||
3252 | rc = role_trans_write(p->role_tr, fp); | 3344 | rc = role_trans_write(p, fp); |
3253 | if (rc) | 3345 | if (rc) |
3254 | return rc; | 3346 | return rc; |
3255 | 3347 | ||
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 732ea4a68682..b846c0387180 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -72,17 +72,20 @@ struct role_datum { | |||
72 | 72 | ||
73 | struct role_trans { | 73 | struct role_trans { |
74 | u32 role; /* current role */ | 74 | u32 role; /* current role */ |
75 | u32 type; /* program executable type */ | 75 | u32 type; /* program executable type, or new object type */ |
76 | u32 tclass; /* process class, or new object class */ | ||
76 | u32 new_role; /* new role */ | 77 | u32 new_role; /* new role */ |
77 | struct role_trans *next; | 78 | struct role_trans *next; |
78 | }; | 79 | }; |
79 | 80 | ||
80 | struct filename_trans { | 81 | struct filename_trans { |
81 | struct filename_trans *next; | ||
82 | u32 stype; /* current process */ | 82 | u32 stype; /* current process */ |
83 | u32 ttype; /* parent dir context */ | 83 | u32 ttype; /* parent dir context */ |
84 | u16 tclass; /* class of new object */ | 84 | u16 tclass; /* class of new object */ |
85 | const char *name; /* last path component */ | 85 | const char *name; /* last path component */ |
86 | }; | ||
87 | |||
88 | struct filename_trans_datum { | ||
86 | u32 otype; /* expected of new object */ | 89 | u32 otype; /* expected of new object */ |
87 | }; | 90 | }; |
88 | 91 | ||
@@ -227,7 +230,10 @@ struct policydb { | |||
227 | struct role_trans *role_tr; | 230 | struct role_trans *role_tr; |
228 | 231 | ||
229 | /* file transitions with the last path component */ | 232 | /* file transitions with the last path component */ |
230 | struct filename_trans *filename_trans; | 233 | /* quickly exclude lookups when parent ttype has no rules */ |
234 | struct ebitmap filename_trans_ttypes; | ||
235 | /* actual set of filename_trans rules */ | ||
236 | struct hashtab *filename_trans; | ||
231 | 237 | ||
232 | /* bools indexed by (value - 1) */ | 238 | /* bools indexed by (value - 1) */ |
233 | struct cond_bool_datum **bool_val_to_struct; | 239 | struct cond_bool_datum **bool_val_to_struct; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 6ef4af47dac4..c3e4b52699f4 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -1359,26 +1359,35 @@ out: | |||
1359 | } | 1359 | } |
1360 | 1360 | ||
1361 | static void filename_compute_type(struct policydb *p, struct context *newcontext, | 1361 | static void filename_compute_type(struct policydb *p, struct context *newcontext, |
1362 | u32 scon, u32 tcon, u16 tclass, | 1362 | u32 stype, u32 ttype, u16 tclass, |
1363 | const struct qstr *qstr) | 1363 | const char *objname) |
1364 | { | 1364 | { |
1365 | struct filename_trans *ft; | 1365 | struct filename_trans ft; |
1366 | for (ft = p->filename_trans; ft; ft = ft->next) { | 1366 | struct filename_trans_datum *otype; |
1367 | if (ft->stype == scon && | 1367 | |
1368 | ft->ttype == tcon && | 1368 | /* |
1369 | ft->tclass == tclass && | 1369 | * Most filename trans rules are going to live in specific directories |
1370 | !strcmp(ft->name, qstr->name)) { | 1370 | * like /dev or /var/run. This bitmap will quickly skip rule searches |
1371 | newcontext->type = ft->otype; | 1371 | * if the ttype does not contain any rules. |
1372 | return; | 1372 | */ |
1373 | } | 1373 | if (!ebitmap_get_bit(&p->filename_trans_ttypes, ttype)) |
1374 | } | 1374 | return; |
1375 | |||
1376 | ft.stype = stype; | ||
1377 | ft.ttype = ttype; | ||
1378 | ft.tclass = tclass; | ||
1379 | ft.name = objname; | ||
1380 | |||
1381 | otype = hashtab_search(p->filename_trans, &ft); | ||
1382 | if (otype) | ||
1383 | newcontext->type = otype->otype; | ||
1375 | } | 1384 | } |
1376 | 1385 | ||
1377 | static int security_compute_sid(u32 ssid, | 1386 | static int security_compute_sid(u32 ssid, |
1378 | u32 tsid, | 1387 | u32 tsid, |
1379 | u16 orig_tclass, | 1388 | u16 orig_tclass, |
1380 | u32 specified, | 1389 | u32 specified, |
1381 | const struct qstr *qstr, | 1390 | const char *objname, |
1382 | u32 *out_sid, | 1391 | u32 *out_sid, |
1383 | bool kern) | 1392 | bool kern) |
1384 | { | 1393 | { |
@@ -1478,23 +1487,21 @@ static int security_compute_sid(u32 ssid, | |||
1478 | newcontext.type = avdatum->data; | 1487 | newcontext.type = avdatum->data; |
1479 | } | 1488 | } |
1480 | 1489 | ||
1481 | /* if we have a qstr this is a file trans check so check those rules */ | 1490 | /* if we have a objname this is a file trans check so check those rules */ |
1482 | if (qstr) | 1491 | if (objname) |
1483 | filename_compute_type(&policydb, &newcontext, scontext->type, | 1492 | filename_compute_type(&policydb, &newcontext, scontext->type, |
1484 | tcontext->type, tclass, qstr); | 1493 | tcontext->type, tclass, objname); |
1485 | 1494 | ||
1486 | /* Check for class-specific changes. */ | 1495 | /* Check for class-specific changes. */ |
1487 | if (tclass == policydb.process_class) { | 1496 | if (specified & AVTAB_TRANSITION) { |
1488 | if (specified & AVTAB_TRANSITION) { | 1497 | /* Look for a role transition rule. */ |
1489 | /* Look for a role transition rule. */ | 1498 | for (roletr = policydb.role_tr; roletr; roletr = roletr->next) { |
1490 | for (roletr = policydb.role_tr; roletr; | 1499 | if ((roletr->role == scontext->role) && |
1491 | roletr = roletr->next) { | 1500 | (roletr->type == tcontext->type) && |
1492 | if (roletr->role == scontext->role && | 1501 | (roletr->tclass == tclass)) { |
1493 | roletr->type == tcontext->type) { | 1502 | /* Use the role transition rule. */ |
1494 | /* Use the role transition rule. */ | 1503 | newcontext.role = roletr->new_role; |
1495 | newcontext.role = roletr->new_role; | 1504 | break; |
1496 | break; | ||
1497 | } | ||
1498 | } | 1505 | } |
1499 | } | 1506 | } |
1500 | } | 1507 | } |
@@ -1541,13 +1548,14 @@ int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, | |||
1541 | const struct qstr *qstr, u32 *out_sid) | 1548 | const struct qstr *qstr, u32 *out_sid) |
1542 | { | 1549 | { |
1543 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | 1550 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, |
1544 | qstr, out_sid, true); | 1551 | qstr ? qstr->name : NULL, out_sid, true); |
1545 | } | 1552 | } |
1546 | 1553 | ||
1547 | int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid) | 1554 | int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, |
1555 | const char *objname, u32 *out_sid) | ||
1548 | { | 1556 | { |
1549 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | 1557 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, |
1550 | NULL, out_sid, false); | 1558 | objname, out_sid, false); |
1551 | } | 1559 | } |
1552 | 1560 | ||
1553 | /** | 1561 | /** |
@@ -3190,7 +3198,7 @@ out: | |||
3190 | * @len: length of data in bytes | 3198 | * @len: length of data in bytes |
3191 | * | 3199 | * |
3192 | */ | 3200 | */ |
3193 | int security_read_policy(void **data, ssize_t *len) | 3201 | int security_read_policy(void **data, size_t *len) |
3194 | { | 3202 | { |
3195 | int rc; | 3203 | int rc; |
3196 | struct policy_file fp; | 3204 | struct policy_file fp; |
diff --git a/security/smack/smack.h b/security/smack/smack.h index b449cfdad21c..2b6c6a516123 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -316,22 +316,17 @@ static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a, | |||
316 | static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a, | 316 | static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a, |
317 | struct dentry *d) | 317 | struct dentry *d) |
318 | { | 318 | { |
319 | a->a.u.fs.path.dentry = d; | 319 | a->a.u.dentry = d; |
320 | } | ||
321 | static inline void smk_ad_setfield_u_fs_path_mnt(struct smk_audit_info *a, | ||
322 | struct vfsmount *m) | ||
323 | { | ||
324 | a->a.u.fs.path.mnt = m; | ||
325 | } | 320 | } |
326 | static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a, | 321 | static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a, |
327 | struct inode *i) | 322 | struct inode *i) |
328 | { | 323 | { |
329 | a->a.u.fs.inode = i; | 324 | a->a.u.inode = i; |
330 | } | 325 | } |
331 | static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a, | 326 | static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a, |
332 | struct path p) | 327 | struct path p) |
333 | { | 328 | { |
334 | a->a.u.fs.path = p; | 329 | a->a.u.path = p; |
335 | } | 330 | } |
336 | static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a, | 331 | static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a, |
337 | struct sock *sk) | 332 | struct sock *sk) |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 400a5d5cde61..9831a39c11f6 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -383,7 +383,7 @@ static int smack_sb_statfs(struct dentry *dentry) | |||
383 | int rc; | 383 | int rc; |
384 | struct smk_audit_info ad; | 384 | struct smk_audit_info ad; |
385 | 385 | ||
386 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 386 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
387 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 387 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
388 | 388 | ||
389 | rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad); | 389 | rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad); |
@@ -407,7 +407,7 @@ static int smack_sb_mount(char *dev_name, struct path *path, | |||
407 | struct superblock_smack *sbp = path->mnt->mnt_sb->s_security; | 407 | struct superblock_smack *sbp = path->mnt->mnt_sb->s_security; |
408 | struct smk_audit_info ad; | 408 | struct smk_audit_info ad; |
409 | 409 | ||
410 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 410 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
411 | smk_ad_setfield_u_fs_path(&ad, *path); | 411 | smk_ad_setfield_u_fs_path(&ad, *path); |
412 | 412 | ||
413 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); | 413 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); |
@@ -425,10 +425,13 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags) | |||
425 | { | 425 | { |
426 | struct superblock_smack *sbp; | 426 | struct superblock_smack *sbp; |
427 | struct smk_audit_info ad; | 427 | struct smk_audit_info ad; |
428 | struct path path; | ||
428 | 429 | ||
429 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 430 | path.dentry = mnt->mnt_root; |
430 | smk_ad_setfield_u_fs_path_dentry(&ad, mnt->mnt_root); | 431 | path.mnt = mnt; |
431 | smk_ad_setfield_u_fs_path_mnt(&ad, mnt); | 432 | |
433 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
434 | smk_ad_setfield_u_fs_path(&ad, path); | ||
432 | 435 | ||
433 | sbp = mnt->mnt_sb->s_security; | 436 | sbp = mnt->mnt_sb->s_security; |
434 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); | 437 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); |
@@ -563,7 +566,7 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, | |||
563 | struct smk_audit_info ad; | 566 | struct smk_audit_info ad; |
564 | int rc; | 567 | int rc; |
565 | 568 | ||
566 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 569 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
567 | smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry); | 570 | smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry); |
568 | 571 | ||
569 | isp = smk_of_inode(old_dentry->d_inode); | 572 | isp = smk_of_inode(old_dentry->d_inode); |
@@ -592,7 +595,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) | |||
592 | struct smk_audit_info ad; | 595 | struct smk_audit_info ad; |
593 | int rc; | 596 | int rc; |
594 | 597 | ||
595 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 598 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
596 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 599 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
597 | 600 | ||
598 | /* | 601 | /* |
@@ -623,7 +626,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) | |||
623 | struct smk_audit_info ad; | 626 | struct smk_audit_info ad; |
624 | int rc; | 627 | int rc; |
625 | 628 | ||
626 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 629 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
627 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 630 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
628 | 631 | ||
629 | /* | 632 | /* |
@@ -663,7 +666,7 @@ static int smack_inode_rename(struct inode *old_inode, | |||
663 | char *isp; | 666 | char *isp; |
664 | struct smk_audit_info ad; | 667 | struct smk_audit_info ad; |
665 | 668 | ||
666 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 669 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
667 | smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry); | 670 | smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry); |
668 | 671 | ||
669 | isp = smk_of_inode(old_dentry->d_inode); | 672 | isp = smk_of_inode(old_dentry->d_inode); |
@@ -700,7 +703,7 @@ static int smack_inode_permission(struct inode *inode, int mask, unsigned flags) | |||
700 | /* May be droppable after audit */ | 703 | /* May be droppable after audit */ |
701 | if (flags & IPERM_FLAG_RCU) | 704 | if (flags & IPERM_FLAG_RCU) |
702 | return -ECHILD; | 705 | return -ECHILD; |
703 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 706 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); |
704 | smk_ad_setfield_u_fs_inode(&ad, inode); | 707 | smk_ad_setfield_u_fs_inode(&ad, inode); |
705 | return smk_curacc(smk_of_inode(inode), mask, &ad); | 708 | return smk_curacc(smk_of_inode(inode), mask, &ad); |
706 | } | 709 | } |
@@ -720,7 +723,7 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) | |||
720 | */ | 723 | */ |
721 | if (iattr->ia_valid & ATTR_FORCE) | 724 | if (iattr->ia_valid & ATTR_FORCE) |
722 | return 0; | 725 | return 0; |
723 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 726 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
724 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 727 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
725 | 728 | ||
726 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 729 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
@@ -736,10 +739,13 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) | |||
736 | static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | 739 | static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
737 | { | 740 | { |
738 | struct smk_audit_info ad; | 741 | struct smk_audit_info ad; |
742 | struct path path; | ||
739 | 743 | ||
740 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 744 | path.dentry = dentry; |
741 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 745 | path.mnt = mnt; |
742 | smk_ad_setfield_u_fs_path_mnt(&ad, mnt); | 746 | |
747 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
748 | smk_ad_setfield_u_fs_path(&ad, path); | ||
743 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); | 749 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); |
744 | } | 750 | } |
745 | 751 | ||
@@ -784,7 +790,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
784 | } else | 790 | } else |
785 | rc = cap_inode_setxattr(dentry, name, value, size, flags); | 791 | rc = cap_inode_setxattr(dentry, name, value, size, flags); |
786 | 792 | ||
787 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 793 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
788 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 794 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
789 | 795 | ||
790 | if (rc == 0) | 796 | if (rc == 0) |
@@ -845,7 +851,7 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name) | |||
845 | { | 851 | { |
846 | struct smk_audit_info ad; | 852 | struct smk_audit_info ad; |
847 | 853 | ||
848 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 854 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
849 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 855 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
850 | 856 | ||
851 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); | 857 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); |
@@ -877,7 +883,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
877 | } else | 883 | } else |
878 | rc = cap_inode_removexattr(dentry, name); | 884 | rc = cap_inode_removexattr(dentry, name); |
879 | 885 | ||
880 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 886 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
881 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 887 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
882 | if (rc == 0) | 888 | if (rc == 0) |
883 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 889 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
@@ -1047,7 +1053,7 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd, | |||
1047 | int rc = 0; | 1053 | int rc = 0; |
1048 | struct smk_audit_info ad; | 1054 | struct smk_audit_info ad; |
1049 | 1055 | ||
1050 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 1056 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1051 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1057 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1052 | 1058 | ||
1053 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 1059 | if (_IOC_DIR(cmd) & _IOC_WRITE) |
@@ -1070,8 +1076,8 @@ static int smack_file_lock(struct file *file, unsigned int cmd) | |||
1070 | { | 1076 | { |
1071 | struct smk_audit_info ad; | 1077 | struct smk_audit_info ad; |
1072 | 1078 | ||
1073 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 1079 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1074 | smk_ad_setfield_u_fs_path_dentry(&ad, file->f_path.dentry); | 1080 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1075 | return smk_curacc(file->f_security, MAY_WRITE, &ad); | 1081 | return smk_curacc(file->f_security, MAY_WRITE, &ad); |
1076 | } | 1082 | } |
1077 | 1083 | ||
@@ -1089,7 +1095,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1089 | struct smk_audit_info ad; | 1095 | struct smk_audit_info ad; |
1090 | int rc; | 1096 | int rc; |
1091 | 1097 | ||
1092 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 1098 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1093 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1099 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1094 | 1100 | ||
1095 | switch (cmd) { | 1101 | switch (cmd) { |
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 7556315c1978..a0d09e56874b 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -108,10 +108,9 @@ static bool tomoyo_flush(struct tomoyo_io_buffer *head) | |||
108 | head->read_user_buf += len; | 108 | head->read_user_buf += len; |
109 | w += len; | 109 | w += len; |
110 | } | 110 | } |
111 | if (*w) { | 111 | head->r.w[0] = w; |
112 | head->r.w[0] = w; | 112 | if (*w) |
113 | return false; | 113 | return false; |
114 | } | ||
115 | /* Add '\0' for query. */ | 114 | /* Add '\0' for query. */ |
116 | if (head->poll) { | 115 | if (head->poll) { |
117 | if (!head->read_user_buf_avail || | 116 | if (!head->read_user_buf_avail || |
@@ -459,8 +458,16 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) | |||
459 | if (profile == &tomoyo_default_profile) | 458 | if (profile == &tomoyo_default_profile) |
460 | return -EINVAL; | 459 | return -EINVAL; |
461 | if (!strcmp(data, "COMMENT")) { | 460 | if (!strcmp(data, "COMMENT")) { |
462 | const struct tomoyo_path_info *old_comment = profile->comment; | 461 | static DEFINE_SPINLOCK(lock); |
463 | profile->comment = tomoyo_get_name(cp); | 462 | const struct tomoyo_path_info *new_comment |
463 | = tomoyo_get_name(cp); | ||
464 | const struct tomoyo_path_info *old_comment; | ||
465 | if (!new_comment) | ||
466 | return -ENOMEM; | ||
467 | spin_lock(&lock); | ||
468 | old_comment = profile->comment; | ||
469 | profile->comment = new_comment; | ||
470 | spin_unlock(&lock); | ||
464 | tomoyo_put_name(old_comment); | 471 | tomoyo_put_name(old_comment); |
465 | return 0; | 472 | return 0; |
466 | } | 473 | } |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index cb09f1fce910..d64e8ecb6fb3 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -1011,7 +1011,6 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
1011 | break; | 1011 | break; |
1012 | case TOMOYO_TYPE_RMDIR: | 1012 | case TOMOYO_TYPE_RMDIR: |
1013 | case TOMOYO_TYPE_CHROOT: | 1013 | case TOMOYO_TYPE_CHROOT: |
1014 | case TOMOYO_TYPE_UMOUNT: | ||
1015 | tomoyo_add_slash(&buf); | 1014 | tomoyo_add_slash(&buf); |
1016 | break; | 1015 | break; |
1017 | } | 1016 | } |
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c index 297612669c74..42a7b1ba8cbf 100644 --- a/security/tomoyo/memory.c +++ b/security/tomoyo/memory.c | |||
@@ -75,6 +75,7 @@ void *tomoyo_commit_ok(void *data, const unsigned int size) | |||
75 | memset(data, 0, size); | 75 | memset(data, 0, size); |
76 | return ptr; | 76 | return ptr; |
77 | } | 77 | } |
78 | kfree(ptr); | ||
78 | return NULL; | 79 | return NULL; |
79 | } | 80 | } |
80 | 81 | ||
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 82bf8c2390bc..162a864dba24 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c | |||
@@ -143,6 +143,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, | |||
143 | goto out; | 143 | goto out; |
144 | } | 144 | } |
145 | requested_dev_name = tomoyo_realpath_from_path(&path); | 145 | requested_dev_name = tomoyo_realpath_from_path(&path); |
146 | path_put(&path); | ||
146 | if (!requested_dev_name) { | 147 | if (!requested_dev_name) { |
147 | error = -ENOENT; | 148 | error = -ENOENT; |
148 | goto out; | 149 | goto out; |
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 9bfc1ee8222d..6d5393204d95 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c | |||
@@ -390,7 +390,7 @@ bool tomoyo_correct_domain(const unsigned char *domainname) | |||
390 | if (!cp) | 390 | if (!cp) |
391 | break; | 391 | break; |
392 | if (*domainname != '/' || | 392 | if (*domainname != '/' || |
393 | !tomoyo_correct_word2(domainname, cp - domainname - 1)) | 393 | !tomoyo_correct_word2(domainname, cp - domainname)) |
394 | goto out; | 394 | goto out; |
395 | domainname = cp + 1; | 395 | domainname = cp + 1; |
396 | } | 396 | } |