diff options
Diffstat (limited to 'security')
38 files changed, 1359 insertions, 468 deletions
diff --git a/security/Makefile b/security/Makefile index b56e7f9ecbc2..95ecc06392d7 100644 --- a/security/Makefile +++ b/security/Makefile | |||
@@ -16,9 +16,7 @@ obj-$(CONFIG_SECURITYFS) += inode.o | |||
16 | # Must precede capability.o in order to stack properly. | 16 | # Must precede capability.o in order to stack properly. |
17 | obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o | 17 | obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o |
18 | obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o | 18 | obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o |
19 | ifeq ($(CONFIG_AUDIT),y) | 19 | obj-$(CONFIG_AUDIT) += lsm_audit.o |
20 | obj-$(CONFIG_SECURITY_SMACK) += lsm_audit.o | ||
21 | endif | ||
22 | obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o | 20 | obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o |
23 | obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o | 21 | obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o |
24 | obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o | 22 | obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o |
diff --git a/security/capability.c b/security/capability.c index 88f752e8152c..fce07a7bc825 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -373,6 +373,11 @@ static int cap_task_create(unsigned long clone_flags) | |||
373 | return 0; | 373 | return 0; |
374 | } | 374 | } |
375 | 375 | ||
376 | static int cap_cred_alloc_blank(struct cred *cred, gfp_t gfp) | ||
377 | { | ||
378 | return 0; | ||
379 | } | ||
380 | |||
376 | static void cap_cred_free(struct cred *cred) | 381 | static void cap_cred_free(struct cred *cred) |
377 | { | 382 | { |
378 | } | 383 | } |
@@ -386,6 +391,10 @@ static void cap_cred_commit(struct cred *new, const struct cred *old) | |||
386 | { | 391 | { |
387 | } | 392 | } |
388 | 393 | ||
394 | static void cap_cred_transfer(struct cred *new, const struct cred *old) | ||
395 | { | ||
396 | } | ||
397 | |||
389 | static int cap_kernel_act_as(struct cred *new, u32 secid) | 398 | static int cap_kernel_act_as(struct cred *new, u32 secid) |
390 | { | 399 | { |
391 | return 0; | 400 | return 0; |
@@ -396,6 +405,11 @@ static int cap_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
396 | return 0; | 405 | return 0; |
397 | } | 406 | } |
398 | 407 | ||
408 | static int cap_kernel_module_request(void) | ||
409 | { | ||
410 | return 0; | ||
411 | } | ||
412 | |||
399 | static int cap_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | 413 | static int cap_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) |
400 | { | 414 | { |
401 | return 0; | 415 | return 0; |
@@ -701,10 +715,26 @@ static void cap_inet_conn_established(struct sock *sk, struct sk_buff *skb) | |||
701 | { | 715 | { |
702 | } | 716 | } |
703 | 717 | ||
718 | |||
719 | |||
704 | static void cap_req_classify_flow(const struct request_sock *req, | 720 | static void cap_req_classify_flow(const struct request_sock *req, |
705 | struct flowi *fl) | 721 | struct flowi *fl) |
706 | { | 722 | { |
707 | } | 723 | } |
724 | |||
725 | static int cap_tun_dev_create(void) | ||
726 | { | ||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | static void cap_tun_dev_post_create(struct sock *sk) | ||
731 | { | ||
732 | } | ||
733 | |||
734 | static int cap_tun_dev_attach(struct sock *sk) | ||
735 | { | ||
736 | return 0; | ||
737 | } | ||
708 | #endif /* CONFIG_SECURITY_NETWORK */ | 738 | #endif /* CONFIG_SECURITY_NETWORK */ |
709 | 739 | ||
710 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 740 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
@@ -792,6 +822,20 @@ static void cap_release_secctx(char *secdata, u32 seclen) | |||
792 | { | 822 | { |
793 | } | 823 | } |
794 | 824 | ||
825 | static int cap_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
826 | { | ||
827 | return 0; | ||
828 | } | ||
829 | |||
830 | static int cap_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
831 | { | ||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | static int cap_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
836 | { | ||
837 | return 0; | ||
838 | } | ||
795 | #ifdef CONFIG_KEYS | 839 | #ifdef CONFIG_KEYS |
796 | static int cap_key_alloc(struct key *key, const struct cred *cred, | 840 | static int cap_key_alloc(struct key *key, const struct cred *cred, |
797 | unsigned long flags) | 841 | unsigned long flags) |
@@ -815,6 +859,13 @@ static int cap_key_getsecurity(struct key *key, char **_buffer) | |||
815 | return 0; | 859 | return 0; |
816 | } | 860 | } |
817 | 861 | ||
862 | static int cap_key_session_to_parent(const struct cred *cred, | ||
863 | const struct cred *parent_cred, | ||
864 | struct key *key) | ||
865 | { | ||
866 | return 0; | ||
867 | } | ||
868 | |||
818 | #endif /* CONFIG_KEYS */ | 869 | #endif /* CONFIG_KEYS */ |
819 | 870 | ||
820 | #ifdef CONFIG_AUDIT | 871 | #ifdef CONFIG_AUDIT |
@@ -854,7 +905,7 @@ struct security_operations default_security_ops = { | |||
854 | 905 | ||
855 | void security_fixup_ops(struct security_operations *ops) | 906 | void security_fixup_ops(struct security_operations *ops) |
856 | { | 907 | { |
857 | set_to_cap_if_null(ops, ptrace_may_access); | 908 | set_to_cap_if_null(ops, ptrace_access_check); |
858 | set_to_cap_if_null(ops, ptrace_traceme); | 909 | set_to_cap_if_null(ops, ptrace_traceme); |
859 | set_to_cap_if_null(ops, capget); | 910 | set_to_cap_if_null(ops, capget); |
860 | set_to_cap_if_null(ops, capset); | 911 | set_to_cap_if_null(ops, capset); |
@@ -940,11 +991,14 @@ void security_fixup_ops(struct security_operations *ops) | |||
940 | set_to_cap_if_null(ops, file_receive); | 991 | set_to_cap_if_null(ops, file_receive); |
941 | set_to_cap_if_null(ops, dentry_open); | 992 | set_to_cap_if_null(ops, dentry_open); |
942 | set_to_cap_if_null(ops, task_create); | 993 | set_to_cap_if_null(ops, task_create); |
994 | set_to_cap_if_null(ops, cred_alloc_blank); | ||
943 | set_to_cap_if_null(ops, cred_free); | 995 | set_to_cap_if_null(ops, cred_free); |
944 | set_to_cap_if_null(ops, cred_prepare); | 996 | set_to_cap_if_null(ops, cred_prepare); |
945 | set_to_cap_if_null(ops, cred_commit); | 997 | set_to_cap_if_null(ops, cred_commit); |
998 | set_to_cap_if_null(ops, cred_transfer); | ||
946 | set_to_cap_if_null(ops, kernel_act_as); | 999 | set_to_cap_if_null(ops, kernel_act_as); |
947 | set_to_cap_if_null(ops, kernel_create_files_as); | 1000 | set_to_cap_if_null(ops, kernel_create_files_as); |
1001 | set_to_cap_if_null(ops, kernel_module_request); | ||
948 | set_to_cap_if_null(ops, task_setuid); | 1002 | set_to_cap_if_null(ops, task_setuid); |
949 | set_to_cap_if_null(ops, task_fix_setuid); | 1003 | set_to_cap_if_null(ops, task_fix_setuid); |
950 | set_to_cap_if_null(ops, task_setgid); | 1004 | set_to_cap_if_null(ops, task_setgid); |
@@ -992,6 +1046,9 @@ void security_fixup_ops(struct security_operations *ops) | |||
992 | set_to_cap_if_null(ops, secid_to_secctx); | 1046 | set_to_cap_if_null(ops, secid_to_secctx); |
993 | set_to_cap_if_null(ops, secctx_to_secid); | 1047 | set_to_cap_if_null(ops, secctx_to_secid); |
994 | set_to_cap_if_null(ops, release_secctx); | 1048 | set_to_cap_if_null(ops, release_secctx); |
1049 | set_to_cap_if_null(ops, inode_notifysecctx); | ||
1050 | set_to_cap_if_null(ops, inode_setsecctx); | ||
1051 | set_to_cap_if_null(ops, inode_getsecctx); | ||
995 | #ifdef CONFIG_SECURITY_NETWORK | 1052 | #ifdef CONFIG_SECURITY_NETWORK |
996 | set_to_cap_if_null(ops, unix_stream_connect); | 1053 | set_to_cap_if_null(ops, unix_stream_connect); |
997 | set_to_cap_if_null(ops, unix_may_send); | 1054 | set_to_cap_if_null(ops, unix_may_send); |
@@ -1020,6 +1077,9 @@ void security_fixup_ops(struct security_operations *ops) | |||
1020 | set_to_cap_if_null(ops, inet_csk_clone); | 1077 | set_to_cap_if_null(ops, inet_csk_clone); |
1021 | set_to_cap_if_null(ops, inet_conn_established); | 1078 | set_to_cap_if_null(ops, inet_conn_established); |
1022 | set_to_cap_if_null(ops, req_classify_flow); | 1079 | set_to_cap_if_null(ops, req_classify_flow); |
1080 | set_to_cap_if_null(ops, tun_dev_create); | ||
1081 | set_to_cap_if_null(ops, tun_dev_post_create); | ||
1082 | set_to_cap_if_null(ops, tun_dev_attach); | ||
1023 | #endif /* CONFIG_SECURITY_NETWORK */ | 1083 | #endif /* CONFIG_SECURITY_NETWORK */ |
1024 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 1084 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
1025 | set_to_cap_if_null(ops, xfrm_policy_alloc_security); | 1085 | set_to_cap_if_null(ops, xfrm_policy_alloc_security); |
@@ -1038,6 +1098,7 @@ void security_fixup_ops(struct security_operations *ops) | |||
1038 | set_to_cap_if_null(ops, key_free); | 1098 | set_to_cap_if_null(ops, key_free); |
1039 | set_to_cap_if_null(ops, key_permission); | 1099 | set_to_cap_if_null(ops, key_permission); |
1040 | set_to_cap_if_null(ops, key_getsecurity); | 1100 | set_to_cap_if_null(ops, key_getsecurity); |
1101 | set_to_cap_if_null(ops, key_session_to_parent); | ||
1041 | #endif /* CONFIG_KEYS */ | 1102 | #endif /* CONFIG_KEYS */ |
1042 | #ifdef CONFIG_AUDIT | 1103 | #ifdef CONFIG_AUDIT |
1043 | set_to_cap_if_null(ops, audit_rule_init); | 1104 | set_to_cap_if_null(ops, audit_rule_init); |
diff --git a/security/commoncap.c b/security/commoncap.c index e3097c0a1311..fe30751a6cd9 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -101,7 +101,7 @@ int cap_settime(struct timespec *ts, struct timezone *tz) | |||
101 | } | 101 | } |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * cap_ptrace_may_access - Determine whether the current process may access | 104 | * cap_ptrace_access_check - Determine whether the current process may access |
105 | * another | 105 | * another |
106 | * @child: The process to be accessed | 106 | * @child: The process to be accessed |
107 | * @mode: The mode of attachment. | 107 | * @mode: The mode of attachment. |
@@ -109,7 +109,7 @@ int cap_settime(struct timespec *ts, struct timezone *tz) | |||
109 | * Determine whether a process may access another, returning 0 if permission | 109 | * Determine whether a process may access another, returning 0 if permission |
110 | * granted, -ve if denied. | 110 | * granted, -ve if denied. |
111 | */ | 111 | */ |
112 | int cap_ptrace_may_access(struct task_struct *child, unsigned int mode) | 112 | int cap_ptrace_access_check(struct task_struct *child, unsigned int mode) |
113 | { | 113 | { |
114 | int ret = 0; | 114 | int ret = 0; |
115 | 115 | ||
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 4732f5e5d127..b85e61bcf246 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -249,7 +249,11 @@ void ima_counts_put(struct path *path, int mask) | |||
249 | struct inode *inode = path->dentry->d_inode; | 249 | struct inode *inode = path->dentry->d_inode; |
250 | struct ima_iint_cache *iint; | 250 | struct ima_iint_cache *iint; |
251 | 251 | ||
252 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 252 | /* The inode may already have been freed, freeing the iint |
253 | * with it. Verify the inode is not NULL before dereferencing | ||
254 | * it. | ||
255 | */ | ||
256 | if (!ima_initialized || !inode || !S_ISREG(inode->i_mode)) | ||
253 | return; | 257 | return; |
254 | iint = ima_iint_find_insert_get(inode); | 258 | iint = ima_iint_find_insert_get(inode); |
255 | if (!iint) | 259 | if (!iint) |
diff --git a/security/keys/Makefile b/security/keys/Makefile index 747a464943af..74d5447d7df7 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile | |||
@@ -3,6 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := \ | 5 | obj-y := \ |
6 | gc.o \ | ||
6 | key.o \ | 7 | key.o \ |
7 | keyring.o \ | 8 | keyring.o \ |
8 | keyctl.o \ | 9 | keyctl.o \ |
diff --git a/security/keys/compat.c b/security/keys/compat.c index c766c68a63bc..792c0a611a6d 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c | |||
@@ -82,6 +82,9 @@ asmlinkage long compat_sys_keyctl(u32 option, | |||
82 | case KEYCTL_GET_SECURITY: | 82 | case KEYCTL_GET_SECURITY: |
83 | return keyctl_get_security(arg2, compat_ptr(arg3), arg4); | 83 | return keyctl_get_security(arg2, compat_ptr(arg3), arg4); |
84 | 84 | ||
85 | case KEYCTL_SESSION_TO_PARENT: | ||
86 | return keyctl_session_to_parent(); | ||
87 | |||
85 | default: | 88 | default: |
86 | return -EOPNOTSUPP; | 89 | return -EOPNOTSUPP; |
87 | } | 90 | } |
diff --git a/security/keys/gc.c b/security/keys/gc.c new file mode 100644 index 000000000000..485fc6233c38 --- /dev/null +++ b/security/keys/gc.c | |||
@@ -0,0 +1,218 @@ | |||
1 | /* Key garbage collector | ||
2 | * | ||
3 | * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <keys/keyring-type.h> | ||
14 | #include "internal.h" | ||
15 | |||
16 | /* | ||
17 | * Delay between key revocation/expiry in seconds | ||
18 | */ | ||
19 | unsigned key_gc_delay = 5 * 60; | ||
20 | |||
21 | /* | ||
22 | * Reaper | ||
23 | */ | ||
24 | static void key_gc_timer_func(unsigned long); | ||
25 | static void key_garbage_collector(struct work_struct *); | ||
26 | static DEFINE_TIMER(key_gc_timer, key_gc_timer_func, 0, 0); | ||
27 | static DECLARE_WORK(key_gc_work, key_garbage_collector); | ||
28 | static key_serial_t key_gc_cursor; /* the last key the gc considered */ | ||
29 | static bool key_gc_again; | ||
30 | static unsigned long key_gc_executing; | ||
31 | static time_t key_gc_next_run = LONG_MAX; | ||
32 | static time_t key_gc_new_timer; | ||
33 | |||
34 | /* | ||
35 | * Schedule a garbage collection run | ||
36 | * - precision isn't particularly important | ||
37 | */ | ||
38 | void key_schedule_gc(time_t gc_at) | ||
39 | { | ||
40 | unsigned long expires; | ||
41 | time_t now = current_kernel_time().tv_sec; | ||
42 | |||
43 | kenter("%ld", gc_at - now); | ||
44 | |||
45 | if (gc_at <= now) { | ||
46 | schedule_work(&key_gc_work); | ||
47 | } else if (gc_at < key_gc_next_run) { | ||
48 | expires = jiffies + (gc_at - now) * HZ; | ||
49 | mod_timer(&key_gc_timer, expires); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * The garbage collector timer kicked off | ||
55 | */ | ||
56 | static void key_gc_timer_func(unsigned long data) | ||
57 | { | ||
58 | kenter(""); | ||
59 | key_gc_next_run = LONG_MAX; | ||
60 | schedule_work(&key_gc_work); | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * Garbage collect pointers from a keyring | ||
65 | * - return true if we altered the keyring | ||
66 | */ | ||
67 | static bool key_gc_keyring(struct key *keyring, time_t limit) | ||
68 | __releases(key_serial_lock) | ||
69 | { | ||
70 | struct keyring_list *klist; | ||
71 | struct key *key; | ||
72 | int loop; | ||
73 | |||
74 | kenter("%x", key_serial(keyring)); | ||
75 | |||
76 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | ||
77 | goto dont_gc; | ||
78 | |||
79 | /* scan the keyring looking for dead keys */ | ||
80 | klist = rcu_dereference(keyring->payload.subscriptions); | ||
81 | if (!klist) | ||
82 | goto dont_gc; | ||
83 | |||
84 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { | ||
85 | key = klist->keys[loop]; | ||
86 | if (test_bit(KEY_FLAG_DEAD, &key->flags) || | ||
87 | (key->expiry > 0 && key->expiry <= limit)) | ||
88 | goto do_gc; | ||
89 | } | ||
90 | |||
91 | dont_gc: | ||
92 | kleave(" = false"); | ||
93 | return false; | ||
94 | |||
95 | do_gc: | ||
96 | key_gc_cursor = keyring->serial; | ||
97 | key_get(keyring); | ||
98 | spin_unlock(&key_serial_lock); | ||
99 | keyring_gc(keyring, limit); | ||
100 | key_put(keyring); | ||
101 | kleave(" = true"); | ||
102 | return true; | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * Garbage collector for keys | ||
107 | * - this involves scanning the keyrings for dead, expired and revoked keys | ||
108 | * that have overstayed their welcome | ||
109 | */ | ||
110 | static void key_garbage_collector(struct work_struct *work) | ||
111 | { | ||
112 | struct rb_node *rb; | ||
113 | key_serial_t cursor; | ||
114 | struct key *key, *xkey; | ||
115 | time_t new_timer = LONG_MAX, limit, now; | ||
116 | |||
117 | now = current_kernel_time().tv_sec; | ||
118 | kenter("[%x,%ld]", key_gc_cursor, key_gc_new_timer - now); | ||
119 | |||
120 | if (test_and_set_bit(0, &key_gc_executing)) { | ||
121 | key_schedule_gc(current_kernel_time().tv_sec + 1); | ||
122 | kleave(" [busy; deferring]"); | ||
123 | return; | ||
124 | } | ||
125 | |||
126 | limit = now; | ||
127 | if (limit > key_gc_delay) | ||
128 | limit -= key_gc_delay; | ||
129 | else | ||
130 | limit = key_gc_delay; | ||
131 | |||
132 | spin_lock(&key_serial_lock); | ||
133 | |||
134 | if (unlikely(RB_EMPTY_ROOT(&key_serial_tree))) { | ||
135 | spin_unlock(&key_serial_lock); | ||
136 | clear_bit(0, &key_gc_executing); | ||
137 | return; | ||
138 | } | ||
139 | |||
140 | cursor = key_gc_cursor; | ||
141 | if (cursor < 0) | ||
142 | cursor = 0; | ||
143 | if (cursor > 0) | ||
144 | new_timer = key_gc_new_timer; | ||
145 | else | ||
146 | key_gc_again = false; | ||
147 | |||
148 | /* find the first key above the cursor */ | ||
149 | key = NULL; | ||
150 | rb = key_serial_tree.rb_node; | ||
151 | while (rb) { | ||
152 | xkey = rb_entry(rb, struct key, serial_node); | ||
153 | if (cursor < xkey->serial) { | ||
154 | key = xkey; | ||
155 | rb = rb->rb_left; | ||
156 | } else if (cursor > xkey->serial) { | ||
157 | rb = rb->rb_right; | ||
158 | } else { | ||
159 | rb = rb_next(rb); | ||
160 | if (!rb) | ||
161 | goto reached_the_end; | ||
162 | key = rb_entry(rb, struct key, serial_node); | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | if (!key) | ||
168 | goto reached_the_end; | ||
169 | |||
170 | /* trawl through the keys looking for keyrings */ | ||
171 | for (;;) { | ||
172 | if (key->expiry > now && key->expiry < new_timer) { | ||
173 | kdebug("will expire %x in %ld", | ||
174 | key_serial(key), key->expiry - now); | ||
175 | new_timer = key->expiry; | ||
176 | } | ||
177 | |||
178 | if (key->type == &key_type_keyring && | ||
179 | key_gc_keyring(key, limit)) | ||
180 | /* the gc had to release our lock so that the keyring | ||
181 | * could be modified, so we have to get it again */ | ||
182 | goto gc_released_our_lock; | ||
183 | |||
184 | rb = rb_next(&key->serial_node); | ||
185 | if (!rb) | ||
186 | goto reached_the_end; | ||
187 | key = rb_entry(rb, struct key, serial_node); | ||
188 | } | ||
189 | |||
190 | gc_released_our_lock: | ||
191 | kdebug("gc_released_our_lock"); | ||
192 | key_gc_new_timer = new_timer; | ||
193 | key_gc_again = true; | ||
194 | clear_bit(0, &key_gc_executing); | ||
195 | schedule_work(&key_gc_work); | ||
196 | kleave(" [continue]"); | ||
197 | return; | ||
198 | |||
199 | /* when we reach the end of the run, we set the timer for the next one */ | ||
200 | reached_the_end: | ||
201 | kdebug("reached_the_end"); | ||
202 | spin_unlock(&key_serial_lock); | ||
203 | key_gc_new_timer = new_timer; | ||
204 | key_gc_cursor = 0; | ||
205 | clear_bit(0, &key_gc_executing); | ||
206 | |||
207 | if (key_gc_again) { | ||
208 | /* there may have been a key that expired whilst we were | ||
209 | * scanning, so if we discarded any links we should do another | ||
210 | * scan */ | ||
211 | new_timer = now + 1; | ||
212 | key_schedule_gc(new_timer); | ||
213 | } else if (new_timer < LONG_MAX) { | ||
214 | new_timer += key_gc_delay; | ||
215 | key_schedule_gc(new_timer); | ||
216 | } | ||
217 | kleave(" [end]"); | ||
218 | } | ||
diff --git a/security/keys/internal.h b/security/keys/internal.h index 9fb679c66b8a..24ba0307b7ad 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -124,11 +124,18 @@ extern struct key *request_key_and_link(struct key_type *type, | |||
124 | struct key *dest_keyring, | 124 | struct key *dest_keyring, |
125 | unsigned long flags); | 125 | unsigned long flags); |
126 | 126 | ||
127 | extern key_ref_t lookup_user_key(key_serial_t id, int create, int partial, | 127 | extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, |
128 | key_perm_t perm); | 128 | key_perm_t perm); |
129 | #define KEY_LOOKUP_CREATE 0x01 | ||
130 | #define KEY_LOOKUP_PARTIAL 0x02 | ||
131 | #define KEY_LOOKUP_FOR_UNLINK 0x04 | ||
129 | 132 | ||
130 | extern long join_session_keyring(const char *name); | 133 | extern long join_session_keyring(const char *name); |
131 | 134 | ||
135 | extern unsigned key_gc_delay; | ||
136 | extern void keyring_gc(struct key *keyring, time_t limit); | ||
137 | extern void key_schedule_gc(time_t expiry_at); | ||
138 | |||
132 | /* | 139 | /* |
133 | * check to see whether permission is granted to use a key in the desired way | 140 | * check to see whether permission is granted to use a key in the desired way |
134 | */ | 141 | */ |
@@ -194,6 +201,7 @@ extern long keyctl_set_timeout(key_serial_t, unsigned); | |||
194 | extern long keyctl_assume_authority(key_serial_t); | 201 | extern long keyctl_assume_authority(key_serial_t); |
195 | extern long keyctl_get_security(key_serial_t keyid, char __user *buffer, | 202 | extern long keyctl_get_security(key_serial_t keyid, char __user *buffer, |
196 | size_t buflen); | 203 | size_t buflen); |
204 | extern long keyctl_session_to_parent(void); | ||
197 | 205 | ||
198 | /* | 206 | /* |
199 | * debugging key validation | 207 | * debugging key validation |
diff --git a/security/keys/key.c b/security/keys/key.c index 4a1297d1ada4..e50d264c9ad1 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -500,6 +500,7 @@ int key_negate_and_link(struct key *key, | |||
500 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); | 500 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); |
501 | now = current_kernel_time(); | 501 | now = current_kernel_time(); |
502 | key->expiry = now.tv_sec + timeout; | 502 | key->expiry = now.tv_sec + timeout; |
503 | key_schedule_gc(key->expiry + key_gc_delay); | ||
503 | 504 | ||
504 | if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) | 505 | if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) |
505 | awaken = 1; | 506 | awaken = 1; |
@@ -642,10 +643,8 @@ struct key *key_lookup(key_serial_t id) | |||
642 | goto error; | 643 | goto error; |
643 | 644 | ||
644 | found: | 645 | found: |
645 | /* pretend it doesn't exist if it's dead */ | 646 | /* pretend it doesn't exist if it is awaiting deletion */ |
646 | if (atomic_read(&key->usage) == 0 || | 647 | if (atomic_read(&key->usage) == 0) |
647 | test_bit(KEY_FLAG_DEAD, &key->flags) || | ||
648 | key->type == &key_type_dead) | ||
649 | goto not_found; | 648 | goto not_found; |
650 | 649 | ||
651 | /* this races with key_put(), but that doesn't matter since key_put() | 650 | /* this races with key_put(), but that doesn't matter since key_put() |
@@ -890,6 +889,9 @@ EXPORT_SYMBOL(key_update); | |||
890 | */ | 889 | */ |
891 | void key_revoke(struct key *key) | 890 | void key_revoke(struct key *key) |
892 | { | 891 | { |
892 | struct timespec now; | ||
893 | time_t time; | ||
894 | |||
893 | key_check(key); | 895 | key_check(key); |
894 | 896 | ||
895 | /* make sure no one's trying to change or use the key when we mark it | 897 | /* make sure no one's trying to change or use the key when we mark it |
@@ -902,6 +904,14 @@ void key_revoke(struct key *key) | |||
902 | key->type->revoke) | 904 | key->type->revoke) |
903 | key->type->revoke(key); | 905 | key->type->revoke(key); |
904 | 906 | ||
907 | /* set the death time to no more than the expiry time */ | ||
908 | now = current_kernel_time(); | ||
909 | time = now.tv_sec; | ||
910 | if (key->revoked_at == 0 || key->revoked_at > time) { | ||
911 | key->revoked_at = time; | ||
912 | key_schedule_gc(key->revoked_at + key_gc_delay); | ||
913 | } | ||
914 | |||
905 | up_write(&key->sem); | 915 | up_write(&key->sem); |
906 | 916 | ||
907 | } /* end key_revoke() */ | 917 | } /* end key_revoke() */ |
@@ -958,8 +968,10 @@ void unregister_key_type(struct key_type *ktype) | |||
958 | for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { | 968 | for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { |
959 | key = rb_entry(_n, struct key, serial_node); | 969 | key = rb_entry(_n, struct key, serial_node); |
960 | 970 | ||
961 | if (key->type == ktype) | 971 | if (key->type == ktype) { |
962 | key->type = &key_type_dead; | 972 | key->type = &key_type_dead; |
973 | set_bit(KEY_FLAG_DEAD, &key->flags); | ||
974 | } | ||
963 | } | 975 | } |
964 | 976 | ||
965 | spin_unlock(&key_serial_lock); | 977 | spin_unlock(&key_serial_lock); |
@@ -984,6 +996,8 @@ void unregister_key_type(struct key_type *ktype) | |||
984 | spin_unlock(&key_serial_lock); | 996 | spin_unlock(&key_serial_lock); |
985 | up_write(&key_types_sem); | 997 | up_write(&key_types_sem); |
986 | 998 | ||
999 | key_schedule_gc(0); | ||
1000 | |||
987 | } /* end unregister_key_type() */ | 1001 | } /* end unregister_key_type() */ |
988 | 1002 | ||
989 | EXPORT_SYMBOL(unregister_key_type); | 1003 | EXPORT_SYMBOL(unregister_key_type); |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 7f09fb897d2b..2fb28efc5326 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -103,7 +103,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, | |||
103 | } | 103 | } |
104 | 104 | ||
105 | /* find the target keyring (which must be writable) */ | 105 | /* find the target keyring (which must be writable) */ |
106 | keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 106 | keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); |
107 | if (IS_ERR(keyring_ref)) { | 107 | if (IS_ERR(keyring_ref)) { |
108 | ret = PTR_ERR(keyring_ref); | 108 | ret = PTR_ERR(keyring_ref); |
109 | goto error3; | 109 | goto error3; |
@@ -185,7 +185,8 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type, | |||
185 | /* get the destination keyring if specified */ | 185 | /* get the destination keyring if specified */ |
186 | dest_ref = NULL; | 186 | dest_ref = NULL; |
187 | if (destringid) { | 187 | if (destringid) { |
188 | dest_ref = lookup_user_key(destringid, 1, 0, KEY_WRITE); | 188 | dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE, |
189 | KEY_WRITE); | ||
189 | if (IS_ERR(dest_ref)) { | 190 | if (IS_ERR(dest_ref)) { |
190 | ret = PTR_ERR(dest_ref); | 191 | ret = PTR_ERR(dest_ref); |
191 | goto error3; | 192 | goto error3; |
@@ -233,9 +234,11 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type, | |||
233 | long keyctl_get_keyring_ID(key_serial_t id, int create) | 234 | long keyctl_get_keyring_ID(key_serial_t id, int create) |
234 | { | 235 | { |
235 | key_ref_t key_ref; | 236 | key_ref_t key_ref; |
237 | unsigned long lflags; | ||
236 | long ret; | 238 | long ret; |
237 | 239 | ||
238 | key_ref = lookup_user_key(id, create, 0, KEY_SEARCH); | 240 | lflags = create ? KEY_LOOKUP_CREATE : 0; |
241 | key_ref = lookup_user_key(id, lflags, KEY_SEARCH); | ||
239 | if (IS_ERR(key_ref)) { | 242 | if (IS_ERR(key_ref)) { |
240 | ret = PTR_ERR(key_ref); | 243 | ret = PTR_ERR(key_ref); |
241 | goto error; | 244 | goto error; |
@@ -309,7 +312,7 @@ long keyctl_update_key(key_serial_t id, | |||
309 | } | 312 | } |
310 | 313 | ||
311 | /* find the target key (which must be writable) */ | 314 | /* find the target key (which must be writable) */ |
312 | key_ref = lookup_user_key(id, 0, 0, KEY_WRITE); | 315 | key_ref = lookup_user_key(id, 0, KEY_WRITE); |
313 | if (IS_ERR(key_ref)) { | 316 | if (IS_ERR(key_ref)) { |
314 | ret = PTR_ERR(key_ref); | 317 | ret = PTR_ERR(key_ref); |
315 | goto error2; | 318 | goto error2; |
@@ -337,10 +340,16 @@ long keyctl_revoke_key(key_serial_t id) | |||
337 | key_ref_t key_ref; | 340 | key_ref_t key_ref; |
338 | long ret; | 341 | long ret; |
339 | 342 | ||
340 | key_ref = lookup_user_key(id, 0, 0, KEY_WRITE); | 343 | key_ref = lookup_user_key(id, 0, KEY_WRITE); |
341 | if (IS_ERR(key_ref)) { | 344 | if (IS_ERR(key_ref)) { |
342 | ret = PTR_ERR(key_ref); | 345 | ret = PTR_ERR(key_ref); |
343 | goto error; | 346 | if (ret != -EACCES) |
347 | goto error; | ||
348 | key_ref = lookup_user_key(id, 0, KEY_SETATTR); | ||
349 | if (IS_ERR(key_ref)) { | ||
350 | ret = PTR_ERR(key_ref); | ||
351 | goto error; | ||
352 | } | ||
344 | } | 353 | } |
345 | 354 | ||
346 | key_revoke(key_ref_to_ptr(key_ref)); | 355 | key_revoke(key_ref_to_ptr(key_ref)); |
@@ -363,7 +372,7 @@ long keyctl_keyring_clear(key_serial_t ringid) | |||
363 | key_ref_t keyring_ref; | 372 | key_ref_t keyring_ref; |
364 | long ret; | 373 | long ret; |
365 | 374 | ||
366 | keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 375 | keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); |
367 | if (IS_ERR(keyring_ref)) { | 376 | if (IS_ERR(keyring_ref)) { |
368 | ret = PTR_ERR(keyring_ref); | 377 | ret = PTR_ERR(keyring_ref); |
369 | goto error; | 378 | goto error; |
@@ -389,13 +398,13 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid) | |||
389 | key_ref_t keyring_ref, key_ref; | 398 | key_ref_t keyring_ref, key_ref; |
390 | long ret; | 399 | long ret; |
391 | 400 | ||
392 | keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 401 | keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); |
393 | if (IS_ERR(keyring_ref)) { | 402 | if (IS_ERR(keyring_ref)) { |
394 | ret = PTR_ERR(keyring_ref); | 403 | ret = PTR_ERR(keyring_ref); |
395 | goto error; | 404 | goto error; |
396 | } | 405 | } |
397 | 406 | ||
398 | key_ref = lookup_user_key(id, 1, 0, KEY_LINK); | 407 | key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_LINK); |
399 | if (IS_ERR(key_ref)) { | 408 | if (IS_ERR(key_ref)) { |
400 | ret = PTR_ERR(key_ref); | 409 | ret = PTR_ERR(key_ref); |
401 | goto error2; | 410 | goto error2; |
@@ -423,13 +432,13 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) | |||
423 | key_ref_t keyring_ref, key_ref; | 432 | key_ref_t keyring_ref, key_ref; |
424 | long ret; | 433 | long ret; |
425 | 434 | ||
426 | keyring_ref = lookup_user_key(ringid, 0, 0, KEY_WRITE); | 435 | keyring_ref = lookup_user_key(ringid, 0, KEY_WRITE); |
427 | if (IS_ERR(keyring_ref)) { | 436 | if (IS_ERR(keyring_ref)) { |
428 | ret = PTR_ERR(keyring_ref); | 437 | ret = PTR_ERR(keyring_ref); |
429 | goto error; | 438 | goto error; |
430 | } | 439 | } |
431 | 440 | ||
432 | key_ref = lookup_user_key(id, 0, 0, 0); | 441 | key_ref = lookup_user_key(id, KEY_LOOKUP_FOR_UNLINK, 0); |
433 | if (IS_ERR(key_ref)) { | 442 | if (IS_ERR(key_ref)) { |
434 | ret = PTR_ERR(key_ref); | 443 | ret = PTR_ERR(key_ref); |
435 | goto error2; | 444 | goto error2; |
@@ -465,7 +474,7 @@ long keyctl_describe_key(key_serial_t keyid, | |||
465 | char *tmpbuf; | 474 | char *tmpbuf; |
466 | long ret; | 475 | long ret; |
467 | 476 | ||
468 | key_ref = lookup_user_key(keyid, 0, 1, KEY_VIEW); | 477 | key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_VIEW); |
469 | if (IS_ERR(key_ref)) { | 478 | if (IS_ERR(key_ref)) { |
470 | /* viewing a key under construction is permitted if we have the | 479 | /* viewing a key under construction is permitted if we have the |
471 | * authorisation token handy */ | 480 | * authorisation token handy */ |
@@ -474,7 +483,8 @@ long keyctl_describe_key(key_serial_t keyid, | |||
474 | if (!IS_ERR(instkey)) { | 483 | if (!IS_ERR(instkey)) { |
475 | key_put(instkey); | 484 | key_put(instkey); |
476 | key_ref = lookup_user_key(keyid, | 485 | key_ref = lookup_user_key(keyid, |
477 | 0, 1, 0); | 486 | KEY_LOOKUP_PARTIAL, |
487 | 0); | ||
478 | if (!IS_ERR(key_ref)) | 488 | if (!IS_ERR(key_ref)) |
479 | goto okay; | 489 | goto okay; |
480 | } | 490 | } |
@@ -558,7 +568,7 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
558 | } | 568 | } |
559 | 569 | ||
560 | /* get the keyring at which to begin the search */ | 570 | /* get the keyring at which to begin the search */ |
561 | keyring_ref = lookup_user_key(ringid, 0, 0, KEY_SEARCH); | 571 | keyring_ref = lookup_user_key(ringid, 0, KEY_SEARCH); |
562 | if (IS_ERR(keyring_ref)) { | 572 | if (IS_ERR(keyring_ref)) { |
563 | ret = PTR_ERR(keyring_ref); | 573 | ret = PTR_ERR(keyring_ref); |
564 | goto error2; | 574 | goto error2; |
@@ -567,7 +577,8 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
567 | /* get the destination keyring if specified */ | 577 | /* get the destination keyring if specified */ |
568 | dest_ref = NULL; | 578 | dest_ref = NULL; |
569 | if (destringid) { | 579 | if (destringid) { |
570 | dest_ref = lookup_user_key(destringid, 1, 0, KEY_WRITE); | 580 | dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE, |
581 | KEY_WRITE); | ||
571 | if (IS_ERR(dest_ref)) { | 582 | if (IS_ERR(dest_ref)) { |
572 | ret = PTR_ERR(dest_ref); | 583 | ret = PTR_ERR(dest_ref); |
573 | goto error3; | 584 | goto error3; |
@@ -637,7 +648,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) | |||
637 | long ret; | 648 | long ret; |
638 | 649 | ||
639 | /* find the key first */ | 650 | /* find the key first */ |
640 | key_ref = lookup_user_key(keyid, 0, 0, 0); | 651 | key_ref = lookup_user_key(keyid, 0, 0); |
641 | if (IS_ERR(key_ref)) { | 652 | if (IS_ERR(key_ref)) { |
642 | ret = -ENOKEY; | 653 | ret = -ENOKEY; |
643 | goto error; | 654 | goto error; |
@@ -700,7 +711,8 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
700 | if (uid == (uid_t) -1 && gid == (gid_t) -1) | 711 | if (uid == (uid_t) -1 && gid == (gid_t) -1) |
701 | goto error; | 712 | goto error; |
702 | 713 | ||
703 | key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR); | 714 | key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, |
715 | KEY_SETATTR); | ||
704 | if (IS_ERR(key_ref)) { | 716 | if (IS_ERR(key_ref)) { |
705 | ret = PTR_ERR(key_ref); | 717 | ret = PTR_ERR(key_ref); |
706 | goto error; | 718 | goto error; |
@@ -805,7 +817,8 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) | |||
805 | if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) | 817 | if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) |
806 | goto error; | 818 | goto error; |
807 | 819 | ||
808 | key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR); | 820 | key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, |
821 | KEY_SETATTR); | ||
809 | if (IS_ERR(key_ref)) { | 822 | if (IS_ERR(key_ref)) { |
810 | ret = PTR_ERR(key_ref); | 823 | ret = PTR_ERR(key_ref); |
811 | goto error; | 824 | goto error; |
@@ -847,7 +860,7 @@ static long get_instantiation_keyring(key_serial_t ringid, | |||
847 | 860 | ||
848 | /* if a specific keyring is nominated by ID, then use that */ | 861 | /* if a specific keyring is nominated by ID, then use that */ |
849 | if (ringid > 0) { | 862 | if (ringid > 0) { |
850 | dkref = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 863 | dkref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); |
851 | if (IS_ERR(dkref)) | 864 | if (IS_ERR(dkref)) |
852 | return PTR_ERR(dkref); | 865 | return PTR_ERR(dkref); |
853 | *_dest_keyring = key_ref_to_ptr(dkref); | 866 | *_dest_keyring = key_ref_to_ptr(dkref); |
@@ -1083,7 +1096,8 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout) | |||
1083 | time_t expiry; | 1096 | time_t expiry; |
1084 | long ret; | 1097 | long ret; |
1085 | 1098 | ||
1086 | key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR); | 1099 | key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, |
1100 | KEY_SETATTR); | ||
1087 | if (IS_ERR(key_ref)) { | 1101 | if (IS_ERR(key_ref)) { |
1088 | ret = PTR_ERR(key_ref); | 1102 | ret = PTR_ERR(key_ref); |
1089 | goto error; | 1103 | goto error; |
@@ -1101,6 +1115,7 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout) | |||
1101 | } | 1115 | } |
1102 | 1116 | ||
1103 | key->expiry = expiry; | 1117 | key->expiry = expiry; |
1118 | key_schedule_gc(key->expiry + key_gc_delay); | ||
1104 | 1119 | ||
1105 | up_write(&key->sem); | 1120 | up_write(&key->sem); |
1106 | key_put(key); | 1121 | key_put(key); |
@@ -1170,7 +1185,7 @@ long keyctl_get_security(key_serial_t keyid, | |||
1170 | char *context; | 1185 | char *context; |
1171 | long ret; | 1186 | long ret; |
1172 | 1187 | ||
1173 | key_ref = lookup_user_key(keyid, 0, 1, KEY_VIEW); | 1188 | key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_VIEW); |
1174 | if (IS_ERR(key_ref)) { | 1189 | if (IS_ERR(key_ref)) { |
1175 | if (PTR_ERR(key_ref) != -EACCES) | 1190 | if (PTR_ERR(key_ref) != -EACCES) |
1176 | return PTR_ERR(key_ref); | 1191 | return PTR_ERR(key_ref); |
@@ -1182,7 +1197,7 @@ long keyctl_get_security(key_serial_t keyid, | |||
1182 | return PTR_ERR(key_ref); | 1197 | return PTR_ERR(key_ref); |
1183 | key_put(instkey); | 1198 | key_put(instkey); |
1184 | 1199 | ||
1185 | key_ref = lookup_user_key(keyid, 0, 1, 0); | 1200 | key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0); |
1186 | if (IS_ERR(key_ref)) | 1201 | if (IS_ERR(key_ref)) |
1187 | return PTR_ERR(key_ref); | 1202 | return PTR_ERR(key_ref); |
1188 | } | 1203 | } |
@@ -1213,6 +1228,106 @@ long keyctl_get_security(key_serial_t keyid, | |||
1213 | return ret; | 1228 | return ret; |
1214 | } | 1229 | } |
1215 | 1230 | ||
1231 | /* | ||
1232 | * attempt to install the calling process's session keyring on the process's | ||
1233 | * parent process | ||
1234 | * - the keyring must exist and must grant us LINK permission | ||
1235 | * - implements keyctl(KEYCTL_SESSION_TO_PARENT) | ||
1236 | */ | ||
1237 | long keyctl_session_to_parent(void) | ||
1238 | { | ||
1239 | struct task_struct *me, *parent; | ||
1240 | const struct cred *mycred, *pcred; | ||
1241 | struct cred *cred, *oldcred; | ||
1242 | key_ref_t keyring_r; | ||
1243 | int ret; | ||
1244 | |||
1245 | keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK); | ||
1246 | if (IS_ERR(keyring_r)) | ||
1247 | return PTR_ERR(keyring_r); | ||
1248 | |||
1249 | /* our parent is going to need a new cred struct, a new tgcred struct | ||
1250 | * and new security data, so we allocate them here to prevent ENOMEM in | ||
1251 | * our parent */ | ||
1252 | ret = -ENOMEM; | ||
1253 | cred = cred_alloc_blank(); | ||
1254 | if (!cred) | ||
1255 | goto error_keyring; | ||
1256 | |||
1257 | cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); | ||
1258 | keyring_r = NULL; | ||
1259 | |||
1260 | me = current; | ||
1261 | write_lock_irq(&tasklist_lock); | ||
1262 | |||
1263 | parent = me->real_parent; | ||
1264 | ret = -EPERM; | ||
1265 | |||
1266 | /* the parent mustn't be init and mustn't be a kernel thread */ | ||
1267 | if (parent->pid <= 1 || !parent->mm) | ||
1268 | goto not_permitted; | ||
1269 | |||
1270 | /* the parent must be single threaded */ | ||
1271 | if (atomic_read(&parent->signal->count) != 1) | ||
1272 | goto not_permitted; | ||
1273 | |||
1274 | /* the parent and the child must have different session keyrings or | ||
1275 | * there's no point */ | ||
1276 | mycred = current_cred(); | ||
1277 | pcred = __task_cred(parent); | ||
1278 | if (mycred == pcred || | ||
1279 | mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) | ||
1280 | goto already_same; | ||
1281 | |||
1282 | /* the parent must have the same effective ownership and mustn't be | ||
1283 | * SUID/SGID */ | ||
1284 | if (pcred-> uid != mycred->euid || | ||
1285 | pcred->euid != mycred->euid || | ||
1286 | pcred->suid != mycred->euid || | ||
1287 | pcred-> gid != mycred->egid || | ||
1288 | pcred->egid != mycred->egid || | ||
1289 | pcred->sgid != mycred->egid) | ||
1290 | goto not_permitted; | ||
1291 | |||
1292 | /* the keyrings must have the same UID */ | ||
1293 | if (pcred ->tgcred->session_keyring->uid != mycred->euid || | ||
1294 | mycred->tgcred->session_keyring->uid != mycred->euid) | ||
1295 | goto not_permitted; | ||
1296 | |||
1297 | /* the LSM must permit the replacement of the parent's keyring with the | ||
1298 | * keyring from this process */ | ||
1299 | ret = security_key_session_to_parent(mycred, pcred, | ||
1300 | key_ref_to_ptr(keyring_r)); | ||
1301 | if (ret < 0) | ||
1302 | goto not_permitted; | ||
1303 | |||
1304 | /* if there's an already pending keyring replacement, then we replace | ||
1305 | * that */ | ||
1306 | oldcred = parent->replacement_session_keyring; | ||
1307 | |||
1308 | /* the replacement session keyring is applied just prior to userspace | ||
1309 | * restarting */ | ||
1310 | parent->replacement_session_keyring = cred; | ||
1311 | cred = NULL; | ||
1312 | set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME); | ||
1313 | |||
1314 | write_unlock_irq(&tasklist_lock); | ||
1315 | if (oldcred) | ||
1316 | put_cred(oldcred); | ||
1317 | return 0; | ||
1318 | |||
1319 | already_same: | ||
1320 | ret = 0; | ||
1321 | not_permitted: | ||
1322 | write_unlock_irq(&tasklist_lock); | ||
1323 | put_cred(cred); | ||
1324 | return ret; | ||
1325 | |||
1326 | error_keyring: | ||
1327 | key_ref_put(keyring_r); | ||
1328 | return ret; | ||
1329 | } | ||
1330 | |||
1216 | /*****************************************************************************/ | 1331 | /*****************************************************************************/ |
1217 | /* | 1332 | /* |
1218 | * the key control system call | 1333 | * the key control system call |
@@ -1298,6 +1413,9 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
1298 | (char __user *) arg3, | 1413 | (char __user *) arg3, |
1299 | (size_t) arg4); | 1414 | (size_t) arg4); |
1300 | 1415 | ||
1416 | case KEYCTL_SESSION_TO_PARENT: | ||
1417 | return keyctl_session_to_parent(); | ||
1418 | |||
1301 | default: | 1419 | default: |
1302 | return -EOPNOTSUPP; | 1420 | return -EOPNOTSUPP; |
1303 | } | 1421 | } |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 3dba81c2eba3..8ec02746ca99 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -1000,3 +1000,102 @@ static void keyring_revoke(struct key *keyring) | |||
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | } /* end keyring_revoke() */ | 1002 | } /* end keyring_revoke() */ |
1003 | |||
1004 | /* | ||
1005 | * Determine whether a key is dead | ||
1006 | */ | ||
1007 | static bool key_is_dead(struct key *key, time_t limit) | ||
1008 | { | ||
1009 | return test_bit(KEY_FLAG_DEAD, &key->flags) || | ||
1010 | (key->expiry > 0 && key->expiry <= limit); | ||
1011 | } | ||
1012 | |||
1013 | /* | ||
1014 | * Collect garbage from the contents of a keyring | ||
1015 | */ | ||
1016 | void keyring_gc(struct key *keyring, time_t limit) | ||
1017 | { | ||
1018 | struct keyring_list *klist, *new; | ||
1019 | struct key *key; | ||
1020 | int loop, keep, max; | ||
1021 | |||
1022 | kenter("{%x,%s}", key_serial(keyring), keyring->description); | ||
1023 | |||
1024 | down_write(&keyring->sem); | ||
1025 | |||
1026 | klist = keyring->payload.subscriptions; | ||
1027 | if (!klist) | ||
1028 | goto no_klist; | ||
1029 | |||
1030 | /* work out how many subscriptions we're keeping */ | ||
1031 | keep = 0; | ||
1032 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | ||
1033 | if (!key_is_dead(klist->keys[loop], limit)) | ||
1034 | keep++; | ||
1035 | |||
1036 | if (keep == klist->nkeys) | ||
1037 | goto just_return; | ||
1038 | |||
1039 | /* allocate a new keyring payload */ | ||
1040 | max = roundup(keep, 4); | ||
1041 | new = kmalloc(sizeof(struct keyring_list) + max * sizeof(struct key *), | ||
1042 | GFP_KERNEL); | ||
1043 | if (!new) | ||
1044 | goto nomem; | ||
1045 | new->maxkeys = max; | ||
1046 | new->nkeys = 0; | ||
1047 | new->delkey = 0; | ||
1048 | |||
1049 | /* install the live keys | ||
1050 | * - must take care as expired keys may be updated back to life | ||
1051 | */ | ||
1052 | keep = 0; | ||
1053 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { | ||
1054 | key = klist->keys[loop]; | ||
1055 | if (!key_is_dead(key, limit)) { | ||
1056 | if (keep >= max) | ||
1057 | goto discard_new; | ||
1058 | new->keys[keep++] = key_get(key); | ||
1059 | } | ||
1060 | } | ||
1061 | new->nkeys = keep; | ||
1062 | |||
1063 | /* adjust the quota */ | ||
1064 | key_payload_reserve(keyring, | ||
1065 | sizeof(struct keyring_list) + | ||
1066 | KEYQUOTA_LINK_BYTES * keep); | ||
1067 | |||
1068 | if (keep == 0) { | ||
1069 | rcu_assign_pointer(keyring->payload.subscriptions, NULL); | ||
1070 | kfree(new); | ||
1071 | } else { | ||
1072 | rcu_assign_pointer(keyring->payload.subscriptions, new); | ||
1073 | } | ||
1074 | |||
1075 | up_write(&keyring->sem); | ||
1076 | |||
1077 | call_rcu(&klist->rcu, keyring_clear_rcu_disposal); | ||
1078 | kleave(" [yes]"); | ||
1079 | return; | ||
1080 | |||
1081 | discard_new: | ||
1082 | new->nkeys = keep; | ||
1083 | keyring_clear_rcu_disposal(&new->rcu); | ||
1084 | up_write(&keyring->sem); | ||
1085 | kleave(" [discard]"); | ||
1086 | return; | ||
1087 | |||
1088 | just_return: | ||
1089 | up_write(&keyring->sem); | ||
1090 | kleave(" [no dead]"); | ||
1091 | return; | ||
1092 | |||
1093 | no_klist: | ||
1094 | up_write(&keyring->sem); | ||
1095 | kleave(" [no_klist]"); | ||
1096 | return; | ||
1097 | |||
1098 | nomem: | ||
1099 | up_write(&keyring->sem); | ||
1100 | kleave(" [oom]"); | ||
1101 | } | ||
diff --git a/security/keys/proc.c b/security/keys/proc.c index 769f9bdfd2b3..9d01021ca0c8 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -91,59 +91,94 @@ __initcall(key_proc_init); | |||
91 | */ | 91 | */ |
92 | #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS | 92 | #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS |
93 | 93 | ||
94 | static struct rb_node *__key_serial_next(struct rb_node *n) | 94 | static struct rb_node *key_serial_next(struct rb_node *n) |
95 | { | 95 | { |
96 | struct user_namespace *user_ns = current_user_ns(); | ||
97 | |||
98 | n = rb_next(n); | ||
96 | while (n) { | 99 | while (n) { |
97 | struct key *key = rb_entry(n, struct key, serial_node); | 100 | struct key *key = rb_entry(n, struct key, serial_node); |
98 | if (key->user->user_ns == current_user_ns()) | 101 | if (key->user->user_ns == user_ns) |
99 | break; | 102 | break; |
100 | n = rb_next(n); | 103 | n = rb_next(n); |
101 | } | 104 | } |
102 | return n; | 105 | return n; |
103 | } | 106 | } |
104 | 107 | ||
105 | static struct rb_node *key_serial_next(struct rb_node *n) | 108 | static int proc_keys_open(struct inode *inode, struct file *file) |
106 | { | 109 | { |
107 | return __key_serial_next(rb_next(n)); | 110 | return seq_open(file, &proc_keys_ops); |
108 | } | 111 | } |
109 | 112 | ||
110 | static struct rb_node *key_serial_first(struct rb_root *r) | 113 | static struct key *find_ge_key(key_serial_t id) |
111 | { | 114 | { |
112 | struct rb_node *n = rb_first(r); | 115 | struct user_namespace *user_ns = current_user_ns(); |
113 | return __key_serial_next(n); | 116 | struct rb_node *n = key_serial_tree.rb_node; |
114 | } | 117 | struct key *minkey = NULL; |
115 | 118 | ||
116 | static int proc_keys_open(struct inode *inode, struct file *file) | 119 | while (n) { |
117 | { | 120 | struct key *key = rb_entry(n, struct key, serial_node); |
118 | return seq_open(file, &proc_keys_ops); | 121 | if (id < key->serial) { |
122 | if (!minkey || minkey->serial > key->serial) | ||
123 | minkey = key; | ||
124 | n = n->rb_left; | ||
125 | } else if (id > key->serial) { | ||
126 | n = n->rb_right; | ||
127 | } else { | ||
128 | minkey = key; | ||
129 | break; | ||
130 | } | ||
131 | key = NULL; | ||
132 | } | ||
119 | 133 | ||
134 | if (!minkey) | ||
135 | return NULL; | ||
136 | |||
137 | for (;;) { | ||
138 | if (minkey->user->user_ns == user_ns) | ||
139 | return minkey; | ||
140 | n = rb_next(&minkey->serial_node); | ||
141 | if (!n) | ||
142 | return NULL; | ||
143 | minkey = rb_entry(n, struct key, serial_node); | ||
144 | } | ||
120 | } | 145 | } |
121 | 146 | ||
122 | static void *proc_keys_start(struct seq_file *p, loff_t *_pos) | 147 | static void *proc_keys_start(struct seq_file *p, loff_t *_pos) |
148 | __acquires(key_serial_lock) | ||
123 | { | 149 | { |
124 | struct rb_node *_p; | 150 | key_serial_t pos = *_pos; |
125 | loff_t pos = *_pos; | 151 | struct key *key; |
126 | 152 | ||
127 | spin_lock(&key_serial_lock); | 153 | spin_lock(&key_serial_lock); |
128 | 154 | ||
129 | _p = key_serial_first(&key_serial_tree); | 155 | if (*_pos > INT_MAX) |
130 | while (pos > 0 && _p) { | 156 | return NULL; |
131 | pos--; | 157 | key = find_ge_key(pos); |
132 | _p = key_serial_next(_p); | 158 | if (!key) |
133 | } | 159 | return NULL; |
134 | 160 | *_pos = key->serial; | |
135 | return _p; | 161 | return &key->serial_node; |
162 | } | ||
136 | 163 | ||
164 | static inline key_serial_t key_node_serial(struct rb_node *n) | ||
165 | { | ||
166 | struct key *key = rb_entry(n, struct key, serial_node); | ||
167 | return key->serial; | ||
137 | } | 168 | } |
138 | 169 | ||
139 | static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos) | 170 | static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos) |
140 | { | 171 | { |
141 | (*_pos)++; | 172 | struct rb_node *n; |
142 | return key_serial_next((struct rb_node *) v); | ||
143 | 173 | ||
174 | n = key_serial_next(v); | ||
175 | if (n) | ||
176 | *_pos = key_node_serial(n); | ||
177 | return n; | ||
144 | } | 178 | } |
145 | 179 | ||
146 | static void proc_keys_stop(struct seq_file *p, void *v) | 180 | static void proc_keys_stop(struct seq_file *p, void *v) |
181 | __releases(key_serial_lock) | ||
147 | { | 182 | { |
148 | spin_unlock(&key_serial_lock); | 183 | spin_unlock(&key_serial_lock); |
149 | } | 184 | } |
@@ -174,11 +209,9 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
174 | /* come up with a suitable timeout value */ | 209 | /* come up with a suitable timeout value */ |
175 | if (key->expiry == 0) { | 210 | if (key->expiry == 0) { |
176 | memcpy(xbuf, "perm", 5); | 211 | memcpy(xbuf, "perm", 5); |
177 | } | 212 | } else if (now.tv_sec >= key->expiry) { |
178 | else if (now.tv_sec >= key->expiry) { | ||
179 | memcpy(xbuf, "expd", 5); | 213 | memcpy(xbuf, "expd", 5); |
180 | } | 214 | } else { |
181 | else { | ||
182 | timo = key->expiry - now.tv_sec; | 215 | timo = key->expiry - now.tv_sec; |
183 | 216 | ||
184 | if (timo < 60) | 217 | if (timo < 60) |
@@ -218,9 +251,7 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
218 | seq_putc(m, '\n'); | 251 | seq_putc(m, '\n'); |
219 | 252 | ||
220 | rcu_read_unlock(); | 253 | rcu_read_unlock(); |
221 | |||
222 | return 0; | 254 | return 0; |
223 | |||
224 | } | 255 | } |
225 | 256 | ||
226 | #endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */ | 257 | #endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */ |
@@ -246,6 +277,7 @@ static struct rb_node *key_user_first(struct rb_root *r) | |||
246 | struct rb_node *n = rb_first(r); | 277 | struct rb_node *n = rb_first(r); |
247 | return __key_user_next(n); | 278 | return __key_user_next(n); |
248 | } | 279 | } |
280 | |||
249 | /*****************************************************************************/ | 281 | /*****************************************************************************/ |
250 | /* | 282 | /* |
251 | * implement "/proc/key-users" to provides a list of the key users | 283 | * implement "/proc/key-users" to provides a list of the key users |
@@ -253,10 +285,10 @@ static struct rb_node *key_user_first(struct rb_root *r) | |||
253 | static int proc_key_users_open(struct inode *inode, struct file *file) | 285 | static int proc_key_users_open(struct inode *inode, struct file *file) |
254 | { | 286 | { |
255 | return seq_open(file, &proc_key_users_ops); | 287 | return seq_open(file, &proc_key_users_ops); |
256 | |||
257 | } | 288 | } |
258 | 289 | ||
259 | static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) | 290 | static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) |
291 | __acquires(key_user_lock) | ||
260 | { | 292 | { |
261 | struct rb_node *_p; | 293 | struct rb_node *_p; |
262 | loff_t pos = *_pos; | 294 | loff_t pos = *_pos; |
@@ -270,17 +302,16 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) | |||
270 | } | 302 | } |
271 | 303 | ||
272 | return _p; | 304 | return _p; |
273 | |||
274 | } | 305 | } |
275 | 306 | ||
276 | static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) | 307 | static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) |
277 | { | 308 | { |
278 | (*_pos)++; | 309 | (*_pos)++; |
279 | return key_user_next((struct rb_node *) v); | 310 | return key_user_next((struct rb_node *) v); |
280 | |||
281 | } | 311 | } |
282 | 312 | ||
283 | static void proc_key_users_stop(struct seq_file *p, void *v) | 313 | static void proc_key_users_stop(struct seq_file *p, void *v) |
314 | __releases(key_user_lock) | ||
284 | { | 315 | { |
285 | spin_unlock(&key_user_lock); | 316 | spin_unlock(&key_user_lock); |
286 | } | 317 | } |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 276d27882ce8..5c23afb31ece 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
20 | #include <linux/security.h> | ||
20 | #include <linux/user_namespace.h> | 21 | #include <linux/user_namespace.h> |
21 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
22 | #include "internal.h" | 23 | #include "internal.h" |
@@ -487,7 +488,7 @@ static int lookup_user_key_possessed(const struct key *key, const void *target) | |||
487 | * - don't create special keyrings unless so requested | 488 | * - don't create special keyrings unless so requested |
488 | * - partially constructed keys aren't found unless requested | 489 | * - partially constructed keys aren't found unless requested |
489 | */ | 490 | */ |
490 | key_ref_t lookup_user_key(key_serial_t id, int create, int partial, | 491 | key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, |
491 | key_perm_t perm) | 492 | key_perm_t perm) |
492 | { | 493 | { |
493 | struct request_key_auth *rka; | 494 | struct request_key_auth *rka; |
@@ -503,7 +504,7 @@ try_again: | |||
503 | switch (id) { | 504 | switch (id) { |
504 | case KEY_SPEC_THREAD_KEYRING: | 505 | case KEY_SPEC_THREAD_KEYRING: |
505 | if (!cred->thread_keyring) { | 506 | if (!cred->thread_keyring) { |
506 | if (!create) | 507 | if (!(lflags & KEY_LOOKUP_CREATE)) |
507 | goto error; | 508 | goto error; |
508 | 509 | ||
509 | ret = install_thread_keyring(); | 510 | ret = install_thread_keyring(); |
@@ -521,7 +522,7 @@ try_again: | |||
521 | 522 | ||
522 | case KEY_SPEC_PROCESS_KEYRING: | 523 | case KEY_SPEC_PROCESS_KEYRING: |
523 | if (!cred->tgcred->process_keyring) { | 524 | if (!cred->tgcred->process_keyring) { |
524 | if (!create) | 525 | if (!(lflags & KEY_LOOKUP_CREATE)) |
525 | goto error; | 526 | goto error; |
526 | 527 | ||
527 | ret = install_process_keyring(); | 528 | ret = install_process_keyring(); |
@@ -642,7 +643,14 @@ try_again: | |||
642 | break; | 643 | break; |
643 | } | 644 | } |
644 | 645 | ||
645 | if (!partial) { | 646 | /* unlink does not use the nominated key in any way, so can skip all |
647 | * the permission checks as it is only concerned with the keyring */ | ||
648 | if (lflags & KEY_LOOKUP_FOR_UNLINK) { | ||
649 | ret = 0; | ||
650 | goto error; | ||
651 | } | ||
652 | |||
653 | if (!(lflags & KEY_LOOKUP_PARTIAL)) { | ||
646 | ret = wait_for_key_construction(key, true); | 654 | ret = wait_for_key_construction(key, true); |
647 | switch (ret) { | 655 | switch (ret) { |
648 | case -ERESTARTSYS: | 656 | case -ERESTARTSYS: |
@@ -660,7 +668,8 @@ try_again: | |||
660 | } | 668 | } |
661 | 669 | ||
662 | ret = -EIO; | 670 | ret = -EIO; |
663 | if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) | 671 | if (!(lflags & KEY_LOOKUP_PARTIAL) && |
672 | !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) | ||
664 | goto invalid_key; | 673 | goto invalid_key; |
665 | 674 | ||
666 | /* check the permissions */ | 675 | /* check the permissions */ |
@@ -702,7 +711,7 @@ long join_session_keyring(const char *name) | |||
702 | /* only permit this if there's a single thread in the thread group - | 711 | /* only permit this if there's a single thread in the thread group - |
703 | * this avoids us having to adjust the creds on all threads and risking | 712 | * this avoids us having to adjust the creds on all threads and risking |
704 | * ENOMEM */ | 713 | * ENOMEM */ |
705 | if (!is_single_threaded(current)) | 714 | if (!current_is_single_threaded()) |
706 | return -EMLINK; | 715 | return -EMLINK; |
707 | 716 | ||
708 | new = prepare_creds(); | 717 | new = prepare_creds(); |
@@ -760,3 +769,51 @@ error: | |||
760 | abort_creds(new); | 769 | abort_creds(new); |
761 | return ret; | 770 | return ret; |
762 | } | 771 | } |
772 | |||
773 | /* | ||
774 | * Replace a process's session keyring when that process resumes userspace on | ||
775 | * behalf of one of its children | ||
776 | */ | ||
777 | void key_replace_session_keyring(void) | ||
778 | { | ||
779 | const struct cred *old; | ||
780 | struct cred *new; | ||
781 | |||
782 | if (!current->replacement_session_keyring) | ||
783 | return; | ||
784 | |||
785 | write_lock_irq(&tasklist_lock); | ||
786 | new = current->replacement_session_keyring; | ||
787 | current->replacement_session_keyring = NULL; | ||
788 | write_unlock_irq(&tasklist_lock); | ||
789 | |||
790 | if (!new) | ||
791 | return; | ||
792 | |||
793 | old = current_cred(); | ||
794 | new-> uid = old-> uid; | ||
795 | new-> euid = old-> euid; | ||
796 | new-> suid = old-> suid; | ||
797 | new->fsuid = old->fsuid; | ||
798 | new-> gid = old-> gid; | ||
799 | new-> egid = old-> egid; | ||
800 | new-> sgid = old-> sgid; | ||
801 | new->fsgid = old->fsgid; | ||
802 | new->user = get_uid(old->user); | ||
803 | new->group_info = get_group_info(old->group_info); | ||
804 | |||
805 | new->securebits = old->securebits; | ||
806 | new->cap_inheritable = old->cap_inheritable; | ||
807 | new->cap_permitted = old->cap_permitted; | ||
808 | new->cap_effective = old->cap_effective; | ||
809 | new->cap_bset = old->cap_bset; | ||
810 | |||
811 | new->jit_keyring = old->jit_keyring; | ||
812 | new->thread_keyring = key_get(old->thread_keyring); | ||
813 | new->tgcred->tgid = old->tgcred->tgid; | ||
814 | new->tgcred->process_keyring = key_get(old->tgcred->process_keyring); | ||
815 | |||
816 | security_transfer_creds(new, old); | ||
817 | |||
818 | commit_creds(new); | ||
819 | } | ||
diff --git a/security/keys/sysctl.c b/security/keys/sysctl.c index b611d493c2d8..5e05dc09e2db 100644 --- a/security/keys/sysctl.c +++ b/security/keys/sysctl.c | |||
@@ -13,6 +13,8 @@ | |||
13 | #include <linux/sysctl.h> | 13 | #include <linux/sysctl.h> |
14 | #include "internal.h" | 14 | #include "internal.h" |
15 | 15 | ||
16 | static const int zero, one = 1, max = INT_MAX; | ||
17 | |||
16 | ctl_table key_sysctls[] = { | 18 | ctl_table key_sysctls[] = { |
17 | { | 19 | { |
18 | .ctl_name = CTL_UNNUMBERED, | 20 | .ctl_name = CTL_UNNUMBERED, |
@@ -20,7 +22,9 @@ ctl_table key_sysctls[] = { | |||
20 | .data = &key_quota_maxkeys, | 22 | .data = &key_quota_maxkeys, |
21 | .maxlen = sizeof(unsigned), | 23 | .maxlen = sizeof(unsigned), |
22 | .mode = 0644, | 24 | .mode = 0644, |
23 | .proc_handler = &proc_dointvec, | 25 | .proc_handler = &proc_dointvec_minmax, |
26 | .extra1 = (void *) &one, | ||
27 | .extra2 = (void *) &max, | ||
24 | }, | 28 | }, |
25 | { | 29 | { |
26 | .ctl_name = CTL_UNNUMBERED, | 30 | .ctl_name = CTL_UNNUMBERED, |
@@ -28,7 +32,9 @@ ctl_table key_sysctls[] = { | |||
28 | .data = &key_quota_maxbytes, | 32 | .data = &key_quota_maxbytes, |
29 | .maxlen = sizeof(unsigned), | 33 | .maxlen = sizeof(unsigned), |
30 | .mode = 0644, | 34 | .mode = 0644, |
31 | .proc_handler = &proc_dointvec, | 35 | .proc_handler = &proc_dointvec_minmax, |
36 | .extra1 = (void *) &one, | ||
37 | .extra2 = (void *) &max, | ||
32 | }, | 38 | }, |
33 | { | 39 | { |
34 | .ctl_name = CTL_UNNUMBERED, | 40 | .ctl_name = CTL_UNNUMBERED, |
@@ -36,7 +42,9 @@ ctl_table key_sysctls[] = { | |||
36 | .data = &key_quota_root_maxkeys, | 42 | .data = &key_quota_root_maxkeys, |
37 | .maxlen = sizeof(unsigned), | 43 | .maxlen = sizeof(unsigned), |
38 | .mode = 0644, | 44 | .mode = 0644, |
39 | .proc_handler = &proc_dointvec, | 45 | .proc_handler = &proc_dointvec_minmax, |
46 | .extra1 = (void *) &one, | ||
47 | .extra2 = (void *) &max, | ||
40 | }, | 48 | }, |
41 | { | 49 | { |
42 | .ctl_name = CTL_UNNUMBERED, | 50 | .ctl_name = CTL_UNNUMBERED, |
@@ -44,7 +52,19 @@ ctl_table key_sysctls[] = { | |||
44 | .data = &key_quota_root_maxbytes, | 52 | .data = &key_quota_root_maxbytes, |
45 | .maxlen = sizeof(unsigned), | 53 | .maxlen = sizeof(unsigned), |
46 | .mode = 0644, | 54 | .mode = 0644, |
47 | .proc_handler = &proc_dointvec, | 55 | .proc_handler = &proc_dointvec_minmax, |
56 | .extra1 = (void *) &one, | ||
57 | .extra2 = (void *) &max, | ||
58 | }, | ||
59 | { | ||
60 | .ctl_name = CTL_UNNUMBERED, | ||
61 | .procname = "gc_delay", | ||
62 | .data = &key_gc_delay, | ||
63 | .maxlen = sizeof(unsigned), | ||
64 | .mode = 0644, | ||
65 | .proc_handler = &proc_dointvec_minmax, | ||
66 | .extra1 = (void *) &zero, | ||
67 | .extra2 = (void *) &max, | ||
48 | }, | 68 | }, |
49 | { .ctl_name = 0 } | 69 | { .ctl_name = 0 } |
50 | }; | 70 | }; |
diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 94b868494b31..500aad0ebd6a 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c | |||
@@ -220,6 +220,8 @@ static void dump_common_audit_data(struct audit_buffer *ab, | |||
220 | } | 220 | } |
221 | 221 | ||
222 | switch (a->type) { | 222 | switch (a->type) { |
223 | case LSM_AUDIT_NO_AUDIT: | ||
224 | return; | ||
223 | case LSM_AUDIT_DATA_IPC: | 225 | case LSM_AUDIT_DATA_IPC: |
224 | audit_log_format(ab, " key=%d ", a->u.ipc_id); | 226 | audit_log_format(ab, " key=%d ", a->u.ipc_id); |
225 | break; | 227 | break; |
diff --git a/security/security.c b/security/security.c index dc7674fbfc7a..c4c673240c1c 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -124,9 +124,9 @@ int register_security(struct security_operations *ops) | |||
124 | 124 | ||
125 | /* Security operations */ | 125 | /* Security operations */ |
126 | 126 | ||
127 | int security_ptrace_may_access(struct task_struct *child, unsigned int mode) | 127 | int security_ptrace_access_check(struct task_struct *child, unsigned int mode) |
128 | { | 128 | { |
129 | return security_ops->ptrace_may_access(child, mode); | 129 | return security_ops->ptrace_access_check(child, mode); |
130 | } | 130 | } |
131 | 131 | ||
132 | int security_ptrace_traceme(struct task_struct *parent) | 132 | int security_ptrace_traceme(struct task_struct *parent) |
@@ -684,6 +684,11 @@ int security_task_create(unsigned long clone_flags) | |||
684 | return security_ops->task_create(clone_flags); | 684 | return security_ops->task_create(clone_flags); |
685 | } | 685 | } |
686 | 686 | ||
687 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) | ||
688 | { | ||
689 | return security_ops->cred_alloc_blank(cred, gfp); | ||
690 | } | ||
691 | |||
687 | void security_cred_free(struct cred *cred) | 692 | void security_cred_free(struct cred *cred) |
688 | { | 693 | { |
689 | security_ops->cred_free(cred); | 694 | security_ops->cred_free(cred); |
@@ -699,6 +704,11 @@ void security_commit_creds(struct cred *new, const struct cred *old) | |||
699 | security_ops->cred_commit(new, old); | 704 | security_ops->cred_commit(new, old); |
700 | } | 705 | } |
701 | 706 | ||
707 | void security_transfer_creds(struct cred *new, const struct cred *old) | ||
708 | { | ||
709 | security_ops->cred_transfer(new, old); | ||
710 | } | ||
711 | |||
702 | int security_kernel_act_as(struct cred *new, u32 secid) | 712 | int security_kernel_act_as(struct cred *new, u32 secid) |
703 | { | 713 | { |
704 | return security_ops->kernel_act_as(new, secid); | 714 | return security_ops->kernel_act_as(new, secid); |
@@ -709,6 +719,11 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
709 | return security_ops->kernel_create_files_as(new, inode); | 719 | return security_ops->kernel_create_files_as(new, inode); |
710 | } | 720 | } |
711 | 721 | ||
722 | int security_kernel_module_request(void) | ||
723 | { | ||
724 | return security_ops->kernel_module_request(); | ||
725 | } | ||
726 | |||
712 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | 727 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) |
713 | { | 728 | { |
714 | return security_ops->task_setuid(id0, id1, id2, flags); | 729 | return security_ops->task_setuid(id0, id1, id2, flags); |
@@ -959,6 +974,24 @@ void security_release_secctx(char *secdata, u32 seclen) | |||
959 | } | 974 | } |
960 | EXPORT_SYMBOL(security_release_secctx); | 975 | EXPORT_SYMBOL(security_release_secctx); |
961 | 976 | ||
977 | int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
978 | { | ||
979 | return security_ops->inode_notifysecctx(inode, ctx, ctxlen); | ||
980 | } | ||
981 | EXPORT_SYMBOL(security_inode_notifysecctx); | ||
982 | |||
983 | int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
984 | { | ||
985 | return security_ops->inode_setsecctx(dentry, ctx, ctxlen); | ||
986 | } | ||
987 | EXPORT_SYMBOL(security_inode_setsecctx); | ||
988 | |||
989 | int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
990 | { | ||
991 | return security_ops->inode_getsecctx(inode, ctx, ctxlen); | ||
992 | } | ||
993 | EXPORT_SYMBOL(security_inode_getsecctx); | ||
994 | |||
962 | #ifdef CONFIG_SECURITY_NETWORK | 995 | #ifdef CONFIG_SECURITY_NETWORK |
963 | 996 | ||
964 | int security_unix_stream_connect(struct socket *sock, struct socket *other, | 997 | int security_unix_stream_connect(struct socket *sock, struct socket *other, |
@@ -1112,6 +1145,24 @@ void security_inet_conn_established(struct sock *sk, | |||
1112 | security_ops->inet_conn_established(sk, skb); | 1145 | security_ops->inet_conn_established(sk, skb); |
1113 | } | 1146 | } |
1114 | 1147 | ||
1148 | int security_tun_dev_create(void) | ||
1149 | { | ||
1150 | return security_ops->tun_dev_create(); | ||
1151 | } | ||
1152 | EXPORT_SYMBOL(security_tun_dev_create); | ||
1153 | |||
1154 | void security_tun_dev_post_create(struct sock *sk) | ||
1155 | { | ||
1156 | return security_ops->tun_dev_post_create(sk); | ||
1157 | } | ||
1158 | EXPORT_SYMBOL(security_tun_dev_post_create); | ||
1159 | |||
1160 | int security_tun_dev_attach(struct sock *sk) | ||
1161 | { | ||
1162 | return security_ops->tun_dev_attach(sk); | ||
1163 | } | ||
1164 | EXPORT_SYMBOL(security_tun_dev_attach); | ||
1165 | |||
1115 | #endif /* CONFIG_SECURITY_NETWORK */ | 1166 | #endif /* CONFIG_SECURITY_NETWORK */ |
1116 | 1167 | ||
1117 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 1168 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
@@ -1218,6 +1269,13 @@ int security_key_getsecurity(struct key *key, char **_buffer) | |||
1218 | return security_ops->key_getsecurity(key, _buffer); | 1269 | return security_ops->key_getsecurity(key, _buffer); |
1219 | } | 1270 | } |
1220 | 1271 | ||
1272 | int security_key_session_to_parent(const struct cred *cred, | ||
1273 | const struct cred *parent_cred, | ||
1274 | struct key *key) | ||
1275 | { | ||
1276 | return security_ops->key_session_to_parent(cred, parent_cred, key); | ||
1277 | } | ||
1278 | |||
1221 | #endif /* CONFIG_KEYS */ | 1279 | #endif /* CONFIG_KEYS */ |
1222 | 1280 | ||
1223 | #ifdef CONFIG_AUDIT | 1281 | #ifdef CONFIG_AUDIT |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index b2ab60859832..1ed0f076aadc 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -137,7 +137,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) | |||
137 | * @tclass: target security class | 137 | * @tclass: target security class |
138 | * @av: access vector | 138 | * @av: access vector |
139 | */ | 139 | */ |
140 | void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) | 140 | static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) |
141 | { | 141 | { |
142 | const char **common_pts = NULL; | 142 | const char **common_pts = NULL; |
143 | u32 common_base = 0; | 143 | u32 common_base = 0; |
@@ -492,23 +492,35 @@ out: | |||
492 | return node; | 492 | return node; |
493 | } | 493 | } |
494 | 494 | ||
495 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | 495 | /** |
496 | struct in6_addr *addr, __be16 port, | 496 | * avc_audit_pre_callback - SELinux specific information |
497 | char *name1, char *name2) | 497 | * will be called by generic audit code |
498 | * @ab: the audit buffer | ||
499 | * @a: audit_data | ||
500 | */ | ||
501 | static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) | ||
498 | { | 502 | { |
499 | if (!ipv6_addr_any(addr)) | 503 | struct common_audit_data *ad = a; |
500 | audit_log_format(ab, " %s=%pI6", name1, addr); | 504 | audit_log_format(ab, "avc: %s ", |
501 | if (port) | 505 | ad->selinux_audit_data.denied ? "denied" : "granted"); |
502 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 506 | avc_dump_av(ab, ad->selinux_audit_data.tclass, |
507 | ad->selinux_audit_data.audited); | ||
508 | audit_log_format(ab, " for "); | ||
503 | } | 509 | } |
504 | 510 | ||
505 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr, | 511 | /** |
506 | __be16 port, char *name1, char *name2) | 512 | * avc_audit_post_callback - SELinux specific information |
513 | * will be called by generic audit code | ||
514 | * @ab: the audit buffer | ||
515 | * @a: audit_data | ||
516 | */ | ||
517 | static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | ||
507 | { | 518 | { |
508 | if (addr) | 519 | struct common_audit_data *ad = a; |
509 | audit_log_format(ab, " %s=%pI4", name1, &addr); | 520 | audit_log_format(ab, " "); |
510 | if (port) | 521 | avc_dump_query(ab, ad->selinux_audit_data.ssid, |
511 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 522 | ad->selinux_audit_data.tsid, |
523 | ad->selinux_audit_data.tclass); | ||
512 | } | 524 | } |
513 | 525 | ||
514 | /** | 526 | /** |
@@ -532,13 +544,10 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr, | |||
532 | */ | 544 | */ |
533 | void avc_audit(u32 ssid, u32 tsid, | 545 | void avc_audit(u32 ssid, u32 tsid, |
534 | u16 tclass, u32 requested, | 546 | u16 tclass, u32 requested, |
535 | struct av_decision *avd, int result, struct avc_audit_data *a) | 547 | struct av_decision *avd, int result, struct common_audit_data *a) |
536 | { | 548 | { |
537 | struct task_struct *tsk = current; | 549 | struct common_audit_data stack_data; |
538 | struct inode *inode = NULL; | ||
539 | u32 denied, audited; | 550 | u32 denied, audited; |
540 | struct audit_buffer *ab; | ||
541 | |||
542 | denied = requested & ~avd->allowed; | 551 | denied = requested & ~avd->allowed; |
543 | if (denied) { | 552 | if (denied) { |
544 | audited = denied; | 553 | audited = denied; |
@@ -551,144 +560,20 @@ void avc_audit(u32 ssid, u32 tsid, | |||
551 | if (!(audited & avd->auditallow)) | 560 | if (!(audited & avd->auditallow)) |
552 | return; | 561 | return; |
553 | } | 562 | } |
554 | 563 | if (!a) { | |
555 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); | 564 | a = &stack_data; |
556 | if (!ab) | 565 | memset(a, 0, sizeof(*a)); |
557 | return; /* audit_panic has been called */ | 566 | a->type = LSM_AUDIT_NO_AUDIT; |
558 | audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted"); | ||
559 | avc_dump_av(ab, tclass, audited); | ||
560 | audit_log_format(ab, " for "); | ||
561 | if (a && a->tsk) | ||
562 | tsk = a->tsk; | ||
563 | if (tsk && tsk->pid) { | ||
564 | audit_log_format(ab, " pid=%d comm=", tsk->pid); | ||
565 | audit_log_untrustedstring(ab, tsk->comm); | ||
566 | } | ||
567 | if (a) { | ||
568 | switch (a->type) { | ||
569 | case AVC_AUDIT_DATA_IPC: | ||
570 | audit_log_format(ab, " key=%d", a->u.ipc_id); | ||
571 | break; | ||
572 | case AVC_AUDIT_DATA_CAP: | ||
573 | audit_log_format(ab, " capability=%d", a->u.cap); | ||
574 | break; | ||
575 | case AVC_AUDIT_DATA_FS: | ||
576 | if (a->u.fs.path.dentry) { | ||
577 | struct dentry *dentry = a->u.fs.path.dentry; | ||
578 | if (a->u.fs.path.mnt) { | ||
579 | audit_log_d_path(ab, "path=", | ||
580 | &a->u.fs.path); | ||
581 | } else { | ||
582 | audit_log_format(ab, " name="); | ||
583 | audit_log_untrustedstring(ab, dentry->d_name.name); | ||
584 | } | ||
585 | inode = dentry->d_inode; | ||
586 | } else if (a->u.fs.inode) { | ||
587 | struct dentry *dentry; | ||
588 | inode = a->u.fs.inode; | ||
589 | dentry = d_find_alias(inode); | ||
590 | if (dentry) { | ||
591 | audit_log_format(ab, " name="); | ||
592 | audit_log_untrustedstring(ab, dentry->d_name.name); | ||
593 | dput(dentry); | ||
594 | } | ||
595 | } | ||
596 | if (inode) | ||
597 | audit_log_format(ab, " dev=%s ino=%lu", | ||
598 | inode->i_sb->s_id, | ||
599 | inode->i_ino); | ||
600 | break; | ||
601 | case AVC_AUDIT_DATA_NET: | ||
602 | if (a->u.net.sk) { | ||
603 | struct sock *sk = a->u.net.sk; | ||
604 | struct unix_sock *u; | ||
605 | int len = 0; | ||
606 | char *p = NULL; | ||
607 | |||
608 | switch (sk->sk_family) { | ||
609 | case AF_INET: { | ||
610 | struct inet_sock *inet = inet_sk(sk); | ||
611 | |||
612 | avc_print_ipv4_addr(ab, inet->rcv_saddr, | ||
613 | inet->sport, | ||
614 | "laddr", "lport"); | ||
615 | avc_print_ipv4_addr(ab, inet->daddr, | ||
616 | inet->dport, | ||
617 | "faddr", "fport"); | ||
618 | break; | ||
619 | } | ||
620 | case AF_INET6: { | ||
621 | struct inet_sock *inet = inet_sk(sk); | ||
622 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | ||
623 | |||
624 | avc_print_ipv6_addr(ab, &inet6->rcv_saddr, | ||
625 | inet->sport, | ||
626 | "laddr", "lport"); | ||
627 | avc_print_ipv6_addr(ab, &inet6->daddr, | ||
628 | inet->dport, | ||
629 | "faddr", "fport"); | ||
630 | break; | ||
631 | } | ||
632 | case AF_UNIX: | ||
633 | u = unix_sk(sk); | ||
634 | if (u->dentry) { | ||
635 | struct path path = { | ||
636 | .dentry = u->dentry, | ||
637 | .mnt = u->mnt | ||
638 | }; | ||
639 | audit_log_d_path(ab, "path=", | ||
640 | &path); | ||
641 | break; | ||
642 | } | ||
643 | if (!u->addr) | ||
644 | break; | ||
645 | len = u->addr->len-sizeof(short); | ||
646 | p = &u->addr->name->sun_path[0]; | ||
647 | audit_log_format(ab, " path="); | ||
648 | if (*p) | ||
649 | audit_log_untrustedstring(ab, p); | ||
650 | else | ||
651 | audit_log_n_hex(ab, p, len); | ||
652 | break; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | switch (a->u.net.family) { | ||
657 | case AF_INET: | ||
658 | avc_print_ipv4_addr(ab, a->u.net.v4info.saddr, | ||
659 | a->u.net.sport, | ||
660 | "saddr", "src"); | ||
661 | avc_print_ipv4_addr(ab, a->u.net.v4info.daddr, | ||
662 | a->u.net.dport, | ||
663 | "daddr", "dest"); | ||
664 | break; | ||
665 | case AF_INET6: | ||
666 | avc_print_ipv6_addr(ab, &a->u.net.v6info.saddr, | ||
667 | a->u.net.sport, | ||
668 | "saddr", "src"); | ||
669 | avc_print_ipv6_addr(ab, &a->u.net.v6info.daddr, | ||
670 | a->u.net.dport, | ||
671 | "daddr", "dest"); | ||
672 | break; | ||
673 | } | ||
674 | if (a->u.net.netif > 0) { | ||
675 | struct net_device *dev; | ||
676 | |||
677 | /* NOTE: we always use init's namespace */ | ||
678 | dev = dev_get_by_index(&init_net, | ||
679 | a->u.net.netif); | ||
680 | if (dev) { | ||
681 | audit_log_format(ab, " netif=%s", | ||
682 | dev->name); | ||
683 | dev_put(dev); | ||
684 | } | ||
685 | } | ||
686 | break; | ||
687 | } | ||
688 | } | 567 | } |
689 | audit_log_format(ab, " "); | 568 | a->selinux_audit_data.tclass = tclass; |
690 | avc_dump_query(ab, ssid, tsid, tclass); | 569 | a->selinux_audit_data.requested = requested; |
691 | audit_log_end(ab); | 570 | a->selinux_audit_data.ssid = ssid; |
571 | a->selinux_audit_data.tsid = tsid; | ||
572 | a->selinux_audit_data.audited = audited; | ||
573 | a->selinux_audit_data.denied = denied; | ||
574 | a->lsm_pre_audit = avc_audit_pre_callback; | ||
575 | a->lsm_post_audit = avc_audit_post_callback; | ||
576 | common_lsm_audit(a); | ||
692 | } | 577 | } |
693 | 578 | ||
694 | /** | 579 | /** |
@@ -824,18 +709,16 @@ out: | |||
824 | } | 709 | } |
825 | 710 | ||
826 | /** | 711 | /** |
827 | * avc_ss_reset - Flush the cache and revalidate migrated permissions. | 712 | * avc_flush - Flush the cache |
828 | * @seqno: policy sequence number | ||
829 | */ | 713 | */ |
830 | int avc_ss_reset(u32 seqno) | 714 | static void avc_flush(void) |
831 | { | 715 | { |
832 | struct avc_callback_node *c; | ||
833 | int i, rc = 0, tmprc; | ||
834 | unsigned long flag; | ||
835 | struct avc_node *node; | ||
836 | struct hlist_head *head; | 716 | struct hlist_head *head; |
837 | struct hlist_node *next; | 717 | struct hlist_node *next; |
718 | struct avc_node *node; | ||
838 | spinlock_t *lock; | 719 | spinlock_t *lock; |
720 | unsigned long flag; | ||
721 | int i; | ||
839 | 722 | ||
840 | for (i = 0; i < AVC_CACHE_SLOTS; i++) { | 723 | for (i = 0; i < AVC_CACHE_SLOTS; i++) { |
841 | head = &avc_cache.slots[i]; | 724 | head = &avc_cache.slots[i]; |
@@ -852,6 +735,18 @@ int avc_ss_reset(u32 seqno) | |||
852 | rcu_read_unlock(); | 735 | rcu_read_unlock(); |
853 | spin_unlock_irqrestore(lock, flag); | 736 | spin_unlock_irqrestore(lock, flag); |
854 | } | 737 | } |
738 | } | ||
739 | |||
740 | /** | ||
741 | * avc_ss_reset - Flush the cache and revalidate migrated permissions. | ||
742 | * @seqno: policy sequence number | ||
743 | */ | ||
744 | int avc_ss_reset(u32 seqno) | ||
745 | { | ||
746 | struct avc_callback_node *c; | ||
747 | int rc = 0, tmprc; | ||
748 | |||
749 | avc_flush(); | ||
855 | 750 | ||
856 | for (c = avc_callbacks; c; c = c->next) { | 751 | for (c = avc_callbacks; c; c = c->next) { |
857 | if (c->events & AVC_CALLBACK_RESET) { | 752 | if (c->events & AVC_CALLBACK_RESET) { |
@@ -956,7 +851,7 @@ out: | |||
956 | * another -errno upon other errors. | 851 | * another -errno upon other errors. |
957 | */ | 852 | */ |
958 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, | 853 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, |
959 | u32 requested, struct avc_audit_data *auditdata) | 854 | u32 requested, struct common_audit_data *auditdata) |
960 | { | 855 | { |
961 | struct av_decision avd; | 856 | struct av_decision avd; |
962 | int rc; | 857 | int rc; |
@@ -970,3 +865,11 @@ u32 avc_policy_seqno(void) | |||
970 | { | 865 | { |
971 | return avc_cache.latest_notif; | 866 | return avc_cache.latest_notif; |
972 | } | 867 | } |
868 | |||
869 | void avc_disable(void) | ||
870 | { | ||
871 | avc_flush(); | ||
872 | synchronize_rcu(); | ||
873 | if (avc_node_cachep) | ||
874 | kmem_cache_destroy(avc_node_cachep); | ||
875 | } | ||
diff --git a/security/selinux/exports.c b/security/selinux/exports.c index c73aeaa008e8..c0a454aee1e0 100644 --- a/security/selinux/exports.c +++ b/security/selinux/exports.c | |||
@@ -63,3 +63,9 @@ void selinux_secmark_refcount_dec(void) | |||
63 | atomic_dec(&selinux_secmark_refcount); | 63 | atomic_dec(&selinux_secmark_refcount); |
64 | } | 64 | } |
65 | EXPORT_SYMBOL_GPL(selinux_secmark_refcount_dec); | 65 | EXPORT_SYMBOL_GPL(selinux_secmark_refcount_dec); |
66 | |||
67 | bool selinux_is_enabled(void) | ||
68 | { | ||
69 | return selinux_enabled; | ||
70 | } | ||
71 | EXPORT_SYMBOL_GPL(selinux_is_enabled); | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8d8b69c5664e..417f7c994522 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -13,8 +13,8 @@ | |||
13 | * Eric Paris <eparis@redhat.com> | 13 | * Eric Paris <eparis@redhat.com> |
14 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. | 14 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. |
15 | * <dgoeddel@trustedcs.com> | 15 | * <dgoeddel@trustedcs.com> |
16 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 16 | * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P. |
17 | * Paul Moore <paul.moore@hp.com> | 17 | * Paul Moore <paul.moore@hp.com> |
18 | * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. | 18 | * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. |
19 | * Yuichi Nakamura <ynakam@hitachisoft.jp> | 19 | * Yuichi Nakamura <ynakam@hitachisoft.jp> |
20 | * | 20 | * |
@@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb) | |||
448 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) | 448 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) |
449 | sbsec->flags &= ~SE_SBLABELSUPP; | 449 | sbsec->flags &= ~SE_SBLABELSUPP; |
450 | 450 | ||
451 | /* Special handling for sysfs. Is genfs but also has setxattr handler*/ | ||
452 | if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0) | ||
453 | sbsec->flags |= SE_SBLABELSUPP; | ||
454 | |||
451 | /* Initialize the root inode. */ | 455 | /* Initialize the root inode. */ |
452 | rc = inode_doinit_with_dentry(root_inode, root); | 456 | rc = inode_doinit_with_dentry(root_inode, root); |
453 | 457 | ||
@@ -1479,14 +1483,14 @@ static int task_has_capability(struct task_struct *tsk, | |||
1479 | const struct cred *cred, | 1483 | const struct cred *cred, |
1480 | int cap, int audit) | 1484 | int cap, int audit) |
1481 | { | 1485 | { |
1482 | struct avc_audit_data ad; | 1486 | struct common_audit_data ad; |
1483 | struct av_decision avd; | 1487 | struct av_decision avd; |
1484 | u16 sclass; | 1488 | u16 sclass; |
1485 | u32 sid = cred_sid(cred); | 1489 | u32 sid = cred_sid(cred); |
1486 | u32 av = CAP_TO_MASK(cap); | 1490 | u32 av = CAP_TO_MASK(cap); |
1487 | int rc; | 1491 | int rc; |
1488 | 1492 | ||
1489 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 1493 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
1490 | ad.tsk = tsk; | 1494 | ad.tsk = tsk; |
1491 | ad.u.cap = cap; | 1495 | ad.u.cap = cap; |
1492 | 1496 | ||
@@ -1525,12 +1529,14 @@ static int task_has_system(struct task_struct *tsk, | |||
1525 | static int inode_has_perm(const struct cred *cred, | 1529 | static int inode_has_perm(const struct cred *cred, |
1526 | struct inode *inode, | 1530 | struct inode *inode, |
1527 | u32 perms, | 1531 | u32 perms, |
1528 | struct avc_audit_data *adp) | 1532 | struct common_audit_data *adp) |
1529 | { | 1533 | { |
1530 | struct inode_security_struct *isec; | 1534 | struct inode_security_struct *isec; |
1531 | struct avc_audit_data ad; | 1535 | struct common_audit_data ad; |
1532 | u32 sid; | 1536 | u32 sid; |
1533 | 1537 | ||
1538 | validate_creds(cred); | ||
1539 | |||
1534 | if (unlikely(IS_PRIVATE(inode))) | 1540 | if (unlikely(IS_PRIVATE(inode))) |
1535 | return 0; | 1541 | return 0; |
1536 | 1542 | ||
@@ -1539,7 +1545,7 @@ static int inode_has_perm(const struct cred *cred, | |||
1539 | 1545 | ||
1540 | if (!adp) { | 1546 | if (!adp) { |
1541 | adp = &ad; | 1547 | adp = &ad; |
1542 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1548 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1543 | ad.u.fs.inode = inode; | 1549 | ad.u.fs.inode = inode; |
1544 | } | 1550 | } |
1545 | 1551 | ||
@@ -1555,9 +1561,9 @@ static inline int dentry_has_perm(const struct cred *cred, | |||
1555 | u32 av) | 1561 | u32 av) |
1556 | { | 1562 | { |
1557 | struct inode *inode = dentry->d_inode; | 1563 | struct inode *inode = dentry->d_inode; |
1558 | struct avc_audit_data ad; | 1564 | struct common_audit_data ad; |
1559 | 1565 | ||
1560 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1566 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1561 | ad.u.fs.path.mnt = mnt; | 1567 | ad.u.fs.path.mnt = mnt; |
1562 | ad.u.fs.path.dentry = dentry; | 1568 | ad.u.fs.path.dentry = dentry; |
1563 | return inode_has_perm(cred, inode, av, &ad); | 1569 | return inode_has_perm(cred, inode, av, &ad); |
@@ -1577,11 +1583,11 @@ static int file_has_perm(const struct cred *cred, | |||
1577 | { | 1583 | { |
1578 | struct file_security_struct *fsec = file->f_security; | 1584 | struct file_security_struct *fsec = file->f_security; |
1579 | struct inode *inode = file->f_path.dentry->d_inode; | 1585 | struct inode *inode = file->f_path.dentry->d_inode; |
1580 | struct avc_audit_data ad; | 1586 | struct common_audit_data ad; |
1581 | u32 sid = cred_sid(cred); | 1587 | u32 sid = cred_sid(cred); |
1582 | int rc; | 1588 | int rc; |
1583 | 1589 | ||
1584 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1590 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1585 | ad.u.fs.path = file->f_path; | 1591 | ad.u.fs.path = file->f_path; |
1586 | 1592 | ||
1587 | if (sid != fsec->sid) { | 1593 | if (sid != fsec->sid) { |
@@ -1612,7 +1618,7 @@ static int may_create(struct inode *dir, | |||
1612 | struct inode_security_struct *dsec; | 1618 | struct inode_security_struct *dsec; |
1613 | struct superblock_security_struct *sbsec; | 1619 | struct superblock_security_struct *sbsec; |
1614 | u32 sid, newsid; | 1620 | u32 sid, newsid; |
1615 | struct avc_audit_data ad; | 1621 | struct common_audit_data ad; |
1616 | int rc; | 1622 | int rc; |
1617 | 1623 | ||
1618 | dsec = dir->i_security; | 1624 | dsec = dir->i_security; |
@@ -1621,7 +1627,7 @@ static int may_create(struct inode *dir, | |||
1621 | sid = tsec->sid; | 1627 | sid = tsec->sid; |
1622 | newsid = tsec->create_sid; | 1628 | newsid = tsec->create_sid; |
1623 | 1629 | ||
1624 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1630 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1625 | ad.u.fs.path.dentry = dentry; | 1631 | ad.u.fs.path.dentry = dentry; |
1626 | 1632 | ||
1627 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1633 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
@@ -1665,7 +1671,7 @@ static int may_link(struct inode *dir, | |||
1665 | 1671 | ||
1666 | { | 1672 | { |
1667 | struct inode_security_struct *dsec, *isec; | 1673 | struct inode_security_struct *dsec, *isec; |
1668 | struct avc_audit_data ad; | 1674 | struct common_audit_data ad; |
1669 | u32 sid = current_sid(); | 1675 | u32 sid = current_sid(); |
1670 | u32 av; | 1676 | u32 av; |
1671 | int rc; | 1677 | int rc; |
@@ -1673,7 +1679,7 @@ static int may_link(struct inode *dir, | |||
1673 | dsec = dir->i_security; | 1679 | dsec = dir->i_security; |
1674 | isec = dentry->d_inode->i_security; | 1680 | isec = dentry->d_inode->i_security; |
1675 | 1681 | ||
1676 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1682 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1677 | ad.u.fs.path.dentry = dentry; | 1683 | ad.u.fs.path.dentry = dentry; |
1678 | 1684 | ||
1679 | av = DIR__SEARCH; | 1685 | av = DIR__SEARCH; |
@@ -1708,7 +1714,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1708 | struct dentry *new_dentry) | 1714 | struct dentry *new_dentry) |
1709 | { | 1715 | { |
1710 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; | 1716 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; |
1711 | struct avc_audit_data ad; | 1717 | struct common_audit_data ad; |
1712 | u32 sid = current_sid(); | 1718 | u32 sid = current_sid(); |
1713 | u32 av; | 1719 | u32 av; |
1714 | int old_is_dir, new_is_dir; | 1720 | int old_is_dir, new_is_dir; |
@@ -1719,7 +1725,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1719 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 1725 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
1720 | new_dsec = new_dir->i_security; | 1726 | new_dsec = new_dir->i_security; |
1721 | 1727 | ||
1722 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1728 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1723 | 1729 | ||
1724 | ad.u.fs.path.dentry = old_dentry; | 1730 | ad.u.fs.path.dentry = old_dentry; |
1725 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 1731 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, |
@@ -1761,7 +1767,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1761 | static int superblock_has_perm(const struct cred *cred, | 1767 | static int superblock_has_perm(const struct cred *cred, |
1762 | struct super_block *sb, | 1768 | struct super_block *sb, |
1763 | u32 perms, | 1769 | u32 perms, |
1764 | struct avc_audit_data *ad) | 1770 | struct common_audit_data *ad) |
1765 | { | 1771 | { |
1766 | struct superblock_security_struct *sbsec; | 1772 | struct superblock_security_struct *sbsec; |
1767 | u32 sid = cred_sid(cred); | 1773 | u32 sid = cred_sid(cred); |
@@ -1855,12 +1861,12 @@ static inline u32 open_file_to_av(struct file *file) | |||
1855 | 1861 | ||
1856 | /* Hook functions begin here. */ | 1862 | /* Hook functions begin here. */ |
1857 | 1863 | ||
1858 | static int selinux_ptrace_may_access(struct task_struct *child, | 1864 | static int selinux_ptrace_access_check(struct task_struct *child, |
1859 | unsigned int mode) | 1865 | unsigned int mode) |
1860 | { | 1866 | { |
1861 | int rc; | 1867 | int rc; |
1862 | 1868 | ||
1863 | rc = cap_ptrace_may_access(child, mode); | 1869 | rc = cap_ptrace_access_check(child, mode); |
1864 | if (rc) | 1870 | if (rc) |
1865 | return rc; | 1871 | return rc; |
1866 | 1872 | ||
@@ -2101,7 +2107,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2101 | const struct task_security_struct *old_tsec; | 2107 | const struct task_security_struct *old_tsec; |
2102 | struct task_security_struct *new_tsec; | 2108 | struct task_security_struct *new_tsec; |
2103 | struct inode_security_struct *isec; | 2109 | struct inode_security_struct *isec; |
2104 | struct avc_audit_data ad; | 2110 | struct common_audit_data ad; |
2105 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | 2111 | struct inode *inode = bprm->file->f_path.dentry->d_inode; |
2106 | int rc; | 2112 | int rc; |
2107 | 2113 | ||
@@ -2139,7 +2145,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2139 | return rc; | 2145 | return rc; |
2140 | } | 2146 | } |
2141 | 2147 | ||
2142 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2148 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2143 | ad.u.fs.path = bprm->file->f_path; | 2149 | ad.u.fs.path = bprm->file->f_path; |
2144 | 2150 | ||
2145 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 2151 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) |
@@ -2232,7 +2238,7 @@ extern struct dentry *selinux_null; | |||
2232 | static inline void flush_unauthorized_files(const struct cred *cred, | 2238 | static inline void flush_unauthorized_files(const struct cred *cred, |
2233 | struct files_struct *files) | 2239 | struct files_struct *files) |
2234 | { | 2240 | { |
2235 | struct avc_audit_data ad; | 2241 | struct common_audit_data ad; |
2236 | struct file *file, *devnull = NULL; | 2242 | struct file *file, *devnull = NULL; |
2237 | struct tty_struct *tty; | 2243 | struct tty_struct *tty; |
2238 | struct fdtable *fdt; | 2244 | struct fdtable *fdt; |
@@ -2266,7 +2272,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2266 | 2272 | ||
2267 | /* Revalidate access to inherited open files. */ | 2273 | /* Revalidate access to inherited open files. */ |
2268 | 2274 | ||
2269 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2275 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2270 | 2276 | ||
2271 | spin_lock(&files->file_lock); | 2277 | spin_lock(&files->file_lock); |
2272 | for (;;) { | 2278 | for (;;) { |
@@ -2515,7 +2521,7 @@ out: | |||
2515 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | 2521 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) |
2516 | { | 2522 | { |
2517 | const struct cred *cred = current_cred(); | 2523 | const struct cred *cred = current_cred(); |
2518 | struct avc_audit_data ad; | 2524 | struct common_audit_data ad; |
2519 | int rc; | 2525 | int rc; |
2520 | 2526 | ||
2521 | rc = superblock_doinit(sb, data); | 2527 | rc = superblock_doinit(sb, data); |
@@ -2526,7 +2532,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2526 | if (flags & MS_KERNMOUNT) | 2532 | if (flags & MS_KERNMOUNT) |
2527 | return 0; | 2533 | return 0; |
2528 | 2534 | ||
2529 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2535 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2530 | ad.u.fs.path.dentry = sb->s_root; | 2536 | ad.u.fs.path.dentry = sb->s_root; |
2531 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); | 2537 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
2532 | } | 2538 | } |
@@ -2534,9 +2540,9 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2534 | static int selinux_sb_statfs(struct dentry *dentry) | 2540 | static int selinux_sb_statfs(struct dentry *dentry) |
2535 | { | 2541 | { |
2536 | const struct cred *cred = current_cred(); | 2542 | const struct cred *cred = current_cred(); |
2537 | struct avc_audit_data ad; | 2543 | struct common_audit_data ad; |
2538 | 2544 | ||
2539 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2545 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2540 | ad.u.fs.path.dentry = dentry->d_sb->s_root; | 2546 | ad.u.fs.path.dentry = dentry->d_sb->s_root; |
2541 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); | 2547 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); |
2542 | } | 2548 | } |
@@ -2711,12 +2717,18 @@ static int selinux_inode_permission(struct inode *inode, int mask) | |||
2711 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2717 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
2712 | { | 2718 | { |
2713 | const struct cred *cred = current_cred(); | 2719 | const struct cred *cred = current_cred(); |
2720 | unsigned int ia_valid = iattr->ia_valid; | ||
2721 | |||
2722 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ | ||
2723 | if (ia_valid & ATTR_FORCE) { | ||
2724 | ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE | | ||
2725 | ATTR_FORCE); | ||
2726 | if (!ia_valid) | ||
2727 | return 0; | ||
2728 | } | ||
2714 | 2729 | ||
2715 | if (iattr->ia_valid & ATTR_FORCE) | 2730 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | |
2716 | return 0; | 2731 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) |
2717 | |||
2718 | if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | | ||
2719 | ATTR_ATIME_SET | ATTR_MTIME_SET)) | ||
2720 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); | 2732 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); |
2721 | 2733 | ||
2722 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); | 2734 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); |
@@ -2756,7 +2768,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2756 | struct inode *inode = dentry->d_inode; | 2768 | struct inode *inode = dentry->d_inode; |
2757 | struct inode_security_struct *isec = inode->i_security; | 2769 | struct inode_security_struct *isec = inode->i_security; |
2758 | struct superblock_security_struct *sbsec; | 2770 | struct superblock_security_struct *sbsec; |
2759 | struct avc_audit_data ad; | 2771 | struct common_audit_data ad; |
2760 | u32 newsid, sid = current_sid(); | 2772 | u32 newsid, sid = current_sid(); |
2761 | int rc = 0; | 2773 | int rc = 0; |
2762 | 2774 | ||
@@ -2770,7 +2782,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2770 | if (!is_owner_or_cap(inode)) | 2782 | if (!is_owner_or_cap(inode)) |
2771 | return -EPERM; | 2783 | return -EPERM; |
2772 | 2784 | ||
2773 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2785 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2774 | ad.u.fs.path.dentry = dentry; | 2786 | ad.u.fs.path.dentry = dentry; |
2775 | 2787 | ||
2776 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 2788 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
@@ -2915,6 +2927,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
2915 | return rc; | 2927 | return rc; |
2916 | 2928 | ||
2917 | isec->sid = newsid; | 2929 | isec->sid = newsid; |
2930 | isec->initialized = 1; | ||
2918 | return 0; | 2931 | return 0; |
2919 | } | 2932 | } |
2920 | 2933 | ||
@@ -2939,11 +2952,6 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2939 | const struct cred *cred = current_cred(); | 2952 | const struct cred *cred = current_cred(); |
2940 | struct inode *inode = file->f_path.dentry->d_inode; | 2953 | struct inode *inode = file->f_path.dentry->d_inode; |
2941 | 2954 | ||
2942 | if (!mask) { | ||
2943 | /* No permission to check. Existence test. */ | ||
2944 | return 0; | ||
2945 | } | ||
2946 | |||
2947 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ | 2955 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ |
2948 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) | 2956 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) |
2949 | mask |= MAY_APPEND; | 2957 | mask |= MAY_APPEND; |
@@ -2954,10 +2962,20 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2954 | 2962 | ||
2955 | static int selinux_file_permission(struct file *file, int mask) | 2963 | static int selinux_file_permission(struct file *file, int mask) |
2956 | { | 2964 | { |
2965 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2966 | struct file_security_struct *fsec = file->f_security; | ||
2967 | struct inode_security_struct *isec = inode->i_security; | ||
2968 | u32 sid = current_sid(); | ||
2969 | |||
2957 | if (!mask) | 2970 | if (!mask) |
2958 | /* No permission to check. Existence test. */ | 2971 | /* No permission to check. Existence test. */ |
2959 | return 0; | 2972 | return 0; |
2960 | 2973 | ||
2974 | if (sid == fsec->sid && fsec->isid == isec->sid && | ||
2975 | fsec->pseqno == avc_policy_seqno()) | ||
2976 | /* No change since dentry_open check. */ | ||
2977 | return 0; | ||
2978 | |||
2961 | return selinux_revalidate_file_permission(file, mask); | 2979 | return selinux_revalidate_file_permission(file, mask); |
2962 | } | 2980 | } |
2963 | 2981 | ||
@@ -3220,12 +3238,29 @@ static int selinux_task_create(unsigned long clone_flags) | |||
3220 | } | 3238 | } |
3221 | 3239 | ||
3222 | /* | 3240 | /* |
3241 | * allocate the SELinux part of blank credentials | ||
3242 | */ | ||
3243 | static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp) | ||
3244 | { | ||
3245 | struct task_security_struct *tsec; | ||
3246 | |||
3247 | tsec = kzalloc(sizeof(struct task_security_struct), gfp); | ||
3248 | if (!tsec) | ||
3249 | return -ENOMEM; | ||
3250 | |||
3251 | cred->security = tsec; | ||
3252 | return 0; | ||
3253 | } | ||
3254 | |||
3255 | /* | ||
3223 | * detach and free the LSM part of a set of credentials | 3256 | * detach and free the LSM part of a set of credentials |
3224 | */ | 3257 | */ |
3225 | static void selinux_cred_free(struct cred *cred) | 3258 | static void selinux_cred_free(struct cred *cred) |
3226 | { | 3259 | { |
3227 | struct task_security_struct *tsec = cred->security; | 3260 | struct task_security_struct *tsec = cred->security; |
3228 | cred->security = NULL; | 3261 | |
3262 | BUG_ON((unsigned long) cred->security < PAGE_SIZE); | ||
3263 | cred->security = (void *) 0x7UL; | ||
3229 | kfree(tsec); | 3264 | kfree(tsec); |
3230 | } | 3265 | } |
3231 | 3266 | ||
@@ -3249,6 +3284,17 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old, | |||
3249 | } | 3284 | } |
3250 | 3285 | ||
3251 | /* | 3286 | /* |
3287 | * transfer the SELinux data to a blank set of creds | ||
3288 | */ | ||
3289 | static void selinux_cred_transfer(struct cred *new, const struct cred *old) | ||
3290 | { | ||
3291 | const struct task_security_struct *old_tsec = old->security; | ||
3292 | struct task_security_struct *tsec = new->security; | ||
3293 | |||
3294 | *tsec = *old_tsec; | ||
3295 | } | ||
3296 | |||
3297 | /* | ||
3252 | * set the security data for a kernel service | 3298 | * set the security data for a kernel service |
3253 | * - all the creation contexts are set to unlabelled | 3299 | * - all the creation contexts are set to unlabelled |
3254 | */ | 3300 | */ |
@@ -3292,6 +3338,11 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
3292 | return 0; | 3338 | return 0; |
3293 | } | 3339 | } |
3294 | 3340 | ||
3341 | static int selinux_kernel_module_request(void) | ||
3342 | { | ||
3343 | return task_has_system(current, SYSTEM__MODULE_REQUEST); | ||
3344 | } | ||
3345 | |||
3295 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3346 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
3296 | { | 3347 | { |
3297 | return current_has_perm(p, PROCESS__SETPGID); | 3348 | return current_has_perm(p, PROCESS__SETPGID); |
@@ -3409,7 +3460,7 @@ static void selinux_task_to_inode(struct task_struct *p, | |||
3409 | 3460 | ||
3410 | /* Returns error only if unable to parse addresses */ | 3461 | /* Returns error only if unable to parse addresses */ |
3411 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, | 3462 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, |
3412 | struct avc_audit_data *ad, u8 *proto) | 3463 | struct common_audit_data *ad, u8 *proto) |
3413 | { | 3464 | { |
3414 | int offset, ihlen, ret = -EINVAL; | 3465 | int offset, ihlen, ret = -EINVAL; |
3415 | struct iphdr _iph, *ih; | 3466 | struct iphdr _iph, *ih; |
@@ -3490,7 +3541,7 @@ out: | |||
3490 | 3541 | ||
3491 | /* Returns error only if unable to parse addresses */ | 3542 | /* Returns error only if unable to parse addresses */ |
3492 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, | 3543 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, |
3493 | struct avc_audit_data *ad, u8 *proto) | 3544 | struct common_audit_data *ad, u8 *proto) |
3494 | { | 3545 | { |
3495 | u8 nexthdr; | 3546 | u8 nexthdr; |
3496 | int ret = -EINVAL, offset; | 3547 | int ret = -EINVAL, offset; |
@@ -3561,7 +3612,7 @@ out: | |||
3561 | 3612 | ||
3562 | #endif /* IPV6 */ | 3613 | #endif /* IPV6 */ |
3563 | 3614 | ||
3564 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, | 3615 | static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, |
3565 | char **_addrp, int src, u8 *proto) | 3616 | char **_addrp, int src, u8 *proto) |
3566 | { | 3617 | { |
3567 | char *addrp; | 3618 | char *addrp; |
@@ -3643,7 +3694,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, | |||
3643 | u32 perms) | 3694 | u32 perms) |
3644 | { | 3695 | { |
3645 | struct inode_security_struct *isec; | 3696 | struct inode_security_struct *isec; |
3646 | struct avc_audit_data ad; | 3697 | struct common_audit_data ad; |
3647 | u32 sid; | 3698 | u32 sid; |
3648 | int err = 0; | 3699 | int err = 0; |
3649 | 3700 | ||
@@ -3653,7 +3704,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, | |||
3653 | goto out; | 3704 | goto out; |
3654 | sid = task_sid(task); | 3705 | sid = task_sid(task); |
3655 | 3706 | ||
3656 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3707 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3657 | ad.u.net.sk = sock->sk; | 3708 | ad.u.net.sk = sock->sk; |
3658 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 3709 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
3659 | 3710 | ||
@@ -3740,7 +3791,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3740 | if (family == PF_INET || family == PF_INET6) { | 3791 | if (family == PF_INET || family == PF_INET6) { |
3741 | char *addrp; | 3792 | char *addrp; |
3742 | struct inode_security_struct *isec; | 3793 | struct inode_security_struct *isec; |
3743 | struct avc_audit_data ad; | 3794 | struct common_audit_data ad; |
3744 | struct sockaddr_in *addr4 = NULL; | 3795 | struct sockaddr_in *addr4 = NULL; |
3745 | struct sockaddr_in6 *addr6 = NULL; | 3796 | struct sockaddr_in6 *addr6 = NULL; |
3746 | unsigned short snum; | 3797 | unsigned short snum; |
@@ -3769,7 +3820,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3769 | snum, &sid); | 3820 | snum, &sid); |
3770 | if (err) | 3821 | if (err) |
3771 | goto out; | 3822 | goto out; |
3772 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3823 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3773 | ad.u.net.sport = htons(snum); | 3824 | ad.u.net.sport = htons(snum); |
3774 | ad.u.net.family = family; | 3825 | ad.u.net.family = family; |
3775 | err = avc_has_perm(isec->sid, sid, | 3826 | err = avc_has_perm(isec->sid, sid, |
@@ -3802,7 +3853,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3802 | if (err) | 3853 | if (err) |
3803 | goto out; | 3854 | goto out; |
3804 | 3855 | ||
3805 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3856 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3806 | ad.u.net.sport = htons(snum); | 3857 | ad.u.net.sport = htons(snum); |
3807 | ad.u.net.family = family; | 3858 | ad.u.net.family = family; |
3808 | 3859 | ||
@@ -3836,7 +3887,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3836 | isec = SOCK_INODE(sock)->i_security; | 3887 | isec = SOCK_INODE(sock)->i_security; |
3837 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3888 | if (isec->sclass == SECCLASS_TCP_SOCKET || |
3838 | isec->sclass == SECCLASS_DCCP_SOCKET) { | 3889 | isec->sclass == SECCLASS_DCCP_SOCKET) { |
3839 | struct avc_audit_data ad; | 3890 | struct common_audit_data ad; |
3840 | struct sockaddr_in *addr4 = NULL; | 3891 | struct sockaddr_in *addr4 = NULL; |
3841 | struct sockaddr_in6 *addr6 = NULL; | 3892 | struct sockaddr_in6 *addr6 = NULL; |
3842 | unsigned short snum; | 3893 | unsigned short snum; |
@@ -3861,7 +3912,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3861 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3912 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? |
3862 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3913 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3863 | 3914 | ||
3864 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3915 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3865 | ad.u.net.dport = htons(snum); | 3916 | ad.u.net.dport = htons(snum); |
3866 | ad.u.net.family = sk->sk_family; | 3917 | ad.u.net.family = sk->sk_family; |
3867 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3918 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); |
@@ -3951,13 +4002,13 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, | |||
3951 | struct sk_security_struct *ssec; | 4002 | struct sk_security_struct *ssec; |
3952 | struct inode_security_struct *isec; | 4003 | struct inode_security_struct *isec; |
3953 | struct inode_security_struct *other_isec; | 4004 | struct inode_security_struct *other_isec; |
3954 | struct avc_audit_data ad; | 4005 | struct common_audit_data ad; |
3955 | int err; | 4006 | int err; |
3956 | 4007 | ||
3957 | isec = SOCK_INODE(sock)->i_security; | 4008 | isec = SOCK_INODE(sock)->i_security; |
3958 | other_isec = SOCK_INODE(other)->i_security; | 4009 | other_isec = SOCK_INODE(other)->i_security; |
3959 | 4010 | ||
3960 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4011 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3961 | ad.u.net.sk = other->sk; | 4012 | ad.u.net.sk = other->sk; |
3962 | 4013 | ||
3963 | err = avc_has_perm(isec->sid, other_isec->sid, | 4014 | err = avc_has_perm(isec->sid, other_isec->sid, |
@@ -3983,13 +4034,13 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
3983 | { | 4034 | { |
3984 | struct inode_security_struct *isec; | 4035 | struct inode_security_struct *isec; |
3985 | struct inode_security_struct *other_isec; | 4036 | struct inode_security_struct *other_isec; |
3986 | struct avc_audit_data ad; | 4037 | struct common_audit_data ad; |
3987 | int err; | 4038 | int err; |
3988 | 4039 | ||
3989 | isec = SOCK_INODE(sock)->i_security; | 4040 | isec = SOCK_INODE(sock)->i_security; |
3990 | other_isec = SOCK_INODE(other)->i_security; | 4041 | other_isec = SOCK_INODE(other)->i_security; |
3991 | 4042 | ||
3992 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4043 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3993 | ad.u.net.sk = other->sk; | 4044 | ad.u.net.sk = other->sk; |
3994 | 4045 | ||
3995 | err = avc_has_perm(isec->sid, other_isec->sid, | 4046 | err = avc_has_perm(isec->sid, other_isec->sid, |
@@ -4002,7 +4053,7 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
4002 | 4053 | ||
4003 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 4054 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
4004 | u32 peer_sid, | 4055 | u32 peer_sid, |
4005 | struct avc_audit_data *ad) | 4056 | struct common_audit_data *ad) |
4006 | { | 4057 | { |
4007 | int err; | 4058 | int err; |
4008 | u32 if_sid; | 4059 | u32 if_sid; |
@@ -4030,10 +4081,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4030 | struct sk_security_struct *sksec = sk->sk_security; | 4081 | struct sk_security_struct *sksec = sk->sk_security; |
4031 | u32 peer_sid; | 4082 | u32 peer_sid; |
4032 | u32 sk_sid = sksec->sid; | 4083 | u32 sk_sid = sksec->sid; |
4033 | struct avc_audit_data ad; | 4084 | struct common_audit_data ad; |
4034 | char *addrp; | 4085 | char *addrp; |
4035 | 4086 | ||
4036 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4087 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4037 | ad.u.net.netif = skb->iif; | 4088 | ad.u.net.netif = skb->iif; |
4038 | ad.u.net.family = family; | 4089 | ad.u.net.family = family; |
4039 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4090 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
@@ -4071,7 +4122,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4071 | struct sk_security_struct *sksec = sk->sk_security; | 4122 | struct sk_security_struct *sksec = sk->sk_security; |
4072 | u16 family = sk->sk_family; | 4123 | u16 family = sk->sk_family; |
4073 | u32 sk_sid = sksec->sid; | 4124 | u32 sk_sid = sksec->sid; |
4074 | struct avc_audit_data ad; | 4125 | struct common_audit_data ad; |
4075 | char *addrp; | 4126 | char *addrp; |
4076 | u8 secmark_active; | 4127 | u8 secmark_active; |
4077 | u8 peerlbl_active; | 4128 | u8 peerlbl_active; |
@@ -4095,7 +4146,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4095 | if (!secmark_active && !peerlbl_active) | 4146 | if (!secmark_active && !peerlbl_active) |
4096 | return 0; | 4147 | return 0; |
4097 | 4148 | ||
4098 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4149 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4099 | ad.u.net.netif = skb->iif; | 4150 | ad.u.net.netif = skb->iif; |
4100 | ad.u.net.family = family; | 4151 | ad.u.net.family = family; |
4101 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4152 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
@@ -4309,6 +4360,59 @@ static void selinux_req_classify_flow(const struct request_sock *req, | |||
4309 | fl->secid = req->secid; | 4360 | fl->secid = req->secid; |
4310 | } | 4361 | } |
4311 | 4362 | ||
4363 | static int selinux_tun_dev_create(void) | ||
4364 | { | ||
4365 | u32 sid = current_sid(); | ||
4366 | |||
4367 | /* we aren't taking into account the "sockcreate" SID since the socket | ||
4368 | * that is being created here is not a socket in the traditional sense, | ||
4369 | * instead it is a private sock, accessible only to the kernel, and | ||
4370 | * representing a wide range of network traffic spanning multiple | ||
4371 | * connections unlike traditional sockets - check the TUN driver to | ||
4372 | * get a better understanding of why this socket is special */ | ||
4373 | |||
4374 | return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, | ||
4375 | NULL); | ||
4376 | } | ||
4377 | |||
4378 | static void selinux_tun_dev_post_create(struct sock *sk) | ||
4379 | { | ||
4380 | struct sk_security_struct *sksec = sk->sk_security; | ||
4381 | |||
4382 | /* we don't currently perform any NetLabel based labeling here and it | ||
4383 | * isn't clear that we would want to do so anyway; while we could apply | ||
4384 | * labeling without the support of the TUN user the resulting labeled | ||
4385 | * traffic from the other end of the connection would almost certainly | ||
4386 | * cause confusion to the TUN user that had no idea network labeling | ||
4387 | * protocols were being used */ | ||
4388 | |||
4389 | /* see the comments in selinux_tun_dev_create() about why we don't use | ||
4390 | * the sockcreate SID here */ | ||
4391 | |||
4392 | sksec->sid = current_sid(); | ||
4393 | sksec->sclass = SECCLASS_TUN_SOCKET; | ||
4394 | } | ||
4395 | |||
4396 | static int selinux_tun_dev_attach(struct sock *sk) | ||
4397 | { | ||
4398 | struct sk_security_struct *sksec = sk->sk_security; | ||
4399 | u32 sid = current_sid(); | ||
4400 | int err; | ||
4401 | |||
4402 | err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET, | ||
4403 | TUN_SOCKET__RELABELFROM, NULL); | ||
4404 | if (err) | ||
4405 | return err; | ||
4406 | err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, | ||
4407 | TUN_SOCKET__RELABELTO, NULL); | ||
4408 | if (err) | ||
4409 | return err; | ||
4410 | |||
4411 | sksec->sid = sid; | ||
4412 | |||
4413 | return 0; | ||
4414 | } | ||
4415 | |||
4312 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | 4416 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) |
4313 | { | 4417 | { |
4314 | int err = 0; | 4418 | int err = 0; |
@@ -4353,7 +4457,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4353 | int err; | 4457 | int err; |
4354 | char *addrp; | 4458 | char *addrp; |
4355 | u32 peer_sid; | 4459 | u32 peer_sid; |
4356 | struct avc_audit_data ad; | 4460 | struct common_audit_data ad; |
4357 | u8 secmark_active; | 4461 | u8 secmark_active; |
4358 | u8 netlbl_active; | 4462 | u8 netlbl_active; |
4359 | u8 peerlbl_active; | 4463 | u8 peerlbl_active; |
@@ -4370,7 +4474,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4370 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | 4474 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) |
4371 | return NF_DROP; | 4475 | return NF_DROP; |
4372 | 4476 | ||
4373 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4477 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4374 | ad.u.net.netif = ifindex; | 4478 | ad.u.net.netif = ifindex; |
4375 | ad.u.net.family = family; | 4479 | ad.u.net.family = family; |
4376 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) | 4480 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) |
@@ -4458,7 +4562,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4458 | { | 4562 | { |
4459 | struct sock *sk = skb->sk; | 4563 | struct sock *sk = skb->sk; |
4460 | struct sk_security_struct *sksec; | 4564 | struct sk_security_struct *sksec; |
4461 | struct avc_audit_data ad; | 4565 | struct common_audit_data ad; |
4462 | char *addrp; | 4566 | char *addrp; |
4463 | u8 proto; | 4567 | u8 proto; |
4464 | 4568 | ||
@@ -4466,7 +4570,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4466 | return NF_ACCEPT; | 4570 | return NF_ACCEPT; |
4467 | sksec = sk->sk_security; | 4571 | sksec = sk->sk_security; |
4468 | 4572 | ||
4469 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4573 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4470 | ad.u.net.netif = ifindex; | 4574 | ad.u.net.netif = ifindex; |
4471 | ad.u.net.family = family; | 4575 | ad.u.net.family = family; |
4472 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) | 4576 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) |
@@ -4490,7 +4594,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4490 | u32 secmark_perm; | 4594 | u32 secmark_perm; |
4491 | u32 peer_sid; | 4595 | u32 peer_sid; |
4492 | struct sock *sk; | 4596 | struct sock *sk; |
4493 | struct avc_audit_data ad; | 4597 | struct common_audit_data ad; |
4494 | char *addrp; | 4598 | char *addrp; |
4495 | u8 secmark_active; | 4599 | u8 secmark_active; |
4496 | u8 peerlbl_active; | 4600 | u8 peerlbl_active; |
@@ -4549,7 +4653,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4549 | secmark_perm = PACKET__SEND; | 4653 | secmark_perm = PACKET__SEND; |
4550 | } | 4654 | } |
4551 | 4655 | ||
4552 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4656 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4553 | ad.u.net.netif = ifindex; | 4657 | ad.u.net.netif = ifindex; |
4554 | ad.u.net.family = family; | 4658 | ad.u.net.family = family; |
4555 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) | 4659 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) |
@@ -4619,13 +4723,13 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
4619 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) | 4723 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) |
4620 | { | 4724 | { |
4621 | int err; | 4725 | int err; |
4622 | struct avc_audit_data ad; | 4726 | struct common_audit_data ad; |
4623 | 4727 | ||
4624 | err = cap_netlink_recv(skb, capability); | 4728 | err = cap_netlink_recv(skb, capability); |
4625 | if (err) | 4729 | if (err) |
4626 | return err; | 4730 | return err; |
4627 | 4731 | ||
4628 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 4732 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
4629 | ad.u.cap = capability; | 4733 | ad.u.cap = capability; |
4630 | 4734 | ||
4631 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, | 4735 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, |
@@ -4684,12 +4788,12 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | |||
4684 | u32 perms) | 4788 | u32 perms) |
4685 | { | 4789 | { |
4686 | struct ipc_security_struct *isec; | 4790 | struct ipc_security_struct *isec; |
4687 | struct avc_audit_data ad; | 4791 | struct common_audit_data ad; |
4688 | u32 sid = current_sid(); | 4792 | u32 sid = current_sid(); |
4689 | 4793 | ||
4690 | isec = ipc_perms->security; | 4794 | isec = ipc_perms->security; |
4691 | 4795 | ||
4692 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4796 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4693 | ad.u.ipc_id = ipc_perms->key; | 4797 | ad.u.ipc_id = ipc_perms->key; |
4694 | 4798 | ||
4695 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 4799 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
@@ -4709,7 +4813,7 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg) | |||
4709 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | 4813 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) |
4710 | { | 4814 | { |
4711 | struct ipc_security_struct *isec; | 4815 | struct ipc_security_struct *isec; |
4712 | struct avc_audit_data ad; | 4816 | struct common_audit_data ad; |
4713 | u32 sid = current_sid(); | 4817 | u32 sid = current_sid(); |
4714 | int rc; | 4818 | int rc; |
4715 | 4819 | ||
@@ -4719,7 +4823,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
4719 | 4823 | ||
4720 | isec = msq->q_perm.security; | 4824 | isec = msq->q_perm.security; |
4721 | 4825 | ||
4722 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4826 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4723 | ad.u.ipc_id = msq->q_perm.key; | 4827 | ad.u.ipc_id = msq->q_perm.key; |
4724 | 4828 | ||
4725 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4829 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4739,12 +4843,12 @@ static void selinux_msg_queue_free_security(struct msg_queue *msq) | |||
4739 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) | 4843 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) |
4740 | { | 4844 | { |
4741 | struct ipc_security_struct *isec; | 4845 | struct ipc_security_struct *isec; |
4742 | struct avc_audit_data ad; | 4846 | struct common_audit_data ad; |
4743 | u32 sid = current_sid(); | 4847 | u32 sid = current_sid(); |
4744 | 4848 | ||
4745 | isec = msq->q_perm.security; | 4849 | isec = msq->q_perm.security; |
4746 | 4850 | ||
4747 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4851 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4748 | ad.u.ipc_id = msq->q_perm.key; | 4852 | ad.u.ipc_id = msq->q_perm.key; |
4749 | 4853 | ||
4750 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4854 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4783,7 +4887,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4783 | { | 4887 | { |
4784 | struct ipc_security_struct *isec; | 4888 | struct ipc_security_struct *isec; |
4785 | struct msg_security_struct *msec; | 4889 | struct msg_security_struct *msec; |
4786 | struct avc_audit_data ad; | 4890 | struct common_audit_data ad; |
4787 | u32 sid = current_sid(); | 4891 | u32 sid = current_sid(); |
4788 | int rc; | 4892 | int rc; |
4789 | 4893 | ||
@@ -4804,7 +4908,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4804 | return rc; | 4908 | return rc; |
4805 | } | 4909 | } |
4806 | 4910 | ||
4807 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4911 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4808 | ad.u.ipc_id = msq->q_perm.key; | 4912 | ad.u.ipc_id = msq->q_perm.key; |
4809 | 4913 | ||
4810 | /* Can this process write to the queue? */ | 4914 | /* Can this process write to the queue? */ |
@@ -4828,14 +4932,14 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4828 | { | 4932 | { |
4829 | struct ipc_security_struct *isec; | 4933 | struct ipc_security_struct *isec; |
4830 | struct msg_security_struct *msec; | 4934 | struct msg_security_struct *msec; |
4831 | struct avc_audit_data ad; | 4935 | struct common_audit_data ad; |
4832 | u32 sid = task_sid(target); | 4936 | u32 sid = task_sid(target); |
4833 | int rc; | 4937 | int rc; |
4834 | 4938 | ||
4835 | isec = msq->q_perm.security; | 4939 | isec = msq->q_perm.security; |
4836 | msec = msg->security; | 4940 | msec = msg->security; |
4837 | 4941 | ||
4838 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4942 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4839 | ad.u.ipc_id = msq->q_perm.key; | 4943 | ad.u.ipc_id = msq->q_perm.key; |
4840 | 4944 | ||
4841 | rc = avc_has_perm(sid, isec->sid, | 4945 | rc = avc_has_perm(sid, isec->sid, |
@@ -4850,7 +4954,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4850 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) | 4954 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) |
4851 | { | 4955 | { |
4852 | struct ipc_security_struct *isec; | 4956 | struct ipc_security_struct *isec; |
4853 | struct avc_audit_data ad; | 4957 | struct common_audit_data ad; |
4854 | u32 sid = current_sid(); | 4958 | u32 sid = current_sid(); |
4855 | int rc; | 4959 | int rc; |
4856 | 4960 | ||
@@ -4860,7 +4964,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
4860 | 4964 | ||
4861 | isec = shp->shm_perm.security; | 4965 | isec = shp->shm_perm.security; |
4862 | 4966 | ||
4863 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4967 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4864 | ad.u.ipc_id = shp->shm_perm.key; | 4968 | ad.u.ipc_id = shp->shm_perm.key; |
4865 | 4969 | ||
4866 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4970 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4880,12 +4984,12 @@ static void selinux_shm_free_security(struct shmid_kernel *shp) | |||
4880 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) | 4984 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) |
4881 | { | 4985 | { |
4882 | struct ipc_security_struct *isec; | 4986 | struct ipc_security_struct *isec; |
4883 | struct avc_audit_data ad; | 4987 | struct common_audit_data ad; |
4884 | u32 sid = current_sid(); | 4988 | u32 sid = current_sid(); |
4885 | 4989 | ||
4886 | isec = shp->shm_perm.security; | 4990 | isec = shp->shm_perm.security; |
4887 | 4991 | ||
4888 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4992 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4889 | ad.u.ipc_id = shp->shm_perm.key; | 4993 | ad.u.ipc_id = shp->shm_perm.key; |
4890 | 4994 | ||
4891 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4995 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4942,7 +5046,7 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, | |||
4942 | static int selinux_sem_alloc_security(struct sem_array *sma) | 5046 | static int selinux_sem_alloc_security(struct sem_array *sma) |
4943 | { | 5047 | { |
4944 | struct ipc_security_struct *isec; | 5048 | struct ipc_security_struct *isec; |
4945 | struct avc_audit_data ad; | 5049 | struct common_audit_data ad; |
4946 | u32 sid = current_sid(); | 5050 | u32 sid = current_sid(); |
4947 | int rc; | 5051 | int rc; |
4948 | 5052 | ||
@@ -4952,7 +5056,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
4952 | 5056 | ||
4953 | isec = sma->sem_perm.security; | 5057 | isec = sma->sem_perm.security; |
4954 | 5058 | ||
4955 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5059 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4956 | ad.u.ipc_id = sma->sem_perm.key; | 5060 | ad.u.ipc_id = sma->sem_perm.key; |
4957 | 5061 | ||
4958 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5062 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -4972,12 +5076,12 @@ static void selinux_sem_free_security(struct sem_array *sma) | |||
4972 | static int selinux_sem_associate(struct sem_array *sma, int semflg) | 5076 | static int selinux_sem_associate(struct sem_array *sma, int semflg) |
4973 | { | 5077 | { |
4974 | struct ipc_security_struct *isec; | 5078 | struct ipc_security_struct *isec; |
4975 | struct avc_audit_data ad; | 5079 | struct common_audit_data ad; |
4976 | u32 sid = current_sid(); | 5080 | u32 sid = current_sid(); |
4977 | 5081 | ||
4978 | isec = sma->sem_perm.security; | 5082 | isec = sma->sem_perm.security; |
4979 | 5083 | ||
4980 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5084 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4981 | ad.u.ipc_id = sma->sem_perm.key; | 5085 | ad.u.ipc_id = sma->sem_perm.key; |
4982 | 5086 | ||
4983 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5087 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -5195,7 +5299,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5195 | 5299 | ||
5196 | /* Only allow single threaded processes to change context */ | 5300 | /* Only allow single threaded processes to change context */ |
5197 | error = -EPERM; | 5301 | error = -EPERM; |
5198 | if (!is_single_threaded(p)) { | 5302 | if (!current_is_single_threaded()) { |
5199 | error = security_bounded_transition(tsec->sid, sid); | 5303 | error = security_bounded_transition(tsec->sid, sid); |
5200 | if (error) | 5304 | if (error) |
5201 | goto abort_change; | 5305 | goto abort_change; |
@@ -5252,6 +5356,32 @@ static void selinux_release_secctx(char *secdata, u32 seclen) | |||
5252 | kfree(secdata); | 5356 | kfree(secdata); |
5253 | } | 5357 | } |
5254 | 5358 | ||
5359 | /* | ||
5360 | * called with inode->i_mutex locked | ||
5361 | */ | ||
5362 | static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
5363 | { | ||
5364 | return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0); | ||
5365 | } | ||
5366 | |||
5367 | /* | ||
5368 | * called with inode->i_mutex locked | ||
5369 | */ | ||
5370 | static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
5371 | { | ||
5372 | return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0); | ||
5373 | } | ||
5374 | |||
5375 | static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
5376 | { | ||
5377 | int len = 0; | ||
5378 | len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX, | ||
5379 | ctx, true); | ||
5380 | if (len < 0) | ||
5381 | return len; | ||
5382 | *ctxlen = len; | ||
5383 | return 0; | ||
5384 | } | ||
5255 | #ifdef CONFIG_KEYS | 5385 | #ifdef CONFIG_KEYS |
5256 | 5386 | ||
5257 | static int selinux_key_alloc(struct key *k, const struct cred *cred, | 5387 | static int selinux_key_alloc(struct key *k, const struct cred *cred, |
@@ -5323,7 +5453,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
5323 | static struct security_operations selinux_ops = { | 5453 | static struct security_operations selinux_ops = { |
5324 | .name = "selinux", | 5454 | .name = "selinux", |
5325 | 5455 | ||
5326 | .ptrace_may_access = selinux_ptrace_may_access, | 5456 | .ptrace_access_check = selinux_ptrace_access_check, |
5327 | .ptrace_traceme = selinux_ptrace_traceme, | 5457 | .ptrace_traceme = selinux_ptrace_traceme, |
5328 | .capget = selinux_capget, | 5458 | .capget = selinux_capget, |
5329 | .capset = selinux_capset, | 5459 | .capset = selinux_capset, |
@@ -5396,10 +5526,13 @@ static struct security_operations selinux_ops = { | |||
5396 | .dentry_open = selinux_dentry_open, | 5526 | .dentry_open = selinux_dentry_open, |
5397 | 5527 | ||
5398 | .task_create = selinux_task_create, | 5528 | .task_create = selinux_task_create, |
5529 | .cred_alloc_blank = selinux_cred_alloc_blank, | ||
5399 | .cred_free = selinux_cred_free, | 5530 | .cred_free = selinux_cred_free, |
5400 | .cred_prepare = selinux_cred_prepare, | 5531 | .cred_prepare = selinux_cred_prepare, |
5532 | .cred_transfer = selinux_cred_transfer, | ||
5401 | .kernel_act_as = selinux_kernel_act_as, | 5533 | .kernel_act_as = selinux_kernel_act_as, |
5402 | .kernel_create_files_as = selinux_kernel_create_files_as, | 5534 | .kernel_create_files_as = selinux_kernel_create_files_as, |
5535 | .kernel_module_request = selinux_kernel_module_request, | ||
5403 | .task_setpgid = selinux_task_setpgid, | 5536 | .task_setpgid = selinux_task_setpgid, |
5404 | .task_getpgid = selinux_task_getpgid, | 5537 | .task_getpgid = selinux_task_getpgid, |
5405 | .task_getsid = selinux_task_getsid, | 5538 | .task_getsid = selinux_task_getsid, |
@@ -5448,6 +5581,9 @@ static struct security_operations selinux_ops = { | |||
5448 | .secid_to_secctx = selinux_secid_to_secctx, | 5581 | .secid_to_secctx = selinux_secid_to_secctx, |
5449 | .secctx_to_secid = selinux_secctx_to_secid, | 5582 | .secctx_to_secid = selinux_secctx_to_secid, |
5450 | .release_secctx = selinux_release_secctx, | 5583 | .release_secctx = selinux_release_secctx, |
5584 | .inode_notifysecctx = selinux_inode_notifysecctx, | ||
5585 | .inode_setsecctx = selinux_inode_setsecctx, | ||
5586 | .inode_getsecctx = selinux_inode_getsecctx, | ||
5451 | 5587 | ||
5452 | .unix_stream_connect = selinux_socket_unix_stream_connect, | 5588 | .unix_stream_connect = selinux_socket_unix_stream_connect, |
5453 | .unix_may_send = selinux_socket_unix_may_send, | 5589 | .unix_may_send = selinux_socket_unix_may_send, |
@@ -5477,6 +5613,9 @@ static struct security_operations selinux_ops = { | |||
5477 | .inet_csk_clone = selinux_inet_csk_clone, | 5613 | .inet_csk_clone = selinux_inet_csk_clone, |
5478 | .inet_conn_established = selinux_inet_conn_established, | 5614 | .inet_conn_established = selinux_inet_conn_established, |
5479 | .req_classify_flow = selinux_req_classify_flow, | 5615 | .req_classify_flow = selinux_req_classify_flow, |
5616 | .tun_dev_create = selinux_tun_dev_create, | ||
5617 | .tun_dev_post_create = selinux_tun_dev_post_create, | ||
5618 | .tun_dev_attach = selinux_tun_dev_attach, | ||
5480 | 5619 | ||
5481 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 5620 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
5482 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, | 5621 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, |
@@ -5691,6 +5830,9 @@ int selinux_disable(void) | |||
5691 | selinux_disabled = 1; | 5830 | selinux_disabled = 1; |
5692 | selinux_enabled = 0; | 5831 | selinux_enabled = 0; |
5693 | 5832 | ||
5833 | /* Try to destroy the avc node cache */ | ||
5834 | avc_disable(); | ||
5835 | |||
5694 | /* Reset security_ops to the secondary module, dummy or capability. */ | 5836 | /* Reset security_ops to the secondary module, dummy or capability. */ |
5695 | security_ops = secondary_ops; | 5837 | security_ops = secondary_ops; |
5696 | 5838 | ||
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h index 8377a4ba3b95..abedcd704dae 100644 --- a/security/selinux/include/av_inherit.h +++ b/security/selinux/include/av_inherit.h | |||
@@ -15,6 +15,7 @@ | |||
15 | S_(SECCLASS_KEY_SOCKET, socket, 0x00400000UL) | 15 | S_(SECCLASS_KEY_SOCKET, socket, 0x00400000UL) |
16 | S_(SECCLASS_UNIX_STREAM_SOCKET, socket, 0x00400000UL) | 16 | S_(SECCLASS_UNIX_STREAM_SOCKET, socket, 0x00400000UL) |
17 | S_(SECCLASS_UNIX_DGRAM_SOCKET, socket, 0x00400000UL) | 17 | S_(SECCLASS_UNIX_DGRAM_SOCKET, socket, 0x00400000UL) |
18 | S_(SECCLASS_TUN_SOCKET, socket, 0x00400000UL) | ||
18 | S_(SECCLASS_IPC, ipc, 0x00000200UL) | 19 | S_(SECCLASS_IPC, ipc, 0x00000200UL) |
19 | S_(SECCLASS_SEM, ipc, 0x00000200UL) | 20 | S_(SECCLASS_SEM, ipc, 0x00000200UL) |
20 | S_(SECCLASS_MSGQ, ipc, 0x00000200UL) | 21 | S_(SECCLASS_MSGQ, ipc, 0x00000200UL) |
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 31df1d7c1aee..2b683ad83d21 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h | |||
@@ -107,6 +107,7 @@ | |||
107 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") | 107 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") |
108 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") | 108 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") |
109 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") | 109 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") |
110 | S_(SECCLASS_SYSTEM, SYSTEM__MODULE_REQUEST, "module_request") | ||
110 | S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") | 111 | S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") |
111 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override") | 112 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override") |
112 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search") | 113 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search") |
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index d645192ee950..0546d616ccac 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h | |||
@@ -423,6 +423,28 @@ | |||
423 | #define UNIX_DGRAM_SOCKET__RECV_MSG 0x00080000UL | 423 | #define UNIX_DGRAM_SOCKET__RECV_MSG 0x00080000UL |
424 | #define UNIX_DGRAM_SOCKET__SEND_MSG 0x00100000UL | 424 | #define UNIX_DGRAM_SOCKET__SEND_MSG 0x00100000UL |
425 | #define UNIX_DGRAM_SOCKET__NAME_BIND 0x00200000UL | 425 | #define UNIX_DGRAM_SOCKET__NAME_BIND 0x00200000UL |
426 | #define TUN_SOCKET__IOCTL 0x00000001UL | ||
427 | #define TUN_SOCKET__READ 0x00000002UL | ||
428 | #define TUN_SOCKET__WRITE 0x00000004UL | ||
429 | #define TUN_SOCKET__CREATE 0x00000008UL | ||
430 | #define TUN_SOCKET__GETATTR 0x00000010UL | ||
431 | #define TUN_SOCKET__SETATTR 0x00000020UL | ||
432 | #define TUN_SOCKET__LOCK 0x00000040UL | ||
433 | #define TUN_SOCKET__RELABELFROM 0x00000080UL | ||
434 | #define TUN_SOCKET__RELABELTO 0x00000100UL | ||
435 | #define TUN_SOCKET__APPEND 0x00000200UL | ||
436 | #define TUN_SOCKET__BIND 0x00000400UL | ||
437 | #define TUN_SOCKET__CONNECT 0x00000800UL | ||
438 | #define TUN_SOCKET__LISTEN 0x00001000UL | ||
439 | #define TUN_SOCKET__ACCEPT 0x00002000UL | ||
440 | #define TUN_SOCKET__GETOPT 0x00004000UL | ||
441 | #define TUN_SOCKET__SETOPT 0x00008000UL | ||
442 | #define TUN_SOCKET__SHUTDOWN 0x00010000UL | ||
443 | #define TUN_SOCKET__RECVFROM 0x00020000UL | ||
444 | #define TUN_SOCKET__SENDTO 0x00040000UL | ||
445 | #define TUN_SOCKET__RECV_MSG 0x00080000UL | ||
446 | #define TUN_SOCKET__SEND_MSG 0x00100000UL | ||
447 | #define TUN_SOCKET__NAME_BIND 0x00200000UL | ||
426 | #define PROCESS__FORK 0x00000001UL | 448 | #define PROCESS__FORK 0x00000001UL |
427 | #define PROCESS__TRANSITION 0x00000002UL | 449 | #define PROCESS__TRANSITION 0x00000002UL |
428 | #define PROCESS__SIGCHLD 0x00000004UL | 450 | #define PROCESS__SIGCHLD 0x00000004UL |
@@ -508,6 +530,7 @@ | |||
508 | #define SYSTEM__SYSLOG_READ 0x00000002UL | 530 | #define SYSTEM__SYSLOG_READ 0x00000002UL |
509 | #define SYSTEM__SYSLOG_MOD 0x00000004UL | 531 | #define SYSTEM__SYSLOG_MOD 0x00000004UL |
510 | #define SYSTEM__SYSLOG_CONSOLE 0x00000008UL | 532 | #define SYSTEM__SYSLOG_CONSOLE 0x00000008UL |
533 | #define SYSTEM__MODULE_REQUEST 0x00000010UL | ||
511 | #define CAPABILITY__CHOWN 0x00000001UL | 534 | #define CAPABILITY__CHOWN 0x00000001UL |
512 | #define CAPABILITY__DAC_OVERRIDE 0x00000002UL | 535 | #define CAPABILITY__DAC_OVERRIDE 0x00000002UL |
513 | #define CAPABILITY__DAC_READ_SEARCH 0x00000004UL | 536 | #define CAPABILITY__DAC_READ_SEARCH 0x00000004UL |
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index d12ff1a9c0aa..e94e82f73818 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/audit.h> | 15 | #include <linux/audit.h> |
16 | #include <linux/lsm_audit.h> | ||
16 | #include <linux/in6.h> | 17 | #include <linux/in6.h> |
17 | #include <linux/path.h> | 18 | #include <linux/path.h> |
18 | #include <asm/system.h> | 19 | #include <asm/system.h> |
@@ -36,48 +37,6 @@ struct inode; | |||
36 | struct sock; | 37 | struct sock; |
37 | struct sk_buff; | 38 | struct sk_buff; |
38 | 39 | ||
39 | /* Auxiliary data to use in generating the audit record. */ | ||
40 | struct avc_audit_data { | ||
41 | char type; | ||
42 | #define AVC_AUDIT_DATA_FS 1 | ||
43 | #define AVC_AUDIT_DATA_NET 2 | ||
44 | #define AVC_AUDIT_DATA_CAP 3 | ||
45 | #define AVC_AUDIT_DATA_IPC 4 | ||
46 | struct task_struct *tsk; | ||
47 | union { | ||
48 | struct { | ||
49 | struct path path; | ||
50 | struct inode *inode; | ||
51 | } fs; | ||
52 | struct { | ||
53 | int netif; | ||
54 | struct sock *sk; | ||
55 | u16 family; | ||
56 | __be16 dport; | ||
57 | __be16 sport; | ||
58 | union { | ||
59 | struct { | ||
60 | __be32 daddr; | ||
61 | __be32 saddr; | ||
62 | } v4; | ||
63 | struct { | ||
64 | struct in6_addr daddr; | ||
65 | struct in6_addr saddr; | ||
66 | } v6; | ||
67 | } fam; | ||
68 | } net; | ||
69 | int cap; | ||
70 | int ipc_id; | ||
71 | } u; | ||
72 | }; | ||
73 | |||
74 | #define v4info fam.v4 | ||
75 | #define v6info fam.v6 | ||
76 | |||
77 | /* Initialize an AVC audit data structure. */ | ||
78 | #define AVC_AUDIT_DATA_INIT(_d,_t) \ | ||
79 | { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; } | ||
80 | |||
81 | /* | 40 | /* |
82 | * AVC statistics | 41 | * AVC statistics |
83 | */ | 42 | */ |
@@ -98,7 +57,9 @@ void __init avc_init(void); | |||
98 | 57 | ||
99 | void avc_audit(u32 ssid, u32 tsid, | 58 | void avc_audit(u32 ssid, u32 tsid, |
100 | u16 tclass, u32 requested, | 59 | u16 tclass, u32 requested, |
101 | struct av_decision *avd, int result, struct avc_audit_data *auditdata); | 60 | struct av_decision *avd, |
61 | int result, | ||
62 | struct common_audit_data *a); | ||
102 | 63 | ||
103 | #define AVC_STRICT 1 /* Ignore permissive mode. */ | 64 | #define AVC_STRICT 1 /* Ignore permissive mode. */ |
104 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 65 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, |
@@ -108,7 +69,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
108 | 69 | ||
109 | int avc_has_perm(u32 ssid, u32 tsid, | 70 | int avc_has_perm(u32 ssid, u32 tsid, |
110 | u16 tclass, u32 requested, | 71 | u16 tclass, u32 requested, |
111 | struct avc_audit_data *auditdata); | 72 | struct common_audit_data *auditdata); |
112 | 73 | ||
113 | u32 avc_policy_seqno(void); | 74 | u32 avc_policy_seqno(void); |
114 | 75 | ||
@@ -127,13 +88,13 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | |||
127 | u32 events, u32 ssid, u32 tsid, | 88 | u32 events, u32 ssid, u32 tsid, |
128 | u16 tclass, u32 perms); | 89 | u16 tclass, u32 perms); |
129 | 90 | ||
130 | /* Shows permission in human readable form */ | ||
131 | void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av); | ||
132 | |||
133 | /* Exported to selinuxfs */ | 91 | /* Exported to selinuxfs */ |
134 | int avc_get_hash_stats(char *page); | 92 | int avc_get_hash_stats(char *page); |
135 | extern unsigned int avc_cache_threshold; | 93 | extern unsigned int avc_cache_threshold; |
136 | 94 | ||
95 | /* Attempt to free avc node cache */ | ||
96 | void avc_disable(void); | ||
97 | |||
137 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS | 98 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS |
138 | DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); | 99 | DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); |
139 | #endif | 100 | #endif |
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index 21ec786611d4..7ab9299bfb6b 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h | |||
@@ -77,3 +77,4 @@ | |||
77 | S_(NULL) | 77 | S_(NULL) |
78 | S_(NULL) | 78 | S_(NULL) |
79 | S_("kernel_service") | 79 | S_("kernel_service") |
80 | S_("tun_socket") | ||
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index 882f27d66fac..f248500a1e3c 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h | |||
@@ -53,6 +53,7 @@ | |||
53 | #define SECCLASS_PEER 68 | 53 | #define SECCLASS_PEER 68 |
54 | #define SECCLASS_CAPABILITY2 69 | 54 | #define SECCLASS_CAPABILITY2 69 |
55 | #define SECCLASS_KERNEL_SERVICE 74 | 55 | #define SECCLASS_KERNEL_SERVICE 74 |
56 | #define SECCLASS_TUN_SOCKET 75 | ||
56 | 57 | ||
57 | /* | 58 | /* |
58 | * Security identifier indices for initial entities | 59 | * Security identifier indices for initial entities |
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index b4b5b9b2f0be..8d7384280a7a 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h | |||
@@ -59,7 +59,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family); | |||
59 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 59 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
60 | struct sk_buff *skb, | 60 | struct sk_buff *skb, |
61 | u16 family, | 61 | u16 family, |
62 | struct avc_audit_data *ad); | 62 | struct common_audit_data *ad); |
63 | int selinux_netlbl_socket_setsockopt(struct socket *sock, | 63 | int selinux_netlbl_socket_setsockopt(struct socket *sock, |
64 | int level, | 64 | int level, |
65 | int optname); | 65 | int optname); |
@@ -129,7 +129,7 @@ static inline int selinux_netlbl_socket_post_create(struct sock *sk, | |||
129 | static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 129 | static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
130 | struct sk_buff *skb, | 130 | struct sk_buff *skb, |
131 | u16 family, | 131 | u16 family, |
132 | struct avc_audit_data *ad) | 132 | struct common_audit_data *ad) |
133 | { | 133 | { |
134 | return 0; | 134 | return 0; |
135 | } | 135 | } |
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 289e24b39e3e..13128f9a3e5a 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
@@ -41,9 +41,9 @@ static inline int selinux_xfrm_enabled(void) | |||
41 | } | 41 | } |
42 | 42 | ||
43 | int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, | 43 | int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, |
44 | struct avc_audit_data *ad); | 44 | struct common_audit_data *ad); |
45 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 45 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
46 | struct avc_audit_data *ad, u8 proto); | 46 | struct common_audit_data *ad, u8 proto); |
47 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); | 47 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); |
48 | 48 | ||
49 | static inline void selinux_xfrm_notify_policyload(void) | 49 | static inline void selinux_xfrm_notify_policyload(void) |
@@ -57,13 +57,13 @@ static inline int selinux_xfrm_enabled(void) | |||
57 | } | 57 | } |
58 | 58 | ||
59 | static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 59 | static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, |
60 | struct avc_audit_data *ad) | 60 | struct common_audit_data *ad) |
61 | { | 61 | { |
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 65 | static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
66 | struct avc_audit_data *ad, u8 proto) | 66 | struct common_audit_data *ad, u8 proto) |
67 | { | 67 | { |
68 | return 0; | 68 | return 0; |
69 | } | 69 | } |
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 2e984413c7b2..e68823741ad5 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
@@ -342,7 +342,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) | |||
342 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 342 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
343 | struct sk_buff *skb, | 343 | struct sk_buff *skb, |
344 | u16 family, | 344 | u16 family, |
345 | struct avc_audit_data *ad) | 345 | struct common_audit_data *ad) |
346 | { | 346 | { |
347 | int rc; | 347 | int rc; |
348 | u32 nlbl_sid; | 348 | u32 nlbl_sid; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 500e6f78e115..ff17820d35ec 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -22,6 +22,11 @@ | |||
22 | * | 22 | * |
23 | * Added validation of kernel classes and permissions | 23 | * Added validation of kernel classes and permissions |
24 | * | 24 | * |
25 | * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
26 | * | ||
27 | * Added support for bounds domain and audit messaged on masked permissions | ||
28 | * | ||
29 | * Copyright (C) 2008, 2009 NEC Corporation | ||
25 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 30 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. |
26 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. | 31 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
27 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC | 32 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC |
@@ -279,6 +284,95 @@ mls_ops: | |||
279 | } | 284 | } |
280 | 285 | ||
281 | /* | 286 | /* |
287 | * security_dump_masked_av - dumps masked permissions during | ||
288 | * security_compute_av due to RBAC, MLS/Constraint and Type bounds. | ||
289 | */ | ||
290 | static int dump_masked_av_helper(void *k, void *d, void *args) | ||
291 | { | ||
292 | struct perm_datum *pdatum = d; | ||
293 | char **permission_names = args; | ||
294 | |||
295 | BUG_ON(pdatum->value < 1 || pdatum->value > 32); | ||
296 | |||
297 | permission_names[pdatum->value - 1] = (char *)k; | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static void security_dump_masked_av(struct context *scontext, | ||
303 | struct context *tcontext, | ||
304 | u16 tclass, | ||
305 | u32 permissions, | ||
306 | const char *reason) | ||
307 | { | ||
308 | struct common_datum *common_dat; | ||
309 | struct class_datum *tclass_dat; | ||
310 | struct audit_buffer *ab; | ||
311 | char *tclass_name; | ||
312 | char *scontext_name = NULL; | ||
313 | char *tcontext_name = NULL; | ||
314 | char *permission_names[32]; | ||
315 | int index, length; | ||
316 | bool need_comma = false; | ||
317 | |||
318 | if (!permissions) | ||
319 | return; | ||
320 | |||
321 | tclass_name = policydb.p_class_val_to_name[tclass - 1]; | ||
322 | tclass_dat = policydb.class_val_to_struct[tclass - 1]; | ||
323 | common_dat = tclass_dat->comdatum; | ||
324 | |||
325 | /* init permission_names */ | ||
326 | if (common_dat && | ||
327 | hashtab_map(common_dat->permissions.table, | ||
328 | dump_masked_av_helper, permission_names) < 0) | ||
329 | goto out; | ||
330 | |||
331 | if (hashtab_map(tclass_dat->permissions.table, | ||
332 | dump_masked_av_helper, permission_names) < 0) | ||
333 | goto out; | ||
334 | |||
335 | /* get scontext/tcontext in text form */ | ||
336 | if (context_struct_to_string(scontext, | ||
337 | &scontext_name, &length) < 0) | ||
338 | goto out; | ||
339 | |||
340 | if (context_struct_to_string(tcontext, | ||
341 | &tcontext_name, &length) < 0) | ||
342 | goto out; | ||
343 | |||
344 | /* audit a message */ | ||
345 | ab = audit_log_start(current->audit_context, | ||
346 | GFP_ATOMIC, AUDIT_SELINUX_ERR); | ||
347 | if (!ab) | ||
348 | goto out; | ||
349 | |||
350 | audit_log_format(ab, "op=security_compute_av reason=%s " | ||
351 | "scontext=%s tcontext=%s tclass=%s perms=", | ||
352 | reason, scontext_name, tcontext_name, tclass_name); | ||
353 | |||
354 | for (index = 0; index < 32; index++) { | ||
355 | u32 mask = (1 << index); | ||
356 | |||
357 | if ((mask & permissions) == 0) | ||
358 | continue; | ||
359 | |||
360 | audit_log_format(ab, "%s%s", | ||
361 | need_comma ? "," : "", | ||
362 | permission_names[index] | ||
363 | ? permission_names[index] : "????"); | ||
364 | need_comma = true; | ||
365 | } | ||
366 | audit_log_end(ab); | ||
367 | out: | ||
368 | /* release scontext/tcontext */ | ||
369 | kfree(tcontext_name); | ||
370 | kfree(scontext_name); | ||
371 | |||
372 | return; | ||
373 | } | ||
374 | |||
375 | /* | ||
282 | * security_boundary_permission - drops violated permissions | 376 | * security_boundary_permission - drops violated permissions |
283 | * on boundary constraint. | 377 | * on boundary constraint. |
284 | */ | 378 | */ |
@@ -347,28 +441,12 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
347 | } | 441 | } |
348 | 442 | ||
349 | if (masked) { | 443 | if (masked) { |
350 | struct audit_buffer *ab; | ||
351 | char *stype_name | ||
352 | = policydb.p_type_val_to_name[source->value - 1]; | ||
353 | char *ttype_name | ||
354 | = policydb.p_type_val_to_name[target->value - 1]; | ||
355 | char *tclass_name | ||
356 | = policydb.p_class_val_to_name[tclass - 1]; | ||
357 | |||
358 | /* mask violated permissions */ | 444 | /* mask violated permissions */ |
359 | avd->allowed &= ~masked; | 445 | avd->allowed &= ~masked; |
360 | 446 | ||
361 | /* notice to userspace via audit message */ | 447 | /* audit masked permissions */ |
362 | ab = audit_log_start(current->audit_context, | 448 | security_dump_masked_av(scontext, tcontext, |
363 | GFP_ATOMIC, AUDIT_SELINUX_ERR); | 449 | tclass, masked, "bounds"); |
364 | if (!ab) | ||
365 | return; | ||
366 | |||
367 | audit_log_format(ab, "av boundary violation: " | ||
368 | "source=%s target=%s tclass=%s", | ||
369 | stype_name, ttype_name, tclass_name); | ||
370 | avc_dump_av(ab, tclass, masked); | ||
371 | audit_log_end(ab); | ||
372 | } | 450 | } |
373 | } | 451 | } |
374 | 452 | ||
@@ -480,7 +558,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
480 | if ((constraint->permissions & (avd->allowed)) && | 558 | if ((constraint->permissions & (avd->allowed)) && |
481 | !constraint_expr_eval(scontext, tcontext, NULL, | 559 | !constraint_expr_eval(scontext, tcontext, NULL, |
482 | constraint->expr)) { | 560 | constraint->expr)) { |
483 | avd->allowed = (avd->allowed) & ~(constraint->permissions); | 561 | avd->allowed &= ~(constraint->permissions); |
484 | } | 562 | } |
485 | constraint = constraint->next; | 563 | constraint = constraint->next; |
486 | } | 564 | } |
@@ -499,8 +577,8 @@ static int context_struct_compute_av(struct context *scontext, | |||
499 | break; | 577 | break; |
500 | } | 578 | } |
501 | if (!ra) | 579 | if (!ra) |
502 | avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | | 580 | avd->allowed &= ~(PROCESS__TRANSITION | |
503 | PROCESS__DYNTRANSITION); | 581 | PROCESS__DYNTRANSITION); |
504 | } | 582 | } |
505 | 583 | ||
506 | /* | 584 | /* |
@@ -687,6 +765,26 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
687 | } | 765 | } |
688 | index = type->bounds; | 766 | index = type->bounds; |
689 | } | 767 | } |
768 | |||
769 | if (rc) { | ||
770 | char *old_name = NULL; | ||
771 | char *new_name = NULL; | ||
772 | int length; | ||
773 | |||
774 | if (!context_struct_to_string(old_context, | ||
775 | &old_name, &length) && | ||
776 | !context_struct_to_string(new_context, | ||
777 | &new_name, &length)) { | ||
778 | audit_log(current->audit_context, | ||
779 | GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
780 | "op=security_bounded_transition " | ||
781 | "result=denied " | ||
782 | "oldcontext=%s newcontext=%s", | ||
783 | old_name, new_name); | ||
784 | } | ||
785 | kfree(new_name); | ||
786 | kfree(old_name); | ||
787 | } | ||
690 | out: | 788 | out: |
691 | read_unlock(&policy_rwlock); | 789 | read_unlock(&policy_rwlock); |
692 | 790 | ||
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 72b18452e1a1..f3cb9ed731a9 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
@@ -401,7 +401,7 @@ int selinux_xfrm_state_delete(struct xfrm_state *x) | |||
401 | * gone thru the IPSec process. | 401 | * gone thru the IPSec process. |
402 | */ | 402 | */ |
403 | int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 403 | int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, |
404 | struct avc_audit_data *ad) | 404 | struct common_audit_data *ad) |
405 | { | 405 | { |
406 | int i, rc = 0; | 406 | int i, rc = 0; |
407 | struct sec_path *sp; | 407 | struct sec_path *sp; |
@@ -442,7 +442,7 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | |||
442 | * checked in the selinux_xfrm_state_pol_flow_match hook above. | 442 | * checked in the selinux_xfrm_state_pol_flow_match hook above. |
443 | */ | 443 | */ |
444 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 444 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
445 | struct avc_audit_data *ad, u8 proto) | 445 | struct common_audit_data *ad, u8 proto) |
446 | { | 446 | { |
447 | struct dst_entry *dst; | 447 | struct dst_entry *dst; |
448 | int rc = 0; | 448 | int rc = 0; |
diff --git a/security/smack/smack.h b/security/smack/smack.h index 243bec175be0..c6e9acae72e4 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -275,7 +275,7 @@ static inline void smk_ad_init(struct smk_audit_info *a, const char *func, | |||
275 | { | 275 | { |
276 | memset(a, 0, sizeof(*a)); | 276 | memset(a, 0, sizeof(*a)); |
277 | a->a.type = type; | 277 | a->a.type = type; |
278 | a->a.function = func; | 278 | a->a.smack_audit_data.function = func; |
279 | } | 279 | } |
280 | 280 | ||
281 | static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a, | 281 | static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a, |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 513dc1aa16dd..0f9ac8146900 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -240,8 +240,9 @@ static inline void smack_str_from_perm(char *string, int access) | |||
240 | static void smack_log_callback(struct audit_buffer *ab, void *a) | 240 | static void smack_log_callback(struct audit_buffer *ab, void *a) |
241 | { | 241 | { |
242 | struct common_audit_data *ad = a; | 242 | struct common_audit_data *ad = a; |
243 | struct smack_audit_data *sad = &ad->lsm_priv.smack_audit_data; | 243 | struct smack_audit_data *sad = &ad->smack_audit_data; |
244 | audit_log_format(ab, "lsm=SMACK fn=%s action=%s", ad->function, | 244 | audit_log_format(ab, "lsm=SMACK fn=%s action=%s", |
245 | ad->smack_audit_data.function, | ||
245 | sad->result ? "denied" : "granted"); | 246 | sad->result ? "denied" : "granted"); |
246 | audit_log_format(ab, " subject="); | 247 | audit_log_format(ab, " subject="); |
247 | audit_log_untrustedstring(ab, sad->subject); | 248 | audit_log_untrustedstring(ab, sad->subject); |
@@ -274,11 +275,11 @@ void smack_log(char *subject_label, char *object_label, int request, | |||
274 | if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0) | 275 | if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0) |
275 | return; | 276 | return; |
276 | 277 | ||
277 | if (a->function == NULL) | 278 | if (a->smack_audit_data.function == NULL) |
278 | a->function = "unknown"; | 279 | a->smack_audit_data.function = "unknown"; |
279 | 280 | ||
280 | /* end preparing the audit data */ | 281 | /* end preparing the audit data */ |
281 | sad = &a->lsm_priv.smack_audit_data; | 282 | sad = &a->smack_audit_data; |
282 | smack_str_from_perm(request_buffer, request); | 283 | smack_str_from_perm(request_buffer, request); |
283 | sad->subject = subject_label; | 284 | sad->subject = subject_label; |
284 | sad->object = object_label; | 285 | sad->object = object_label; |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 0023182078c7..acae7ef4092d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -91,7 +91,7 @@ struct inode_smack *new_inode_smack(char *smack) | |||
91 | */ | 91 | */ |
92 | 92 | ||
93 | /** | 93 | /** |
94 | * smack_ptrace_may_access - Smack approval on PTRACE_ATTACH | 94 | * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH |
95 | * @ctp: child task pointer | 95 | * @ctp: child task pointer |
96 | * @mode: ptrace attachment mode | 96 | * @mode: ptrace attachment mode |
97 | * | 97 | * |
@@ -99,13 +99,13 @@ struct inode_smack *new_inode_smack(char *smack) | |||
99 | * | 99 | * |
100 | * Do the capability checks, and require read and write. | 100 | * Do the capability checks, and require read and write. |
101 | */ | 101 | */ |
102 | static int smack_ptrace_may_access(struct task_struct *ctp, unsigned int mode) | 102 | static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) |
103 | { | 103 | { |
104 | int rc; | 104 | int rc; |
105 | struct smk_audit_info ad; | 105 | struct smk_audit_info ad; |
106 | char *sp, *tsp; | 106 | char *sp, *tsp; |
107 | 107 | ||
108 | rc = cap_ptrace_may_access(ctp, mode); | 108 | rc = cap_ptrace_access_check(ctp, mode); |
109 | if (rc != 0) | 109 | if (rc != 0) |
110 | return rc; | 110 | return rc; |
111 | 111 | ||
@@ -1080,6 +1080,22 @@ static int smack_file_receive(struct file *file) | |||
1080 | */ | 1080 | */ |
1081 | 1081 | ||
1082 | /** | 1082 | /** |
1083 | * smack_cred_alloc_blank - "allocate" blank task-level security credentials | ||
1084 | * @new: the new credentials | ||
1085 | * @gfp: the atomicity of any memory allocations | ||
1086 | * | ||
1087 | * Prepare a blank set of credentials for modification. This must allocate all | ||
1088 | * the memory the LSM module might require such that cred_transfer() can | ||
1089 | * complete without error. | ||
1090 | */ | ||
1091 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | ||
1092 | { | ||
1093 | cred->security = NULL; | ||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | |||
1098 | /** | ||
1083 | * smack_cred_free - "free" task-level security credentials | 1099 | * smack_cred_free - "free" task-level security credentials |
1084 | * @cred: the credentials in question | 1100 | * @cred: the credentials in question |
1085 | * | 1101 | * |
@@ -1117,6 +1133,18 @@ static void smack_cred_commit(struct cred *new, const struct cred *old) | |||
1117 | } | 1133 | } |
1118 | 1134 | ||
1119 | /** | 1135 | /** |
1136 | * smack_cred_transfer - Transfer the old credentials to the new credentials | ||
1137 | * @new: the new credentials | ||
1138 | * @old: the original credentials | ||
1139 | * | ||
1140 | * Fill in a set of blank credentials from another set of credentials. | ||
1141 | */ | ||
1142 | static void smack_cred_transfer(struct cred *new, const struct cred *old) | ||
1143 | { | ||
1144 | new->security = old->security; | ||
1145 | } | ||
1146 | |||
1147 | /** | ||
1120 | * smack_kernel_act_as - Set the subjective context in a set of credentials | 1148 | * smack_kernel_act_as - Set the subjective context in a set of credentials |
1121 | * @new: points to the set of credentials to be modified. | 1149 | * @new: points to the set of credentials to be modified. |
1122 | * @secid: specifies the security ID to be set | 1150 | * @secid: specifies the security ID to be set |
@@ -1638,6 +1666,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
1638 | 1666 | ||
1639 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { | 1667 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { |
1640 | nsp->smk_inode = sp; | 1668 | nsp->smk_inode = sp; |
1669 | nsp->smk_flags |= SMK_INODE_INSTANT; | ||
1641 | return 0; | 1670 | return 0; |
1642 | } | 1671 | } |
1643 | /* | 1672 | /* |
@@ -2464,7 +2493,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
2464 | /* | 2493 | /* |
2465 | * Perfectly reasonable for this to be NULL | 2494 | * Perfectly reasonable for this to be NULL |
2466 | */ | 2495 | */ |
2467 | if (sip == NULL || sip->sin_family != PF_INET) | 2496 | if (sip == NULL || sip->sin_family != AF_INET) |
2468 | return 0; | 2497 | return 0; |
2469 | 2498 | ||
2470 | return smack_netlabel_send(sock->sk, sip); | 2499 | return smack_netlabel_send(sock->sk, sip); |
@@ -3029,10 +3058,31 @@ static void smack_release_secctx(char *secdata, u32 seclen) | |||
3029 | { | 3058 | { |
3030 | } | 3059 | } |
3031 | 3060 | ||
3061 | static int smack_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
3062 | { | ||
3063 | return smack_inode_setsecurity(inode, XATTR_SMACK_SUFFIX, ctx, ctxlen, 0); | ||
3064 | } | ||
3065 | |||
3066 | static int smack_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
3067 | { | ||
3068 | return __vfs_setxattr_noperm(dentry, XATTR_NAME_SMACK, ctx, ctxlen, 0); | ||
3069 | } | ||
3070 | |||
3071 | static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
3072 | { | ||
3073 | int len = 0; | ||
3074 | len = smack_inode_getsecurity(inode, XATTR_SMACK_SUFFIX, ctx, true); | ||
3075 | |||
3076 | if (len < 0) | ||
3077 | return len; | ||
3078 | *ctxlen = len; | ||
3079 | return 0; | ||
3080 | } | ||
3081 | |||
3032 | struct security_operations smack_ops = { | 3082 | struct security_operations smack_ops = { |
3033 | .name = "smack", | 3083 | .name = "smack", |
3034 | 3084 | ||
3035 | .ptrace_may_access = smack_ptrace_may_access, | 3085 | .ptrace_access_check = smack_ptrace_access_check, |
3036 | .ptrace_traceme = smack_ptrace_traceme, | 3086 | .ptrace_traceme = smack_ptrace_traceme, |
3037 | .syslog = smack_syslog, | 3087 | .syslog = smack_syslog, |
3038 | 3088 | ||
@@ -3073,9 +3123,11 @@ struct security_operations smack_ops = { | |||
3073 | .file_send_sigiotask = smack_file_send_sigiotask, | 3123 | .file_send_sigiotask = smack_file_send_sigiotask, |
3074 | .file_receive = smack_file_receive, | 3124 | .file_receive = smack_file_receive, |
3075 | 3125 | ||
3126 | .cred_alloc_blank = smack_cred_alloc_blank, | ||
3076 | .cred_free = smack_cred_free, | 3127 | .cred_free = smack_cred_free, |
3077 | .cred_prepare = smack_cred_prepare, | 3128 | .cred_prepare = smack_cred_prepare, |
3078 | .cred_commit = smack_cred_commit, | 3129 | .cred_commit = smack_cred_commit, |
3130 | .cred_transfer = smack_cred_transfer, | ||
3079 | .kernel_act_as = smack_kernel_act_as, | 3131 | .kernel_act_as = smack_kernel_act_as, |
3080 | .kernel_create_files_as = smack_kernel_create_files_as, | 3132 | .kernel_create_files_as = smack_kernel_create_files_as, |
3081 | .task_setpgid = smack_task_setpgid, | 3133 | .task_setpgid = smack_task_setpgid, |
@@ -3155,6 +3207,9 @@ struct security_operations smack_ops = { | |||
3155 | .secid_to_secctx = smack_secid_to_secctx, | 3207 | .secid_to_secctx = smack_secid_to_secctx, |
3156 | .secctx_to_secid = smack_secctx_to_secid, | 3208 | .secctx_to_secid = smack_secctx_to_secid, |
3157 | .release_secctx = smack_release_secctx, | 3209 | .release_secctx = smack_release_secctx, |
3210 | .inode_notifysecctx = smack_inode_notifysecctx, | ||
3211 | .inode_setsecctx = smack_inode_setsecctx, | ||
3212 | .inode_getsecctx = smack_inode_getsecctx, | ||
3158 | }; | 3213 | }; |
3159 | 3214 | ||
3160 | 3215 | ||
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index fdd1f4b8c448..3c8bd8ee0b95 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -1285,6 +1285,36 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, | |||
1285 | } | 1285 | } |
1286 | 1286 | ||
1287 | /** | 1287 | /** |
1288 | * tomoyo_delete_domain - Delete a domain. | ||
1289 | * | ||
1290 | * @domainname: The name of domain. | ||
1291 | * | ||
1292 | * Returns 0. | ||
1293 | */ | ||
1294 | static int tomoyo_delete_domain(char *domainname) | ||
1295 | { | ||
1296 | struct tomoyo_domain_info *domain; | ||
1297 | struct tomoyo_path_info name; | ||
1298 | |||
1299 | name.name = domainname; | ||
1300 | tomoyo_fill_path_info(&name); | ||
1301 | down_write(&tomoyo_domain_list_lock); | ||
1302 | /* Is there an active domain? */ | ||
1303 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | ||
1304 | /* Never delete tomoyo_kernel_domain */ | ||
1305 | if (domain == &tomoyo_kernel_domain) | ||
1306 | continue; | ||
1307 | if (domain->is_deleted || | ||
1308 | tomoyo_pathcmp(domain->domainname, &name)) | ||
1309 | continue; | ||
1310 | domain->is_deleted = true; | ||
1311 | break; | ||
1312 | } | ||
1313 | up_write(&tomoyo_domain_list_lock); | ||
1314 | return 0; | ||
1315 | } | ||
1316 | |||
1317 | /** | ||
1288 | * tomoyo_write_domain_policy - Write domain policy. | 1318 | * tomoyo_write_domain_policy - Write domain policy. |
1289 | * | 1319 | * |
1290 | * @head: Pointer to "struct tomoyo_io_buffer". | 1320 | * @head: Pointer to "struct tomoyo_io_buffer". |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 6d6ba09af457..31df541911f7 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -339,8 +339,6 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); | |||
339 | const char *tomoyo_get_msg(const bool is_enforce); | 339 | const char *tomoyo_get_msg(const bool is_enforce); |
340 | /* Convert single path operation to operation name. */ | 340 | /* Convert single path operation to operation name. */ |
341 | const char *tomoyo_sp2keyword(const u8 operation); | 341 | const char *tomoyo_sp2keyword(const u8 operation); |
342 | /* Delete a domain. */ | ||
343 | int tomoyo_delete_domain(char *data); | ||
344 | /* Create "alias" entry in exception policy. */ | 342 | /* Create "alias" entry in exception policy. */ |
345 | int tomoyo_write_alias_policy(char *data, const bool is_delete); | 343 | int tomoyo_write_alias_policy(char *data, const bool is_delete); |
346 | /* | 344 | /* |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 1d8b16960576..fcf52accce2b 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -717,38 +717,6 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete) | |||
717 | return tomoyo_update_alias_entry(data, cp, is_delete); | 717 | return tomoyo_update_alias_entry(data, cp, is_delete); |
718 | } | 718 | } |
719 | 719 | ||
720 | /* Domain create/delete handler. */ | ||
721 | |||
722 | /** | ||
723 | * tomoyo_delete_domain - Delete a domain. | ||
724 | * | ||
725 | * @domainname: The name of domain. | ||
726 | * | ||
727 | * Returns 0. | ||
728 | */ | ||
729 | int tomoyo_delete_domain(char *domainname) | ||
730 | { | ||
731 | struct tomoyo_domain_info *domain; | ||
732 | struct tomoyo_path_info name; | ||
733 | |||
734 | name.name = domainname; | ||
735 | tomoyo_fill_path_info(&name); | ||
736 | down_write(&tomoyo_domain_list_lock); | ||
737 | /* Is there an active domain? */ | ||
738 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | ||
739 | /* Never delete tomoyo_kernel_domain */ | ||
740 | if (domain == &tomoyo_kernel_domain) | ||
741 | continue; | ||
742 | if (domain->is_deleted || | ||
743 | tomoyo_pathcmp(domain->domainname, &name)) | ||
744 | continue; | ||
745 | domain->is_deleted = true; | ||
746 | break; | ||
747 | } | ||
748 | up_write(&tomoyo_domain_list_lock); | ||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | /** | 720 | /** |
753 | * tomoyo_find_or_assign_new_domain - Create a domain. | 721 | * tomoyo_find_or_assign_new_domain - Create a domain. |
754 | * | 722 | * |
@@ -818,13 +786,11 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
818 | /** | 786 | /** |
819 | * tomoyo_find_next_domain - Find a domain. | 787 | * tomoyo_find_next_domain - Find a domain. |
820 | * | 788 | * |
821 | * @bprm: Pointer to "struct linux_binprm". | 789 | * @bprm: Pointer to "struct linux_binprm". |
822 | * @next_domain: Pointer to pointer to "struct tomoyo_domain_info". | ||
823 | * | 790 | * |
824 | * Returns 0 on success, negative value otherwise. | 791 | * Returns 0 on success, negative value otherwise. |
825 | */ | 792 | */ |
826 | int tomoyo_find_next_domain(struct linux_binprm *bprm, | 793 | int tomoyo_find_next_domain(struct linux_binprm *bprm) |
827 | struct tomoyo_domain_info **next_domain) | ||
828 | { | 794 | { |
829 | /* | 795 | /* |
830 | * This function assumes that the size of buffer returned by | 796 | * This function assumes that the size of buffer returned by |
@@ -946,9 +912,11 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm, | |||
946 | tomoyo_set_domain_flag(old_domain, false, | 912 | tomoyo_set_domain_flag(old_domain, false, |
947 | TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED); | 913 | TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED); |
948 | out: | 914 | out: |
915 | if (!domain) | ||
916 | domain = old_domain; | ||
917 | bprm->cred->security = domain; | ||
949 | tomoyo_free(real_program_name); | 918 | tomoyo_free(real_program_name); |
950 | tomoyo_free(symlink_program_name); | 919 | tomoyo_free(symlink_program_name); |
951 | *next_domain = domain ? domain : old_domain; | ||
952 | tomoyo_free(tmp); | 920 | tomoyo_free(tmp); |
953 | return retval; | 921 | return retval; |
954 | } | 922 | } |
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 3194d09fe0f4..9548a0984cc4 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
@@ -14,6 +14,12 @@ | |||
14 | #include "tomoyo.h" | 14 | #include "tomoyo.h" |
15 | #include "realpath.h" | 15 | #include "realpath.h" |
16 | 16 | ||
17 | static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) | ||
18 | { | ||
19 | new->security = NULL; | ||
20 | return 0; | ||
21 | } | ||
22 | |||
17 | static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, | 23 | static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, |
18 | gfp_t gfp) | 24 | gfp_t gfp) |
19 | { | 25 | { |
@@ -25,6 +31,15 @@ static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, | |||
25 | return 0; | 31 | return 0; |
26 | } | 32 | } |
27 | 33 | ||
34 | static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) | ||
35 | { | ||
36 | /* | ||
37 | * Since "struct tomoyo_domain_info *" is a sharable pointer, | ||
38 | * we don't need to duplicate. | ||
39 | */ | ||
40 | new->security = old->security; | ||
41 | } | ||
42 | |||
28 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | 43 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) |
29 | { | 44 | { |
30 | int rc; | 45 | int rc; |
@@ -61,14 +76,8 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | |||
61 | * Execute permission is checked against pathname passed to do_execve() | 76 | * Execute permission is checked against pathname passed to do_execve() |
62 | * using current domain. | 77 | * using current domain. |
63 | */ | 78 | */ |
64 | if (!domain) { | 79 | if (!domain) |
65 | struct tomoyo_domain_info *next_domain = NULL; | 80 | return tomoyo_find_next_domain(bprm); |
66 | int retval = tomoyo_find_next_domain(bprm, &next_domain); | ||
67 | |||
68 | if (!retval) | ||
69 | bprm->cred->security = next_domain; | ||
70 | return retval; | ||
71 | } | ||
72 | /* | 81 | /* |
73 | * Read permission is checked against interpreters using next domain. | 82 | * Read permission is checked against interpreters using next domain. |
74 | * '1' is the result of open_to_namei_flags(O_RDONLY). | 83 | * '1' is the result of open_to_namei_flags(O_RDONLY). |
@@ -268,7 +277,9 @@ static int tomoyo_dentry_open(struct file *f, const struct cred *cred) | |||
268 | */ | 277 | */ |
269 | static struct security_operations tomoyo_security_ops = { | 278 | static struct security_operations tomoyo_security_ops = { |
270 | .name = "tomoyo", | 279 | .name = "tomoyo", |
280 | .cred_alloc_blank = tomoyo_cred_alloc_blank, | ||
271 | .cred_prepare = tomoyo_cred_prepare, | 281 | .cred_prepare = tomoyo_cred_prepare, |
282 | .cred_transfer = tomoyo_cred_transfer, | ||
272 | .bprm_set_creds = tomoyo_bprm_set_creds, | 283 | .bprm_set_creds = tomoyo_bprm_set_creds, |
273 | .bprm_check_security = tomoyo_bprm_check_security, | 284 | .bprm_check_security = tomoyo_bprm_check_security, |
274 | #ifdef CONFIG_SYSCTL | 285 | #ifdef CONFIG_SYSCTL |
diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h index 0fd588a629cf..cd6ba0bf7069 100644 --- a/security/tomoyo/tomoyo.h +++ b/security/tomoyo/tomoyo.h | |||
@@ -31,8 +31,7 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain, | |||
31 | struct path *path2); | 31 | struct path *path2); |
32 | int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, | 32 | int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, |
33 | struct file *filp); | 33 | struct file *filp); |
34 | int tomoyo_find_next_domain(struct linux_binprm *bprm, | 34 | int tomoyo_find_next_domain(struct linux_binprm *bprm); |
35 | struct tomoyo_domain_info **next_domain); | ||
36 | 35 | ||
37 | /* Index numbers for Access Controls. */ | 36 | /* Index numbers for Access Controls. */ |
38 | 37 | ||