aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/netlabel.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/netlabel.c')
-rw-r--r--security/selinux/netlabel.c82
1 files changed, 14 insertions, 68 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 0fa2be4149e8..e8ee91ac12ef 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -34,6 +34,7 @@
34 34
35#include "objsec.h" 35#include "objsec.h"
36#include "security.h" 36#include "security.h"
37#include "netlabel.h"
37 38
38/** 39/**
39 * selinux_netlbl_sidlookup_cached - Cache a SID lookup 40 * selinux_netlbl_sidlookup_cached - Cache a SID lookup
@@ -69,9 +70,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
69 * 70 *
70 * Description: 71 * Description:
71 * Attempt to label a socket using the NetLabel mechanism using the given 72 * Attempt to label a socket using the NetLabel mechanism using the given
72 * SID. Returns zero values on success, negative values on failure. The 73 * SID. Returns zero values on success, negative values on failure.
73 * caller is responsibile for calling rcu_read_lock() before calling this
74 * this function and rcu_read_unlock() after this function returns.
75 * 74 *
76 */ 75 */
77static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) 76static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
@@ -86,11 +85,8 @@ static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
86 if (rc != 0) 85 if (rc != 0)
87 goto sock_setsid_return; 86 goto sock_setsid_return;
88 rc = netlbl_sock_setattr(sk, &secattr); 87 rc = netlbl_sock_setattr(sk, &secattr);
89 if (rc == 0) { 88 if (rc == 0)
90 spin_lock_bh(&sksec->nlbl_lock);
91 sksec->nlbl_state = NLBL_LABELED; 89 sksec->nlbl_state = NLBL_LABELED;
92 spin_unlock_bh(&sksec->nlbl_lock);
93 }
94 90
95sock_setsid_return: 91sock_setsid_return:
96 netlbl_secattr_destroy(&secattr); 92 netlbl_secattr_destroy(&secattr);
@@ -129,45 +125,6 @@ void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
129} 125}
130 126
131/** 127/**
132 * selinux_netlbl_sk_security_init - Setup the NetLabel fields
133 * @ssec: the sk_security_struct
134 * @family: the socket family
135 *
136 * Description:
137 * Called when a new sk_security_struct is allocated to initialize the NetLabel
138 * fields.
139 *
140 */
141void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
142 int family)
143{
144 /* No locking needed, we are the only one who has access to ssec */
145 selinux_netlbl_sk_security_reset(ssec, family);
146 spin_lock_init(&ssec->nlbl_lock);
147}
148
149/**
150 * selinux_netlbl_sk_security_clone - Copy the NetLabel fields
151 * @ssec: the original sk_security_struct
152 * @newssec: the cloned sk_security_struct
153 *
154 * Description:
155 * Clone the NetLabel specific sk_security_struct fields from @ssec to
156 * @newssec.
157 *
158 */
159void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
160 struct sk_security_struct *newssec)
161{
162 /* We don't need to take newssec->nlbl_lock because we are the only
163 * thread with access to newssec, but we do need to take the RCU read
164 * lock as other threads could have access to ssec */
165 rcu_read_lock();
166 selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
167 rcu_read_unlock();
168}
169
170/**
171 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel 128 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
172 * @skb: the packet 129 * @skb: the packet
173 * @family: protocol family 130 * @family: protocol family
@@ -221,12 +178,8 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
221 struct netlbl_lsm_secattr secattr; 178 struct netlbl_lsm_secattr secattr;
222 u32 nlbl_peer_sid; 179 u32 nlbl_peer_sid;
223 180
224 rcu_read_lock(); 181 if (sksec->nlbl_state != NLBL_REQUIRE)
225
226 if (sksec->nlbl_state != NLBL_REQUIRE) {
227 rcu_read_unlock();
228 return; 182 return;
229 }
230 183
231 netlbl_secattr_init(&secattr); 184 netlbl_secattr_init(&secattr);
232 if (netlbl_sock_getattr(sk, &secattr) == 0 && 185 if (netlbl_sock_getattr(sk, &secattr) == 0 &&
@@ -239,8 +192,6 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
239 * here we will pick up the pieces in later calls to 192 * here we will pick up the pieces in later calls to
240 * selinux_netlbl_inode_permission(). */ 193 * selinux_netlbl_inode_permission(). */
241 selinux_netlbl_sock_setsid(sk, sksec->sid); 194 selinux_netlbl_sock_setsid(sk, sksec->sid);
242
243 rcu_read_unlock();
244} 195}
245 196
246/** 197/**
@@ -254,16 +205,13 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
254 */ 205 */
255int selinux_netlbl_socket_post_create(struct socket *sock) 206int selinux_netlbl_socket_post_create(struct socket *sock)
256{ 207{
257 int rc = 0;
258 struct sock *sk = sock->sk; 208 struct sock *sk = sock->sk;
259 struct sk_security_struct *sksec = sk->sk_security; 209 struct sk_security_struct *sksec = sk->sk_security;
260 210
261 rcu_read_lock(); 211 if (sksec->nlbl_state != NLBL_REQUIRE)
262 if (sksec->nlbl_state == NLBL_REQUIRE) 212 return 0;
263 rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
264 rcu_read_unlock();
265 213
266 return rc; 214 return selinux_netlbl_sock_setsid(sk, sksec->sid);
267} 215}
268 216
269/** 217/**
@@ -288,21 +236,21 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
288 if (!S_ISSOCK(inode->i_mode) || 236 if (!S_ISSOCK(inode->i_mode) ||
289 ((mask & (MAY_WRITE | MAY_APPEND)) == 0)) 237 ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
290 return 0; 238 return 0;
239
291 sock = SOCKET_I(inode); 240 sock = SOCKET_I(inode);
292 sk = sock->sk; 241 sk = sock->sk;
293 sksec = sk->sk_security; 242 sksec = sk->sk_security;
294 243 if (sksec->nlbl_state != NLBL_REQUIRE)
295 rcu_read_lock();
296 if (sksec->nlbl_state != NLBL_REQUIRE) {
297 rcu_read_unlock();
298 return 0; 244 return 0;
299 } 245
300 local_bh_disable(); 246 local_bh_disable();
301 bh_lock_sock_nested(sk); 247 bh_lock_sock_nested(sk);
302 rc = selinux_netlbl_sock_setsid(sk, sksec->sid); 248 if (likely(sksec->nlbl_state == NLBL_REQUIRE))
249 rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
250 else
251 rc = 0;
303 bh_unlock_sock(sk); 252 bh_unlock_sock(sk);
304 local_bh_enable(); 253 local_bh_enable();
305 rcu_read_unlock();
306 254
307 return rc; 255 return rc;
308} 256}
@@ -385,7 +333,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
385 struct sk_security_struct *sksec = sk->sk_security; 333 struct sk_security_struct *sksec = sk->sk_security;
386 struct netlbl_lsm_secattr secattr; 334 struct netlbl_lsm_secattr secattr;
387 335
388 rcu_read_lock();
389 if (level == IPPROTO_IP && optname == IP_OPTIONS && 336 if (level == IPPROTO_IP && optname == IP_OPTIONS &&
390 sksec->nlbl_state == NLBL_LABELED) { 337 sksec->nlbl_state == NLBL_LABELED) {
391 netlbl_secattr_init(&secattr); 338 netlbl_secattr_init(&secattr);
@@ -396,7 +343,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
396 rc = -EACCES; 343 rc = -EACCES;
397 netlbl_secattr_destroy(&secattr); 344 netlbl_secattr_destroy(&secattr);
398 } 345 }
399 rcu_read_unlock();
400 346
401 return rc; 347 return rc;
402} 348}