summaryrefslogtreecommitdiffstats
path: root/security/selinux/avc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-09-08 15:41:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-08 15:41:25 -0400
commitb793c005ceabf6db0b17494b0ec67ade6796bb34 (patch)
tree080c884f04254403ec9564742f591a9fd9b7e95a /security/selinux/avc.c
parent6f0a2fc1feb19bd142961a39dc118e7e55418b3f (diff)
parent07f081fb5057b2ea98baeca3a47bf0eb33e94aa1 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "Highlights: - PKCS#7 support added to support signed kexec, also utilized for module signing. See comments in 3f1e1bea. ** NOTE: this requires linking against the OpenSSL library, which must be installed, e.g. the openssl-devel on Fedora ** - Smack - add IPv6 host labeling; ignore labels on kernel threads - support smack labeling mounts which use binary mount data - SELinux: - add ioctl whitelisting (see http://kernsec.org/files/lss2015/vanderstoep.pdf) - fix mprotect PROT_EXEC regression caused by mm change - Seccomp: - add ptrace options for suspend/resume" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (57 commits) PKCS#7: Add OIDs for sha224, sha284 and sha512 hash algos and use them Documentation/Changes: Now need OpenSSL devel packages for module signing scripts: add extract-cert and sign-file to .gitignore modsign: Handle signing key in source tree modsign: Use if_changed rule for extracting cert from module signing key Move certificate handling to its own directory sign-file: Fix warning about BIO_reset() return value PKCS#7: Add MODULE_LICENSE() to test module Smack - Fix build error with bringup unconfigured sign-file: Document dependency on OpenSSL devel libraries PKCS#7: Appropriately restrict authenticated attributes and content type KEYS: Add a name for PKEY_ID_PKCS7 PKCS#7: Improve and export the X.509 ASN.1 time object decoder modsign: Use extract-cert to process CONFIG_SYSTEM_TRUSTED_KEYS extract-cert: Cope with multiple X.509 certificates in a single file sign-file: Generate CMS message as signature instead of PKCS#7 PKCS#7: Support CMS messages also [RFC5652] X.509: Change recorded SKID & AKID to not include Subject or Issuer PKCS#7: Check content type and versions MAINTAINERS: The keyrings mailing list has moved ...
Diffstat (limited to 'security/selinux/avc.c')
-rw-r--r--security/selinux/avc.c418
1 files changed, 402 insertions, 16 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 0b122b1421a9..e60c79de13e1 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -22,6 +22,7 @@
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/skbuff.h> 23#include <linux/skbuff.h>
24#include <linux/percpu.h> 24#include <linux/percpu.h>
25#include <linux/list.h>
25#include <net/sock.h> 26#include <net/sock.h>
26#include <linux/un.h> 27#include <linux/un.h>
27#include <net/af_unix.h> 28#include <net/af_unix.h>
@@ -48,6 +49,7 @@ struct avc_entry {
48 u32 tsid; 49 u32 tsid;
49 u16 tclass; 50 u16 tclass;
50 struct av_decision avd; 51 struct av_decision avd;
52 struct avc_xperms_node *xp_node;
51}; 53};
52 54
53struct avc_node { 55struct avc_node {
@@ -56,6 +58,16 @@ struct avc_node {
56 struct rcu_head rhead; 58 struct rcu_head rhead;
57}; 59};
58 60
61struct avc_xperms_decision_node {
62 struct extended_perms_decision xpd;
63 struct list_head xpd_list; /* list of extended_perms_decision */
64};
65
66struct avc_xperms_node {
67 struct extended_perms xp;
68 struct list_head xpd_head; /* list head of extended_perms_decision */
69};
70
59struct avc_cache { 71struct avc_cache {
60 struct hlist_head slots[AVC_CACHE_SLOTS]; /* head for avc_node->list */ 72 struct hlist_head slots[AVC_CACHE_SLOTS]; /* head for avc_node->list */
61 spinlock_t slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */ 73 spinlock_t slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */
@@ -80,6 +92,9 @@ DEFINE_PER_CPU(struct avc_cache_stats, avc_cache_stats) = { 0 };
80static struct avc_cache avc_cache; 92static struct avc_cache avc_cache;
81static struct avc_callback_node *avc_callbacks; 93static struct avc_callback_node *avc_callbacks;
82static struct kmem_cache *avc_node_cachep; 94static struct kmem_cache *avc_node_cachep;
95static struct kmem_cache *avc_xperms_data_cachep;
96static struct kmem_cache *avc_xperms_decision_cachep;
97static struct kmem_cache *avc_xperms_cachep;
83 98
84static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) 99static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
85{ 100{
@@ -101,6 +116,7 @@ static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
101 return; 116 return;
102 } 117 }
103 118
119 BUG_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map));
104 perms = secclass_map[tclass-1].perms; 120 perms = secclass_map[tclass-1].perms;
105 121
106 audit_log_format(ab, " {"); 122 audit_log_format(ab, " {");
@@ -149,7 +165,7 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla
149 kfree(scontext); 165 kfree(scontext);
150 } 166 }
151 167
152 BUG_ON(tclass >= ARRAY_SIZE(secclass_map)); 168 BUG_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map));
153 audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name); 169 audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name);
154} 170}
155 171
@@ -170,7 +186,17 @@ void __init avc_init(void)
170 atomic_set(&avc_cache.lru_hint, 0); 186 atomic_set(&avc_cache.lru_hint, 0);
171 187
172 avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node), 188 avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
173 0, SLAB_PANIC, NULL); 189 0, SLAB_PANIC, NULL);
190 avc_xperms_cachep = kmem_cache_create("avc_xperms_node",
191 sizeof(struct avc_xperms_node),
192 0, SLAB_PANIC, NULL);
193 avc_xperms_decision_cachep = kmem_cache_create(
194 "avc_xperms_decision_node",
195 sizeof(struct avc_xperms_decision_node),
196 0, SLAB_PANIC, NULL);
197 avc_xperms_data_cachep = kmem_cache_create("avc_xperms_data",
198 sizeof(struct extended_perms_data),
199 0, SLAB_PANIC, NULL);
174 200
175 audit_log(current->audit_context, GFP_KERNEL, AUDIT_KERNEL, "AVC INITIALIZED\n"); 201 audit_log(current->audit_context, GFP_KERNEL, AUDIT_KERNEL, "AVC INITIALIZED\n");
176} 202}
@@ -205,9 +231,261 @@ int avc_get_hash_stats(char *page)
205 slots_used, AVC_CACHE_SLOTS, max_chain_len); 231 slots_used, AVC_CACHE_SLOTS, max_chain_len);
206} 232}
207 233
234/*
235 * using a linked list for extended_perms_decision lookup because the list is
236 * always small. i.e. less than 5, typically 1
237 */
238static struct extended_perms_decision *avc_xperms_decision_lookup(u8 driver,
239 struct avc_xperms_node *xp_node)
240{
241 struct avc_xperms_decision_node *xpd_node;
242
243 list_for_each_entry(xpd_node, &xp_node->xpd_head, xpd_list) {
244 if (xpd_node->xpd.driver == driver)
245 return &xpd_node->xpd;
246 }
247 return NULL;
248}
249
250static inline unsigned int
251avc_xperms_has_perm(struct extended_perms_decision *xpd,
252 u8 perm, u8 which)
253{
254 unsigned int rc = 0;
255
256 if ((which == XPERMS_ALLOWED) &&
257 (xpd->used & XPERMS_ALLOWED))
258 rc = security_xperm_test(xpd->allowed->p, perm);
259 else if ((which == XPERMS_AUDITALLOW) &&
260 (xpd->used & XPERMS_AUDITALLOW))
261 rc = security_xperm_test(xpd->auditallow->p, perm);
262 else if ((which == XPERMS_DONTAUDIT) &&
263 (xpd->used & XPERMS_DONTAUDIT))
264 rc = security_xperm_test(xpd->dontaudit->p, perm);
265 return rc;
266}
267
268static void avc_xperms_allow_perm(struct avc_xperms_node *xp_node,
269 u8 driver, u8 perm)
270{
271 struct extended_perms_decision *xpd;
272 security_xperm_set(xp_node->xp.drivers.p, driver);
273 xpd = avc_xperms_decision_lookup(driver, xp_node);
274 if (xpd && xpd->allowed)
275 security_xperm_set(xpd->allowed->p, perm);
276}
277
278static void avc_xperms_decision_free(struct avc_xperms_decision_node *xpd_node)
279{
280 struct extended_perms_decision *xpd;
281
282 xpd = &xpd_node->xpd;
283 if (xpd->allowed)
284 kmem_cache_free(avc_xperms_data_cachep, xpd->allowed);
285 if (xpd->auditallow)
286 kmem_cache_free(avc_xperms_data_cachep, xpd->auditallow);
287 if (xpd->dontaudit)
288 kmem_cache_free(avc_xperms_data_cachep, xpd->dontaudit);
289 kmem_cache_free(avc_xperms_decision_cachep, xpd_node);
290}
291
292static void avc_xperms_free(struct avc_xperms_node *xp_node)
293{
294 struct avc_xperms_decision_node *xpd_node, *tmp;
295
296 if (!xp_node)
297 return;
298
299 list_for_each_entry_safe(xpd_node, tmp, &xp_node->xpd_head, xpd_list) {
300 list_del(&xpd_node->xpd_list);
301 avc_xperms_decision_free(xpd_node);
302 }
303 kmem_cache_free(avc_xperms_cachep, xp_node);
304}
305
306static void avc_copy_xperms_decision(struct extended_perms_decision *dest,
307 struct extended_perms_decision *src)
308{
309 dest->driver = src->driver;
310 dest->used = src->used;
311 if (dest->used & XPERMS_ALLOWED)
312 memcpy(dest->allowed->p, src->allowed->p,
313 sizeof(src->allowed->p));
314 if (dest->used & XPERMS_AUDITALLOW)
315 memcpy(dest->auditallow->p, src->auditallow->p,
316 sizeof(src->auditallow->p));
317 if (dest->used & XPERMS_DONTAUDIT)
318 memcpy(dest->dontaudit->p, src->dontaudit->p,
319 sizeof(src->dontaudit->p));
320}
321
322/*
323 * similar to avc_copy_xperms_decision, but only copy decision
324 * information relevant to this perm
325 */
326static inline void avc_quick_copy_xperms_decision(u8 perm,
327 struct extended_perms_decision *dest,
328 struct extended_perms_decision *src)
329{
330 /*
331 * compute index of the u32 of the 256 bits (8 u32s) that contain this
332 * command permission
333 */
334 u8 i = perm >> 5;
335
336 dest->used = src->used;
337 if (dest->used & XPERMS_ALLOWED)
338 dest->allowed->p[i] = src->allowed->p[i];
339 if (dest->used & XPERMS_AUDITALLOW)
340 dest->auditallow->p[i] = src->auditallow->p[i];
341 if (dest->used & XPERMS_DONTAUDIT)
342 dest->dontaudit->p[i] = src->dontaudit->p[i];
343}
344
345static struct avc_xperms_decision_node
346 *avc_xperms_decision_alloc(u8 which)
347{
348 struct avc_xperms_decision_node *xpd_node;
349 struct extended_perms_decision *xpd;
350
351 xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep,
352 GFP_ATOMIC | __GFP_NOMEMALLOC);
353 if (!xpd_node)
354 return NULL;
355
356 xpd = &xpd_node->xpd;
357 if (which & XPERMS_ALLOWED) {
358 xpd->allowed = kmem_cache_zalloc(avc_xperms_data_cachep,
359 GFP_ATOMIC | __GFP_NOMEMALLOC);
360 if (!xpd->allowed)
361 goto error;
362 }
363 if (which & XPERMS_AUDITALLOW) {
364 xpd->auditallow = kmem_cache_zalloc(avc_xperms_data_cachep,
365 GFP_ATOMIC | __GFP_NOMEMALLOC);
366 if (!xpd->auditallow)
367 goto error;
368 }
369 if (which & XPERMS_DONTAUDIT) {
370 xpd->dontaudit = kmem_cache_zalloc(avc_xperms_data_cachep,
371 GFP_ATOMIC | __GFP_NOMEMALLOC);
372 if (!xpd->dontaudit)
373 goto error;
374 }
375 return xpd_node;
376error:
377 avc_xperms_decision_free(xpd_node);
378 return NULL;
379}
380
381static int avc_add_xperms_decision(struct avc_node *node,
382 struct extended_perms_decision *src)
383{
384 struct avc_xperms_decision_node *dest_xpd;
385
386 node->ae.xp_node->xp.len++;
387 dest_xpd = avc_xperms_decision_alloc(src->used);
388 if (!dest_xpd)
389 return -ENOMEM;
390 avc_copy_xperms_decision(&dest_xpd->xpd, src);
391 list_add(&dest_xpd->xpd_list, &node->ae.xp_node->xpd_head);
392 return 0;
393}
394
395static struct avc_xperms_node *avc_xperms_alloc(void)
396{
397 struct avc_xperms_node *xp_node;
398
399 xp_node = kmem_cache_zalloc(avc_xperms_cachep,
400 GFP_ATOMIC|__GFP_NOMEMALLOC);
401 if (!xp_node)
402 return xp_node;
403 INIT_LIST_HEAD(&xp_node->xpd_head);
404 return xp_node;
405}
406
407static int avc_xperms_populate(struct avc_node *node,
408 struct avc_xperms_node *src)
409{
410 struct avc_xperms_node *dest;
411 struct avc_xperms_decision_node *dest_xpd;
412 struct avc_xperms_decision_node *src_xpd;
413
414 if (src->xp.len == 0)
415 return 0;
416 dest = avc_xperms_alloc();
417 if (!dest)
418 return -ENOMEM;
419
420 memcpy(dest->xp.drivers.p, src->xp.drivers.p, sizeof(dest->xp.drivers.p));
421 dest->xp.len = src->xp.len;
422
423 /* for each source xpd allocate a destination xpd and copy */
424 list_for_each_entry(src_xpd, &src->xpd_head, xpd_list) {
425 dest_xpd = avc_xperms_decision_alloc(src_xpd->xpd.used);
426 if (!dest_xpd)
427 goto error;
428 avc_copy_xperms_decision(&dest_xpd->xpd, &src_xpd->xpd);
429 list_add(&dest_xpd->xpd_list, &dest->xpd_head);
430 }
431 node->ae.xp_node = dest;
432 return 0;
433error:
434 avc_xperms_free(dest);
435 return -ENOMEM;
436
437}
438
439static inline u32 avc_xperms_audit_required(u32 requested,
440 struct av_decision *avd,
441 struct extended_perms_decision *xpd,
442 u8 perm,
443 int result,
444 u32 *deniedp)
445{
446 u32 denied, audited;
447
448 denied = requested & ~avd->allowed;
449 if (unlikely(denied)) {
450 audited = denied & avd->auditdeny;
451 if (audited && xpd) {
452 if (avc_xperms_has_perm(xpd, perm, XPERMS_DONTAUDIT))
453 audited &= ~requested;
454 }
455 } else if (result) {
456 audited = denied = requested;
457 } else {
458 audited = requested & avd->auditallow;
459 if (audited && xpd) {
460 if (!avc_xperms_has_perm(xpd, perm, XPERMS_AUDITALLOW))
461 audited &= ~requested;
462 }
463 }
464
465 *deniedp = denied;
466 return audited;
467}
468
469static inline int avc_xperms_audit(u32 ssid, u32 tsid, u16 tclass,
470 u32 requested, struct av_decision *avd,
471 struct extended_perms_decision *xpd,
472 u8 perm, int result,
473 struct common_audit_data *ad)
474{
475 u32 audited, denied;
476
477 audited = avc_xperms_audit_required(
478 requested, avd, xpd, perm, result, &denied);
479 if (likely(!audited))
480 return 0;
481 return slow_avc_audit(ssid, tsid, tclass, requested,
482 audited, denied, result, ad, 0);
483}
484
208static void avc_node_free(struct rcu_head *rhead) 485static void avc_node_free(struct rcu_head *rhead)
209{ 486{
210 struct avc_node *node = container_of(rhead, struct avc_node, rhead); 487 struct avc_node *node = container_of(rhead, struct avc_node, rhead);
488 avc_xperms_free(node->ae.xp_node);
211 kmem_cache_free(avc_node_cachep, node); 489 kmem_cache_free(avc_node_cachep, node);
212 avc_cache_stats_incr(frees); 490 avc_cache_stats_incr(frees);
213} 491}
@@ -221,6 +499,7 @@ static void avc_node_delete(struct avc_node *node)
221 499
222static void avc_node_kill(struct avc_node *node) 500static void avc_node_kill(struct avc_node *node)
223{ 501{
502 avc_xperms_free(node->ae.xp_node);
224 kmem_cache_free(avc_node_cachep, node); 503 kmem_cache_free(avc_node_cachep, node);
225 avc_cache_stats_incr(frees); 504 avc_cache_stats_incr(frees);
226 atomic_dec(&avc_cache.active_nodes); 505 atomic_dec(&avc_cache.active_nodes);
@@ -367,6 +646,7 @@ static int avc_latest_notif_update(int seqno, int is_insert)
367 * @tsid: target security identifier 646 * @tsid: target security identifier
368 * @tclass: target security class 647 * @tclass: target security class
369 * @avd: resulting av decision 648 * @avd: resulting av decision
649 * @xp_node: resulting extended permissions
370 * 650 *
371 * Insert an AVC entry for the SID pair 651 * Insert an AVC entry for the SID pair
372 * (@ssid, @tsid) and class @tclass. 652 * (@ssid, @tsid) and class @tclass.
@@ -378,7 +658,9 @@ static int avc_latest_notif_update(int seqno, int is_insert)
378 * the access vectors into a cache entry, returns 658 * the access vectors into a cache entry, returns
379 * avc_node inserted. Otherwise, this function returns NULL. 659 * avc_node inserted. Otherwise, this function returns NULL.
380 */ 660 */
381static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd) 661static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass,
662 struct av_decision *avd,
663 struct avc_xperms_node *xp_node)
382{ 664{
383 struct avc_node *pos, *node = NULL; 665 struct avc_node *pos, *node = NULL;
384 int hvalue; 666 int hvalue;
@@ -391,10 +673,15 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_dec
391 if (node) { 673 if (node) {
392 struct hlist_head *head; 674 struct hlist_head *head;
393 spinlock_t *lock; 675 spinlock_t *lock;
676 int rc = 0;
394 677
395 hvalue = avc_hash(ssid, tsid, tclass); 678 hvalue = avc_hash(ssid, tsid, tclass);
396 avc_node_populate(node, ssid, tsid, tclass, avd); 679 avc_node_populate(node, ssid, tsid, tclass, avd);
397 680 rc = avc_xperms_populate(node, xp_node);
681 if (rc) {
682 kmem_cache_free(avc_node_cachep, node);
683 return NULL;
684 }
398 head = &avc_cache.slots[hvalue]; 685 head = &avc_cache.slots[hvalue];
399 lock = &avc_cache.slots_lock[hvalue]; 686 lock = &avc_cache.slots_lock[hvalue];
400 687
@@ -523,14 +810,17 @@ out:
523 * @perms : Permission mask bits 810 * @perms : Permission mask bits
524 * @ssid,@tsid,@tclass : identifier of an AVC entry 811 * @ssid,@tsid,@tclass : identifier of an AVC entry
525 * @seqno : sequence number when decision was made 812 * @seqno : sequence number when decision was made
813 * @xpd: extended_perms_decision to be added to the node
526 * 814 *
527 * if a valid AVC entry doesn't exist,this function returns -ENOENT. 815 * if a valid AVC entry doesn't exist,this function returns -ENOENT.
528 * if kmalloc() called internal returns NULL, this function returns -ENOMEM. 816 * if kmalloc() called internal returns NULL, this function returns -ENOMEM.
529 * otherwise, this function updates the AVC entry. The original AVC-entry object 817 * otherwise, this function updates the AVC entry. The original AVC-entry object
530 * will release later by RCU. 818 * will release later by RCU.
531 */ 819 */
532static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass, 820static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid,
533 u32 seqno) 821 u32 tsid, u16 tclass, u32 seqno,
822 struct extended_perms_decision *xpd,
823 u32 flags)
534{ 824{
535 int hvalue, rc = 0; 825 int hvalue, rc = 0;
536 unsigned long flag; 826 unsigned long flag;
@@ -574,9 +864,19 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass,
574 864
575 avc_node_populate(node, ssid, tsid, tclass, &orig->ae.avd); 865 avc_node_populate(node, ssid, tsid, tclass, &orig->ae.avd);
576 866
867 if (orig->ae.xp_node) {
868 rc = avc_xperms_populate(node, orig->ae.xp_node);
869 if (rc) {
870 kmem_cache_free(avc_node_cachep, node);
871 goto out_unlock;
872 }
873 }
874
577 switch (event) { 875 switch (event) {
578 case AVC_CALLBACK_GRANT: 876 case AVC_CALLBACK_GRANT:
579 node->ae.avd.allowed |= perms; 877 node->ae.avd.allowed |= perms;
878 if (node->ae.xp_node && (flags & AVC_EXTENDED_PERMS))
879 avc_xperms_allow_perm(node->ae.xp_node, driver, xperm);
580 break; 880 break;
581 case AVC_CALLBACK_TRY_REVOKE: 881 case AVC_CALLBACK_TRY_REVOKE:
582 case AVC_CALLBACK_REVOKE: 882 case AVC_CALLBACK_REVOKE:
@@ -594,6 +894,9 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass,
594 case AVC_CALLBACK_AUDITDENY_DISABLE: 894 case AVC_CALLBACK_AUDITDENY_DISABLE:
595 node->ae.avd.auditdeny &= ~perms; 895 node->ae.avd.auditdeny &= ~perms;
596 break; 896 break;
897 case AVC_CALLBACK_ADD_XPERMS:
898 avc_add_xperms_decision(node, xpd);
899 break;
597 } 900 }
598 avc_node_replace(node, orig); 901 avc_node_replace(node, orig);
599out_unlock: 902out_unlock:
@@ -665,18 +968,20 @@ int avc_ss_reset(u32 seqno)
665 * results in a bigger stack frame. 968 * results in a bigger stack frame.
666 */ 969 */
667static noinline struct avc_node *avc_compute_av(u32 ssid, u32 tsid, 970static noinline struct avc_node *avc_compute_av(u32 ssid, u32 tsid,
668 u16 tclass, struct av_decision *avd) 971 u16 tclass, struct av_decision *avd,
972 struct avc_xperms_node *xp_node)
669{ 973{
670 rcu_read_unlock(); 974 rcu_read_unlock();
671 security_compute_av(ssid, tsid, tclass, avd); 975 INIT_LIST_HEAD(&xp_node->xpd_head);
976 security_compute_av(ssid, tsid, tclass, avd, &xp_node->xp);
672 rcu_read_lock(); 977 rcu_read_lock();
673 return avc_insert(ssid, tsid, tclass, avd); 978 return avc_insert(ssid, tsid, tclass, avd, xp_node);
674} 979}
675 980
676static noinline int avc_denied(u32 ssid, u32 tsid, 981static noinline int avc_denied(u32 ssid, u32 tsid,
677 u16 tclass, u32 requested, 982 u16 tclass, u32 requested,
678 unsigned flags, 983 u8 driver, u8 xperm, unsigned flags,
679 struct av_decision *avd) 984 struct av_decision *avd)
680{ 985{
681 if (flags & AVC_STRICT) 986 if (flags & AVC_STRICT)
682 return -EACCES; 987 return -EACCES;
@@ -684,11 +989,91 @@ static noinline int avc_denied(u32 ssid, u32 tsid,
684 if (selinux_enforcing && !(avd->flags & AVD_FLAGS_PERMISSIVE)) 989 if (selinux_enforcing && !(avd->flags & AVD_FLAGS_PERMISSIVE))
685 return -EACCES; 990 return -EACCES;
686 991
687 avc_update_node(AVC_CALLBACK_GRANT, requested, ssid, 992 avc_update_node(AVC_CALLBACK_GRANT, requested, driver, xperm, ssid,
688 tsid, tclass, avd->seqno); 993 tsid, tclass, avd->seqno, NULL, flags);
689 return 0; 994 return 0;
690} 995}
691 996
997/*
998 * The avc extended permissions logic adds an additional 256 bits of
999 * permissions to an avc node when extended permissions for that node are
1000 * specified in the avtab. If the additional 256 permissions is not adequate,
1001 * as-is the case with ioctls, then multiple may be chained together and the
1002 * driver field is used to specify which set contains the permission.
1003 */
1004int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested,
1005 u8 driver, u8 xperm, struct common_audit_data *ad)
1006{
1007 struct avc_node *node;
1008 struct av_decision avd;
1009 u32 denied;
1010 struct extended_perms_decision local_xpd;
1011 struct extended_perms_decision *xpd = NULL;
1012 struct extended_perms_data allowed;
1013 struct extended_perms_data auditallow;
1014 struct extended_perms_data dontaudit;
1015 struct avc_xperms_node local_xp_node;
1016 struct avc_xperms_node *xp_node;
1017 int rc = 0, rc2;
1018
1019 xp_node = &local_xp_node;
1020 BUG_ON(!requested);
1021
1022 rcu_read_lock();
1023
1024 node = avc_lookup(ssid, tsid, tclass);
1025 if (unlikely(!node)) {
1026 node = avc_compute_av(ssid, tsid, tclass, &avd, xp_node);
1027 } else {
1028 memcpy(&avd, &node->ae.avd, sizeof(avd));
1029 xp_node = node->ae.xp_node;
1030 }
1031 /* if extended permissions are not defined, only consider av_decision */
1032 if (!xp_node || !xp_node->xp.len)
1033 goto decision;
1034
1035 local_xpd.allowed = &allowed;
1036 local_xpd.auditallow = &auditallow;
1037 local_xpd.dontaudit = &dontaudit;
1038
1039 xpd = avc_xperms_decision_lookup(driver, xp_node);
1040 if (unlikely(!xpd)) {
1041 /*
1042 * Compute the extended_perms_decision only if the driver
1043 * is flagged
1044 */
1045 if (!security_xperm_test(xp_node->xp.drivers.p, driver)) {
1046 avd.allowed &= ~requested;
1047 goto decision;
1048 }
1049 rcu_read_unlock();
1050 security_compute_xperms_decision(ssid, tsid, tclass, driver,
1051 &local_xpd);
1052 rcu_read_lock();
1053 avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested, driver, xperm,
1054 ssid, tsid, tclass, avd.seqno, &local_xpd, 0);
1055 } else {
1056 avc_quick_copy_xperms_decision(xperm, &local_xpd, xpd);
1057 }
1058 xpd = &local_xpd;
1059
1060 if (!avc_xperms_has_perm(xpd, xperm, XPERMS_ALLOWED))
1061 avd.allowed &= ~requested;
1062
1063decision:
1064 denied = requested & ~(avd.allowed);
1065 if (unlikely(denied))
1066 rc = avc_denied(ssid, tsid, tclass, requested, driver, xperm,
1067 AVC_EXTENDED_PERMS, &avd);
1068
1069 rcu_read_unlock();
1070
1071 rc2 = avc_xperms_audit(ssid, tsid, tclass, requested,
1072 &avd, xpd, xperm, rc, ad);
1073 if (rc2)
1074 return rc2;
1075 return rc;
1076}
692 1077
693/** 1078/**
694 * avc_has_perm_noaudit - Check permissions but perform no auditing. 1079 * avc_has_perm_noaudit - Check permissions but perform no auditing.
@@ -716,6 +1101,7 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
716 struct av_decision *avd) 1101 struct av_decision *avd)
717{ 1102{
718 struct avc_node *node; 1103 struct avc_node *node;
1104 struct avc_xperms_node xp_node;
719 int rc = 0; 1105 int rc = 0;
720 u32 denied; 1106 u32 denied;
721 1107
@@ -725,13 +1111,13 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
725 1111
726 node = avc_lookup(ssid, tsid, tclass); 1112 node = avc_lookup(ssid, tsid, tclass);
727 if (unlikely(!node)) 1113 if (unlikely(!node))
728 node = avc_compute_av(ssid, tsid, tclass, avd); 1114 node = avc_compute_av(ssid, tsid, tclass, avd, &xp_node);
729 else 1115 else
730 memcpy(avd, &node->ae.avd, sizeof(*avd)); 1116 memcpy(avd, &node->ae.avd, sizeof(*avd));
731 1117
732 denied = requested & ~(avd->allowed); 1118 denied = requested & ~(avd->allowed);
733 if (unlikely(denied)) 1119 if (unlikely(denied))
734 rc = avc_denied(ssid, tsid, tclass, requested, flags, avd); 1120 rc = avc_denied(ssid, tsid, tclass, requested, 0, 0, flags, avd);
735 1121
736 rcu_read_unlock(); 1122 rcu_read_unlock();
737 return rc; 1123 return rc;