aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/netlabel.c
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2008-02-25 11:40:33 -0500
committerJames Morris <jmorris@namei.org>2008-04-18 06:26:03 -0400
commitf74af6e816c940c678c235d49486fe40d7e49ce9 (patch)
tree06f2fa54bd7ceabac2ad29a6ab0aca1deb87c032 /security/selinux/netlabel.c
parent4b119e21d0c66c22e8ca03df05d9de623d0eb50f (diff)
SELinux: Correct the NetLabel locking for the sk_security_struct
The RCU/spinlock locking approach for the nlbl_state in the sk_security_struct was almost certainly overkill. This patch removes both the RCU and spinlock locking, relying on the existing socket locks to handle the case of multiple writers. This change also makes several code reductions possible. Less locking, less code - it's a Good Thing. Signed-off-by: Paul Moore <paul.moore@hp.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/netlabel.c')
-rw-r--r--security/selinux/netlabel.c81
1 files changed, 13 insertions, 68 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 0fa2be4149e8..ccf71f69a185 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -69,9 +69,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
69 * 69 *
70 * Description: 70 * Description:
71 * Attempt to label a socket using the NetLabel mechanism using the given 71 * Attempt to label a socket using the NetLabel mechanism using the given
72 * SID. Returns zero values on success, negative values on failure. The 72 * 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 * 73 *
76 */ 74 */
77static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) 75static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
@@ -86,11 +84,8 @@ static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
86 if (rc != 0) 84 if (rc != 0)
87 goto sock_setsid_return; 85 goto sock_setsid_return;
88 rc = netlbl_sock_setattr(sk, &secattr); 86 rc = netlbl_sock_setattr(sk, &secattr);
89 if (rc == 0) { 87 if (rc == 0)
90 spin_lock_bh(&sksec->nlbl_lock);
91 sksec->nlbl_state = NLBL_LABELED; 88 sksec->nlbl_state = NLBL_LABELED;
92 spin_unlock_bh(&sksec->nlbl_lock);
93 }
94 89
95sock_setsid_return: 90sock_setsid_return:
96 netlbl_secattr_destroy(&secattr); 91 netlbl_secattr_destroy(&secattr);
@@ -129,45 +124,6 @@ void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
129} 124}
130 125
131/** 126/**
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 127 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
172 * @skb: the packet 128 * @skb: the packet
173 * @family: protocol family 129 * @family: protocol family
@@ -221,12 +177,8 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
221 struct netlbl_lsm_secattr secattr; 177 struct netlbl_lsm_secattr secattr;
222 u32 nlbl_peer_sid; 178 u32 nlbl_peer_sid;
223 179
224 rcu_read_lock(); 180 if (sksec->nlbl_state != NLBL_REQUIRE)
225
226 if (sksec->nlbl_state != NLBL_REQUIRE) {
227 rcu_read_unlock();
228 return; 181 return;
229 }
230 182
231 netlbl_secattr_init(&secattr); 183 netlbl_secattr_init(&secattr);
232 if (netlbl_sock_getattr(sk, &secattr) == 0 && 184 if (netlbl_sock_getattr(sk, &secattr) == 0 &&
@@ -239,8 +191,6 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
239 * here we will pick up the pieces in later calls to 191 * here we will pick up the pieces in later calls to
240 * selinux_netlbl_inode_permission(). */ 192 * selinux_netlbl_inode_permission(). */
241 selinux_netlbl_sock_setsid(sk, sksec->sid); 193 selinux_netlbl_sock_setsid(sk, sksec->sid);
242
243 rcu_read_unlock();
244} 194}
245 195
246/** 196/**
@@ -254,16 +204,13 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
254 */ 204 */
255int selinux_netlbl_socket_post_create(struct socket *sock) 205int selinux_netlbl_socket_post_create(struct socket *sock)
256{ 206{
257 int rc = 0;
258 struct sock *sk = sock->sk; 207 struct sock *sk = sock->sk;
259 struct sk_security_struct *sksec = sk->sk_security; 208 struct sk_security_struct *sksec = sk->sk_security;
260 209
261 rcu_read_lock(); 210 if (sksec->nlbl_state != NLBL_REQUIRE)
262 if (sksec->nlbl_state == NLBL_REQUIRE) 211 return 0;
263 rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
264 rcu_read_unlock();
265 212
266 return rc; 213 return selinux_netlbl_sock_setsid(sk, sksec->sid);
267} 214}
268 215
269/** 216/**
@@ -288,21 +235,21 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
288 if (!S_ISSOCK(inode->i_mode) || 235 if (!S_ISSOCK(inode->i_mode) ||
289 ((mask & (MAY_WRITE | MAY_APPEND)) == 0)) 236 ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
290 return 0; 237 return 0;
238
291 sock = SOCKET_I(inode); 239 sock = SOCKET_I(inode);
292 sk = sock->sk; 240 sk = sock->sk;
293 sksec = sk->sk_security; 241 sksec = sk->sk_security;
294 242 if (sksec->nlbl_state != NLBL_REQUIRE)
295 rcu_read_lock();
296 if (sksec->nlbl_state != NLBL_REQUIRE) {
297 rcu_read_unlock();
298 return 0; 243 return 0;
299 } 244
300 local_bh_disable(); 245 local_bh_disable();
301 bh_lock_sock_nested(sk); 246 bh_lock_sock_nested(sk);
302 rc = selinux_netlbl_sock_setsid(sk, sksec->sid); 247 if (likely(sksec->nlbl_state == NLBL_REQUIRE))
248 rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
249 else
250 rc = 0;
303 bh_unlock_sock(sk); 251 bh_unlock_sock(sk);
304 local_bh_enable(); 252 local_bh_enable();
305 rcu_read_unlock();
306 253
307 return rc; 254 return rc;
308} 255}
@@ -385,7 +332,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
385 struct sk_security_struct *sksec = sk->sk_security; 332 struct sk_security_struct *sksec = sk->sk_security;
386 struct netlbl_lsm_secattr secattr; 333 struct netlbl_lsm_secattr secattr;
387 334
388 rcu_read_lock();
389 if (level == IPPROTO_IP && optname == IP_OPTIONS && 335 if (level == IPPROTO_IP && optname == IP_OPTIONS &&
390 sksec->nlbl_state == NLBL_LABELED) { 336 sksec->nlbl_state == NLBL_LABELED) {
391 netlbl_secattr_init(&secattr); 337 netlbl_secattr_init(&secattr);
@@ -396,7 +342,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
396 rc = -EACCES; 342 rc = -EACCES;
397 netlbl_secattr_destroy(&secattr); 343 netlbl_secattr_destroy(&secattr);
398 } 344 }
399 rcu_read_unlock();
400 345
401 return rc; 346 return rc;
402} 347}