diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 14:35:36 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 14:35:36 -0500 |
commit | 4ba24fef3eb3b142197135223b90ced2f319cd53 (patch) | |
tree | a20c125b27740ec7b4c761b11d801108e1b316b2 /security/smack/smack_access.c | |
parent | 47c1ffb2b6b630894e9a16442611c056ab21c057 (diff) | |
parent | 98a4a59ee31a12105a2b84f5b8b515ac2cb208ef (diff) |
Merge branch 'next' into for-linus
Prepare first round of input updates for 3.20.
Diffstat (limited to 'security/smack/smack_access.c')
-rw-r--r-- | security/smack/smack_access.c | 131 |
1 files changed, 57 insertions, 74 deletions
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index f97d0842e621..1158430f5bb9 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -94,7 +94,7 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
94 | struct smack_rule *srp; | 94 | struct smack_rule *srp; |
95 | 95 | ||
96 | list_for_each_entry_rcu(srp, rule_list, list) { | 96 | list_for_each_entry_rcu(srp, rule_list, list) { |
97 | if (srp->smk_object == object_label && | 97 | if (srp->smk_object->smk_known == object_label && |
98 | srp->smk_subject->smk_known == subject_label) { | 98 | srp->smk_subject->smk_known == subject_label) { |
99 | may = srp->smk_access; | 99 | may = srp->smk_access; |
100 | break; | 100 | break; |
@@ -111,8 +111,8 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
111 | 111 | ||
112 | /** | 112 | /** |
113 | * smk_access - determine if a subject has a specific access to an object | 113 | * smk_access - determine if a subject has a specific access to an object |
114 | * @subject_known: a pointer to the subject's Smack label entry | 114 | * @subject: a pointer to the subject's Smack label entry |
115 | * @object_label: a pointer to the object's Smack label | 115 | * @object: a pointer to the object's Smack label entry |
116 | * @request: the access requested, in "MAY" format | 116 | * @request: the access requested, in "MAY" format |
117 | * @a : a pointer to the audit data | 117 | * @a : a pointer to the audit data |
118 | * | 118 | * |
@@ -122,8 +122,8 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
122 | * | 122 | * |
123 | * Smack labels are shared on smack_list | 123 | * Smack labels are shared on smack_list |
124 | */ | 124 | */ |
125 | int smk_access(struct smack_known *subject_known, char *object_label, | 125 | int smk_access(struct smack_known *subject, struct smack_known *object, |
126 | int request, struct smk_audit_info *a) | 126 | int request, struct smk_audit_info *a) |
127 | { | 127 | { |
128 | int may = MAY_NOT; | 128 | int may = MAY_NOT; |
129 | int rc = 0; | 129 | int rc = 0; |
@@ -133,7 +133,7 @@ int smk_access(struct smack_known *subject_known, char *object_label, | |||
133 | * | 133 | * |
134 | * A star subject can't access any object. | 134 | * A star subject can't access any object. |
135 | */ | 135 | */ |
136 | if (subject_known == &smack_known_star) { | 136 | if (subject == &smack_known_star) { |
137 | rc = -EACCES; | 137 | rc = -EACCES; |
138 | goto out_audit; | 138 | goto out_audit; |
139 | } | 139 | } |
@@ -142,28 +142,28 @@ int smk_access(struct smack_known *subject_known, char *object_label, | |||
142 | * Tasks cannot be assigned the internet label. | 142 | * Tasks cannot be assigned the internet label. |
143 | * An internet subject can access any object. | 143 | * An internet subject can access any object. |
144 | */ | 144 | */ |
145 | if (object_label == smack_known_web.smk_known || | 145 | if (object == &smack_known_web || subject == &smack_known_web) |
146 | subject_known == &smack_known_web) | ||
147 | goto out_audit; | 146 | goto out_audit; |
148 | /* | 147 | /* |
149 | * A star object can be accessed by any subject. | 148 | * A star object can be accessed by any subject. |
150 | */ | 149 | */ |
151 | if (object_label == smack_known_star.smk_known) | 150 | if (object == &smack_known_star) |
152 | goto out_audit; | 151 | goto out_audit; |
153 | /* | 152 | /* |
154 | * An object can be accessed in any way by a subject | 153 | * An object can be accessed in any way by a subject |
155 | * with the same label. | 154 | * with the same label. |
156 | */ | 155 | */ |
157 | if (subject_known->smk_known == object_label) | 156 | if (subject->smk_known == object->smk_known) |
158 | goto out_audit; | 157 | goto out_audit; |
159 | /* | 158 | /* |
160 | * A hat subject can read any object. | 159 | * A hat subject can read or lock any object. |
161 | * A floor object can be read by any subject. | 160 | * A floor object can be read or locked by any subject. |
162 | */ | 161 | */ |
163 | if ((request & MAY_ANYREAD) == request) { | 162 | if ((request & MAY_ANYREAD) == request || |
164 | if (object_label == smack_known_floor.smk_known) | 163 | (request & MAY_LOCK) == request) { |
164 | if (object == &smack_known_floor) | ||
165 | goto out_audit; | 165 | goto out_audit; |
166 | if (subject_known == &smack_known_hat) | 166 | if (subject == &smack_known_hat) |
167 | goto out_audit; | 167 | goto out_audit; |
168 | } | 168 | } |
169 | /* | 169 | /* |
@@ -174,27 +174,38 @@ int smk_access(struct smack_known *subject_known, char *object_label, | |||
174 | * indicates there is no entry for this pair. | 174 | * indicates there is no entry for this pair. |
175 | */ | 175 | */ |
176 | rcu_read_lock(); | 176 | rcu_read_lock(); |
177 | may = smk_access_entry(subject_known->smk_known, object_label, | 177 | may = smk_access_entry(subject->smk_known, object->smk_known, |
178 | &subject_known->smk_rules); | 178 | &subject->smk_rules); |
179 | rcu_read_unlock(); | 179 | rcu_read_unlock(); |
180 | 180 | ||
181 | if (may > 0 && (request & may) == request) | 181 | if (may <= 0 || (request & may) != request) { |
182 | rc = -EACCES; | ||
182 | goto out_audit; | 183 | goto out_audit; |
184 | } | ||
185 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
186 | /* | ||
187 | * Return a positive value if using bringup mode. | ||
188 | * This allows the hooks to identify checks that | ||
189 | * succeed because of "b" rules. | ||
190 | */ | ||
191 | if (may & MAY_BRINGUP) | ||
192 | rc = MAY_BRINGUP; | ||
193 | #endif | ||
183 | 194 | ||
184 | rc = -EACCES; | ||
185 | out_audit: | 195 | out_audit: |
186 | #ifdef CONFIG_AUDIT | 196 | #ifdef CONFIG_AUDIT |
187 | if (a) | 197 | if (a) |
188 | smack_log(subject_known->smk_known, object_label, request, | 198 | smack_log(subject->smk_known, object->smk_known, |
189 | rc, a); | 199 | request, rc, a); |
190 | #endif | 200 | #endif |
201 | |||
191 | return rc; | 202 | return rc; |
192 | } | 203 | } |
193 | 204 | ||
194 | /** | 205 | /** |
195 | * smk_tskacc - determine if a task has a specific access to an object | 206 | * smk_tskacc - determine if a task has a specific access to an object |
196 | * @tsp: a pointer to the subject task | 207 | * @tsp: a pointer to the subject's task |
197 | * @obj_label: a pointer to the object's Smack label | 208 | * @obj_known: a pointer to the object's label entry |
198 | * @mode: the access requested, in "MAY" format | 209 | * @mode: the access requested, in "MAY" format |
199 | * @a : common audit data | 210 | * @a : common audit data |
200 | * | 211 | * |
@@ -203,24 +214,25 @@ out_audit: | |||
203 | * non zero otherwise. It allows that the task may have the capability | 214 | * non zero otherwise. It allows that the task may have the capability |
204 | * to override the rules. | 215 | * to override the rules. |
205 | */ | 216 | */ |
206 | int smk_tskacc(struct task_smack *subject, char *obj_label, | 217 | int smk_tskacc(struct task_smack *tsp, struct smack_known *obj_known, |
207 | u32 mode, struct smk_audit_info *a) | 218 | u32 mode, struct smk_audit_info *a) |
208 | { | 219 | { |
209 | struct smack_known *skp = smk_of_task(subject); | 220 | struct smack_known *sbj_known = smk_of_task(tsp); |
210 | int may; | 221 | int may; |
211 | int rc; | 222 | int rc; |
212 | 223 | ||
213 | /* | 224 | /* |
214 | * Check the global rule list | 225 | * Check the global rule list |
215 | */ | 226 | */ |
216 | rc = smk_access(skp, obj_label, mode, NULL); | 227 | rc = smk_access(sbj_known, obj_known, mode, NULL); |
217 | if (rc == 0) { | 228 | if (rc >= 0) { |
218 | /* | 229 | /* |
219 | * If there is an entry in the task's rule list | 230 | * If there is an entry in the task's rule list |
220 | * it can further restrict access. | 231 | * it can further restrict access. |
221 | */ | 232 | */ |
222 | may = smk_access_entry(skp->smk_known, obj_label, | 233 | may = smk_access_entry(sbj_known->smk_known, |
223 | &subject->smk_rules); | 234 | obj_known->smk_known, |
235 | &tsp->smk_rules); | ||
224 | if (may < 0) | 236 | if (may < 0) |
225 | goto out_audit; | 237 | goto out_audit; |
226 | if ((mode & may) == mode) | 238 | if ((mode & may) == mode) |
@@ -237,14 +249,15 @@ int smk_tskacc(struct task_smack *subject, char *obj_label, | |||
237 | out_audit: | 249 | out_audit: |
238 | #ifdef CONFIG_AUDIT | 250 | #ifdef CONFIG_AUDIT |
239 | if (a) | 251 | if (a) |
240 | smack_log(skp->smk_known, obj_label, mode, rc, a); | 252 | smack_log(sbj_known->smk_known, obj_known->smk_known, |
253 | mode, rc, a); | ||
241 | #endif | 254 | #endif |
242 | return rc; | 255 | return rc; |
243 | } | 256 | } |
244 | 257 | ||
245 | /** | 258 | /** |
246 | * smk_curacc - determine if current has a specific access to an object | 259 | * smk_curacc - determine if current has a specific access to an object |
247 | * @obj_label: a pointer to the object's Smack label | 260 | * @obj_known: a pointer to the object's Smack label entry |
248 | * @mode: the access requested, in "MAY" format | 261 | * @mode: the access requested, in "MAY" format |
249 | * @a : common audit data | 262 | * @a : common audit data |
250 | * | 263 | * |
@@ -253,11 +266,12 @@ out_audit: | |||
253 | * non zero otherwise. It allows that current may have the capability | 266 | * non zero otherwise. It allows that current may have the capability |
254 | * to override the rules. | 267 | * to override the rules. |
255 | */ | 268 | */ |
256 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | 269 | int smk_curacc(struct smack_known *obj_known, |
270 | u32 mode, struct smk_audit_info *a) | ||
257 | { | 271 | { |
258 | struct task_smack *tsp = current_security(); | 272 | struct task_smack *tsp = current_security(); |
259 | 273 | ||
260 | return smk_tskacc(tsp, obj_label, mode, a); | 274 | return smk_tskacc(tsp, obj_known, mode, a); |
261 | } | 275 | } |
262 | 276 | ||
263 | #ifdef CONFIG_AUDIT | 277 | #ifdef CONFIG_AUDIT |
@@ -328,6 +342,13 @@ void smack_log(char *subject_label, char *object_label, int request, | |||
328 | struct smack_audit_data *sad; | 342 | struct smack_audit_data *sad; |
329 | struct common_audit_data *a = &ad->a; | 343 | struct common_audit_data *a = &ad->a; |
330 | 344 | ||
345 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
346 | /* | ||
347 | * The result may be positive in bringup mode. | ||
348 | */ | ||
349 | if (result > 0) | ||
350 | result = 0; | ||
351 | #endif | ||
331 | /* check if we have to log the current event */ | 352 | /* check if we have to log the current event */ |
332 | if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) | 353 | if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) |
333 | return; | 354 | return; |
@@ -431,10 +452,9 @@ char *smk_parse_smack(const char *string, int len) | |||
431 | return NULL; | 452 | return NULL; |
432 | 453 | ||
433 | smack = kzalloc(i + 1, GFP_KERNEL); | 454 | smack = kzalloc(i + 1, GFP_KERNEL); |
434 | if (smack != NULL) { | 455 | if (smack != NULL) |
435 | strncpy(smack, string, i + 1); | 456 | strncpy(smack, string, i); |
436 | smack[i] = '\0'; | 457 | |
437 | } | ||
438 | return smack; | 458 | return smack; |
439 | } | 459 | } |
440 | 460 | ||
@@ -544,27 +564,6 @@ unlockout: | |||
544 | } | 564 | } |
545 | 565 | ||
546 | /** | 566 | /** |
547 | * smk_import - import a smack label | ||
548 | * @string: a text string that might be a Smack label | ||
549 | * @len: the maximum size, or zero if it is NULL terminated. | ||
550 | * | ||
551 | * Returns a pointer to the label in the label list that | ||
552 | * matches the passed string, adding it if necessary. | ||
553 | */ | ||
554 | char *smk_import(const char *string, int len) | ||
555 | { | ||
556 | struct smack_known *skp; | ||
557 | |||
558 | /* labels cannot begin with a '-' */ | ||
559 | if (string[0] == '-') | ||
560 | return NULL; | ||
561 | skp = smk_import_entry(string, len); | ||
562 | if (skp == NULL) | ||
563 | return NULL; | ||
564 | return skp->smk_known; | ||
565 | } | ||
566 | |||
567 | /** | ||
568 | * smack_from_secid - find the Smack label associated with a secid | 567 | * smack_from_secid - find the Smack label associated with a secid |
569 | * @secid: an integer that might be associated with a Smack label | 568 | * @secid: an integer that might be associated with a Smack label |
570 | * | 569 | * |
@@ -590,19 +589,3 @@ struct smack_known *smack_from_secid(const u32 secid) | |||
590 | rcu_read_unlock(); | 589 | rcu_read_unlock(); |
591 | return &smack_known_invalid; | 590 | return &smack_known_invalid; |
592 | } | 591 | } |
593 | |||
594 | /** | ||
595 | * smack_to_secid - find the secid associated with a Smack label | ||
596 | * @smack: the Smack label | ||
597 | * | ||
598 | * Returns the appropriate secid if there is one, | ||
599 | * otherwise 0 | ||
600 | */ | ||
601 | u32 smack_to_secid(const char *smack) | ||
602 | { | ||
603 | struct smack_known *skp = smk_find_entry(smack); | ||
604 | |||
605 | if (skp == NULL) | ||
606 | return 0; | ||
607 | return skp->smk_secid; | ||
608 | } | ||