summaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
authorVishal Goel <vishal.goel@samsung.com>2016-11-23 00:01:08 -0500
committerCasey Schaufler <casey@schaufler-ca.com>2017-01-10 12:47:20 -0500
commit3c7ce3427106f0fa2d8593f9fd8f82c494215782 (patch)
tree982ee2c19f059bbd1377d0345006a9f87eb7b9ee /security/smack
parent916cafdc95843fb9af5fd5f83ca499d75473d107 (diff)
SMACK: Add the rcu synchronization mechanism in ipv6 hooks
Add the rcu synchronization mechanism for accessing smk_ipv6_port_list in smack IPv6 hooks. Access to the port list is vulnerable to a race condition issue,it does not apply proper synchronization methods while working on critical section. It is possible that when one thread is reading the list, at the same time another thread is modifying the same port list, which can cause the major problems. To ensure proper synchronization between two threads, rcu mechanism has been applied while accessing and modifying the port list. RCU will also not affect the performance, as there are more accesses than modification where RCU is most effective synchronization mechanism. Signed-off-by: Vishal Goel <vishal.goel@samsung.com> Signed-off-by: Himanshu Shukla <himanshu.sh@samsung.com> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack_lsm.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 94dc9d406ce3..b76696b84e5c 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -52,6 +52,7 @@
52#define SMK_SENDING 2 52#define SMK_SENDING 2
53 53
54#ifdef SMACK_IPV6_PORT_LABELING 54#ifdef SMACK_IPV6_PORT_LABELING
55DEFINE_MUTEX(smack_ipv6_lock);
55static LIST_HEAD(smk_ipv6_port_list); 56static LIST_HEAD(smk_ipv6_port_list);
56#endif 57#endif
57static struct kmem_cache *smack_inode_cache; 58static struct kmem_cache *smack_inode_cache;
@@ -2603,17 +2604,20 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
2603 * on the bound socket. Take the changes to the port 2604 * on the bound socket. Take the changes to the port
2604 * as well. 2605 * as well.
2605 */ 2606 */
2606 list_for_each_entry(spp, &smk_ipv6_port_list, list) { 2607 rcu_read_lock();
2608 list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
2607 if (sk != spp->smk_sock) 2609 if (sk != spp->smk_sock)
2608 continue; 2610 continue;
2609 spp->smk_in = ssp->smk_in; 2611 spp->smk_in = ssp->smk_in;
2610 spp->smk_out = ssp->smk_out; 2612 spp->smk_out = ssp->smk_out;
2613 rcu_read_unlock();
2611 return; 2614 return;
2612 } 2615 }
2613 /* 2616 /*
2614 * A NULL address is only used for updating existing 2617 * A NULL address is only used for updating existing
2615 * bound entries. If there isn't one, it's OK. 2618 * bound entries. If there isn't one, it's OK.
2616 */ 2619 */
2620 rcu_read_unlock();
2617 return; 2621 return;
2618 } 2622 }
2619 2623
@@ -2629,16 +2633,18 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
2629 * Look for an existing port list entry. 2633 * Look for an existing port list entry.
2630 * This is an indication that a port is getting reused. 2634 * This is an indication that a port is getting reused.
2631 */ 2635 */
2632 list_for_each_entry(spp, &smk_ipv6_port_list, list) { 2636 rcu_read_lock();
2637 list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
2633 if (spp->smk_port != port) 2638 if (spp->smk_port != port)
2634 continue; 2639 continue;
2635 spp->smk_port = port; 2640 spp->smk_port = port;
2636 spp->smk_sock = sk; 2641 spp->smk_sock = sk;
2637 spp->smk_in = ssp->smk_in; 2642 spp->smk_in = ssp->smk_in;
2638 spp->smk_out = ssp->smk_out; 2643 spp->smk_out = ssp->smk_out;
2644 rcu_read_unlock();
2639 return; 2645 return;
2640 } 2646 }
2641 2647 rcu_read_unlock();
2642 /* 2648 /*
2643 * A new port entry is required. 2649 * A new port entry is required.
2644 */ 2650 */
@@ -2651,7 +2657,9 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
2651 spp->smk_in = ssp->smk_in; 2657 spp->smk_in = ssp->smk_in;
2652 spp->smk_out = ssp->smk_out; 2658 spp->smk_out = ssp->smk_out;
2653 2659
2654 list_add(&spp->list, &smk_ipv6_port_list); 2660 mutex_lock(&smack_ipv6_lock);
2661 list_add_rcu(&spp->list, &smk_ipv6_port_list);
2662 mutex_unlock(&smack_ipv6_lock);
2655 return; 2663 return;
2656} 2664}
2657 2665
@@ -2702,7 +2710,8 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
2702 return 0; 2710 return 0;
2703 2711
2704 port = ntohs(address->sin6_port); 2712 port = ntohs(address->sin6_port);
2705 list_for_each_entry(spp, &smk_ipv6_port_list, list) { 2713 rcu_read_lock();
2714 list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
2706 if (spp->smk_port != port) 2715 if (spp->smk_port != port)
2707 continue; 2716 continue;
2708 object = spp->smk_in; 2717 object = spp->smk_in;
@@ -2710,6 +2719,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
2710 ssp->smk_packet = spp->smk_out; 2719 ssp->smk_packet = spp->smk_out;
2711 break; 2720 break;
2712 } 2721 }
2722 rcu_read_unlock();
2713 2723
2714 return smk_ipv6_check(skp, object, address, act); 2724 return smk_ipv6_check(skp, object, address, act);
2715} 2725}