diff options
Diffstat (limited to 'security/selinux/netlabel.c')
-rw-r--r-- | security/selinux/netlabel.c | 82 |
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 | */ |
77 | static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) | 76 | static 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 | ||
95 | sock_setsid_return: | 91 | sock_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 | */ | ||
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 | 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 | */ |
255 | int selinux_netlbl_socket_post_create(struct socket *sock) | 206 | int 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 | } |