aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/selinux/hooks.c4
-rw-r--r--security/selinux/include/netlabel.h16
-rw-r--r--security/selinux/include/objsec.h1
-rw-r--r--security/selinux/netlabel.c81
4 files changed, 15 insertions, 87 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d39b59cf8a0..d51bd40a04a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -280,7 +280,7 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
280 ssec->sid = SECINITSID_UNLABELED; 280 ssec->sid = SECINITSID_UNLABELED;
281 sk->sk_security = ssec; 281 sk->sk_security = ssec;
282 282
283 selinux_netlbl_sk_security_init(ssec, family); 283 selinux_netlbl_sk_security_reset(ssec, family);
284 284
285 return 0; 285 return 0;
286} 286}
@@ -4139,7 +4139,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4139 newssec->peer_sid = ssec->peer_sid; 4139 newssec->peer_sid = ssec->peer_sid;
4140 newssec->sclass = ssec->sclass; 4140 newssec->sclass = ssec->sclass;
4141 4141
4142 selinux_netlbl_sk_security_clone(ssec, newssec); 4142 selinux_netlbl_sk_security_reset(newssec, newsk->sk_family);
4143} 4143}
4144 4144
4145static void selinux_sk_getsecid(struct sock *sk, u32 *secid) 4145static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index 00a2809c850..9a9e7cd9a37 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -41,10 +41,6 @@ void selinux_netlbl_cache_invalidate(void);
41 41
42void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 42void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
43 int family); 43 int family);
44void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
45 int family);
46void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
47 struct sk_security_struct *newssec);
48 44
49int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 45int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
50 u16 family, 46 u16 family,
@@ -73,18 +69,6 @@ static inline void selinux_netlbl_sk_security_reset(
73{ 69{
74 return; 70 return;
75} 71}
76static inline void selinux_netlbl_sk_security_init(
77 struct sk_security_struct *ssec,
78 int family)
79{
80 return;
81}
82static inline void selinux_netlbl_sk_security_clone(
83 struct sk_security_struct *ssec,
84 struct sk_security_struct *newssec)
85{
86 return;
87}
88 72
89static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 73static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
90 u16 family, 74 u16 family,
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index c6c2bb4ebac..0b74077eed4 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -120,7 +120,6 @@ struct sk_security_struct {
120 NLBL_REQUIRE, 120 NLBL_REQUIRE,
121 NLBL_LABELED, 121 NLBL_LABELED,
122 } nlbl_state; 122 } nlbl_state;
123 spinlock_t nlbl_lock; /* protects nlbl_state */
124#endif 123#endif
125}; 124};
126 125
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 0fa2be4149e..ccf71f69a18 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}