aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/avc.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/avc.c')
-rw-r--r--security/selinux/avc.c43
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
353static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae) 353static 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
361static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) 361static 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 */
450static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae) 450static 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)
864int avc_has_perm_noaudit(u32 ssid, u32 tsid, 864int 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 }