diff options
-rw-r--r-- | security/selinux/hooks.c | 4 | ||||
-rw-r--r-- | security/selinux/include/netlabel.h | 16 | ||||
-rw-r--r-- | security/selinux/include/objsec.h | 1 | ||||
-rw-r--r-- | security/selinux/netlabel.c | 81 |
4 files changed, 15 insertions, 87 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d39b59cf8a08..d51bd40a04a8 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 | ||
4145 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 4145 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) |
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index 00a2809c8506..9a9e7cd9a379 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 | ||
42 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, | 42 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, |
43 | int family); | 43 | int family); |
44 | void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, | ||
45 | int family); | ||
46 | void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, | ||
47 | struct sk_security_struct *newssec); | ||
48 | 44 | ||
49 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | 45 | int 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 | } |
76 | static inline void selinux_netlbl_sk_security_init( | ||
77 | struct sk_security_struct *ssec, | ||
78 | int family) | ||
79 | { | ||
80 | return; | ||
81 | } | ||
82 | static 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 | ||
89 | static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | 73 | static 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 c6c2bb4ebacc..0b74077eed4f 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 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 | */ |
77 | static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) | 75 | static 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 | ||
95 | sock_setsid_return: | 90 | sock_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 | */ | ||
141 | void 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 | */ | ||
159 | void 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 | */ |
255 | int selinux_netlbl_socket_post_create(struct socket *sock) | 205 | int 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 | } |