diff options
Diffstat (limited to 'security/selinux/avc.c')
-rw-r--r-- | security/selinux/avc.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 0afb990fdfa4..2a84dec4adfe 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -350,12 +350,12 @@ out: | |||
350 | return node; | 350 | return node; |
351 | } | 351 | } |
352 | 352 | ||
353 | static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae) | 353 | static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd) |
354 | { | 354 | { |
355 | node->ae.ssid = ssid; | 355 | node->ae.ssid = ssid; |
356 | node->ae.tsid = tsid; | 356 | node->ae.tsid = tsid; |
357 | node->ae.tclass = tclass; | 357 | node->ae.tclass = tclass; |
358 | memcpy(&node->ae.avd, &ae->avd, sizeof(node->ae.avd)); | 358 | memcpy(&node->ae.avd, avd, sizeof(node->ae.avd)); |
359 | } | 359 | } |
360 | 360 | ||
361 | static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) | 361 | static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) |
@@ -435,31 +435,31 @@ static int avc_latest_notif_update(int seqno, int is_insert) | |||
435 | * @ssid: source security identifier | 435 | * @ssid: source security identifier |
436 | * @tsid: target security identifier | 436 | * @tsid: target security identifier |
437 | * @tclass: target security class | 437 | * @tclass: target security class |
438 | * @ae: AVC entry | 438 | * @avd: resulting av decision |
439 | * | 439 | * |
440 | * Insert an AVC entry for the SID pair | 440 | * Insert an AVC entry for the SID pair |
441 | * (@ssid, @tsid) and class @tclass. | 441 | * (@ssid, @tsid) and class @tclass. |
442 | * The access vectors and the sequence number are | 442 | * The access vectors and the sequence number are |
443 | * normally provided by the security server in | 443 | * normally provided by the security server in |
444 | * response to a security_compute_av() call. If the | 444 | * response to a security_compute_av() call. If the |
445 | * sequence number @ae->avd.seqno is not less than the latest | 445 | * sequence number @avd->seqno is not less than the latest |
446 | * revocation notification, then the function copies | 446 | * revocation notification, then the function copies |
447 | * the access vectors into a cache entry, returns | 447 | * the access vectors into a cache entry, returns |
448 | * avc_node inserted. Otherwise, this function returns NULL. | 448 | * avc_node inserted. Otherwise, this function returns NULL. |
449 | */ | 449 | */ |
450 | static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae) | 450 | static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd) |
451 | { | 451 | { |
452 | struct avc_node *pos, *node = NULL; | 452 | struct avc_node *pos, *node = NULL; |
453 | int hvalue; | 453 | int hvalue; |
454 | unsigned long flag; | 454 | unsigned long flag; |
455 | 455 | ||
456 | if (avc_latest_notif_update(ae->avd.seqno, 1)) | 456 | if (avc_latest_notif_update(avd->seqno, 1)) |
457 | goto out; | 457 | goto out; |
458 | 458 | ||
459 | node = avc_alloc_node(); | 459 | node = avc_alloc_node(); |
460 | if (node) { | 460 | if (node) { |
461 | hvalue = avc_hash(ssid, tsid, tclass); | 461 | hvalue = avc_hash(ssid, tsid, tclass); |
462 | avc_node_populate(node, ssid, tsid, tclass, ae); | 462 | avc_node_populate(node, ssid, tsid, tclass, avd); |
463 | 463 | ||
464 | spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag); | 464 | spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag); |
465 | list_for_each_entry(pos, &avc_cache.slots[hvalue], list) { | 465 | list_for_each_entry(pos, &avc_cache.slots[hvalue], list) { |
@@ -772,7 +772,7 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass, | |||
772 | * Copy and replace original node. | 772 | * Copy and replace original node. |
773 | */ | 773 | */ |
774 | 774 | ||
775 | avc_node_populate(node, ssid, tsid, tclass, &orig->ae); | 775 | avc_node_populate(node, ssid, tsid, tclass, &orig->ae.avd); |
776 | 776 | ||
777 | switch (event) { | 777 | switch (event) { |
778 | case AVC_CALLBACK_GRANT: | 778 | case AVC_CALLBACK_GRANT: |
@@ -864,10 +864,10 @@ int avc_ss_reset(u32 seqno) | |||
864 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 864 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, |
865 | u16 tclass, u32 requested, | 865 | u16 tclass, u32 requested, |
866 | unsigned flags, | 866 | unsigned flags, |
867 | struct av_decision *avd) | 867 | struct av_decision *in_avd) |
868 | { | 868 | { |
869 | struct avc_node *node; | 869 | struct avc_node *node; |
870 | struct avc_entry entry, *p_ae; | 870 | struct av_decision avd_entry, *avd; |
871 | int rc = 0; | 871 | int rc = 0; |
872 | u32 denied; | 872 | u32 denied; |
873 | 873 | ||
@@ -878,26 +878,31 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
878 | node = avc_lookup(ssid, tsid, tclass, requested); | 878 | node = avc_lookup(ssid, tsid, tclass, requested); |
879 | if (!node) { | 879 | if (!node) { |
880 | rcu_read_unlock(); | 880 | rcu_read_unlock(); |
881 | rc = security_compute_av(ssid, tsid, tclass, requested, &entry.avd); | 881 | |
882 | if (in_avd) | ||
883 | avd = in_avd; | ||
884 | else | ||
885 | avd = &avd_entry; | ||
886 | |||
887 | rc = security_compute_av(ssid, tsid, tclass, requested, avd); | ||
882 | if (rc) | 888 | if (rc) |
883 | goto out; | 889 | goto out; |
884 | rcu_read_lock(); | 890 | rcu_read_lock(); |
885 | node = avc_insert(ssid, tsid, tclass, &entry); | 891 | node = avc_insert(ssid, tsid, tclass, avd); |
892 | } else { | ||
893 | if (in_avd) | ||
894 | memcpy(in_avd, &node->ae.avd, sizeof(*in_avd)); | ||
895 | avd = &node->ae.avd; | ||
886 | } | 896 | } |
887 | 897 | ||
888 | p_ae = node ? &node->ae : &entry; | 898 | denied = requested & ~(avd->allowed); |
889 | |||
890 | if (avd) | ||
891 | memcpy(avd, &p_ae->avd, sizeof(*avd)); | ||
892 | |||
893 | denied = requested & ~(p_ae->avd.allowed); | ||
894 | 899 | ||
895 | if (denied) { | 900 | if (denied) { |
896 | if (flags & AVC_STRICT) | 901 | if (flags & AVC_STRICT) |
897 | rc = -EACCES; | 902 | rc = -EACCES; |
898 | else if (!selinux_enforcing || security_permissive_sid(ssid)) | 903 | else if (!selinux_enforcing || security_permissive_sid(ssid)) |
899 | avc_update_node(AVC_CALLBACK_GRANT, requested, ssid, | 904 | avc_update_node(AVC_CALLBACK_GRANT, requested, ssid, |
900 | tsid, tclass, p_ae->avd.seqno); | 905 | tsid, tclass, avd->seqno); |
901 | else | 906 | else |
902 | rc = -EACCES; | 907 | rc = -EACCES; |
903 | } | 908 | } |