diff options
Diffstat (limited to 'security/selinux/netlabel.c')
-rw-r--r-- | security/selinux/netlabel.c | 75 |
1 files changed, 45 insertions, 30 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 66e013d6f6f6..0fa2be4149e8 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
@@ -36,6 +36,33 @@ | |||
36 | #include "security.h" | 36 | #include "security.h" |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * selinux_netlbl_sidlookup_cached - Cache a SID lookup | ||
40 | * @skb: the packet | ||
41 | * @secattr: the NetLabel security attributes | ||
42 | * @sid: the SID | ||
43 | * | ||
44 | * Description: | ||
45 | * Query the SELinux security server to lookup the correct SID for the given | ||
46 | * security attributes. If the query is successful, cache the result to speed | ||
47 | * up future lookups. Returns zero on success, negative values on failure. | ||
48 | * | ||
49 | */ | ||
50 | static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, | ||
51 | struct netlbl_lsm_secattr *secattr, | ||
52 | u32 *sid) | ||
53 | { | ||
54 | int rc; | ||
55 | |||
56 | rc = security_netlbl_secattr_to_sid(secattr, sid); | ||
57 | if (rc == 0 && | ||
58 | (secattr->flags & NETLBL_SECATTR_CACHEABLE) && | ||
59 | (secattr->flags & NETLBL_SECATTR_CACHE)) | ||
60 | netlbl_cache_add(skb, secattr); | ||
61 | |||
62 | return rc; | ||
63 | } | ||
64 | |||
65 | /** | ||
39 | * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism | 66 | * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism |
40 | * @sk: the socket to label | 67 | * @sk: the socket to label |
41 | * @sid: the SID to use | 68 | * @sid: the SID to use |
@@ -137,14 +164,14 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, | |||
137 | * lock as other threads could have access to ssec */ | 164 | * lock as other threads could have access to ssec */ |
138 | rcu_read_lock(); | 165 | rcu_read_lock(); |
139 | selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family); | 166 | selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family); |
140 | newssec->sclass = ssec->sclass; | ||
141 | rcu_read_unlock(); | 167 | rcu_read_unlock(); |
142 | } | 168 | } |
143 | 169 | ||
144 | /** | 170 | /** |
145 | * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel | 171 | * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel |
146 | * @skb: the packet | 172 | * @skb: the packet |
147 | * @base_sid: the SELinux SID to use as a context for MLS only attributes | 173 | * @family: protocol family |
174 | * @type: NetLabel labeling protocol type | ||
148 | * @sid: the SID | 175 | * @sid: the SID |
149 | * | 176 | * |
150 | * Description: | 177 | * Description: |
@@ -153,7 +180,10 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, | |||
153 | * assign to the packet. Returns zero on success, negative values on failure. | 180 | * assign to the packet. Returns zero on success, negative values on failure. |
154 | * | 181 | * |
155 | */ | 182 | */ |
156 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid) | 183 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, |
184 | u16 family, | ||
185 | u32 *type, | ||
186 | u32 *sid) | ||
157 | { | 187 | { |
158 | int rc; | 188 | int rc; |
159 | struct netlbl_lsm_secattr secattr; | 189 | struct netlbl_lsm_secattr secattr; |
@@ -164,15 +194,12 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid) | |||
164 | } | 194 | } |
165 | 195 | ||
166 | netlbl_secattr_init(&secattr); | 196 | netlbl_secattr_init(&secattr); |
167 | rc = netlbl_skbuff_getattr(skb, &secattr); | 197 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
168 | if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) { | 198 | if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) |
169 | rc = security_netlbl_secattr_to_sid(&secattr, base_sid, sid); | 199 | rc = selinux_netlbl_sidlookup_cached(skb, &secattr, sid); |
170 | if (rc == 0 && | 200 | else |
171 | (secattr.flags & NETLBL_SECATTR_CACHEABLE) && | ||
172 | (secattr.flags & NETLBL_SECATTR_CACHE)) | ||
173 | netlbl_cache_add(skb, &secattr); | ||
174 | } else | ||
175 | *sid = SECSID_NULL; | 201 | *sid = SECSID_NULL; |
202 | *type = secattr.type; | ||
176 | netlbl_secattr_destroy(&secattr); | 203 | netlbl_secattr_destroy(&secattr); |
177 | 204 | ||
178 | return rc; | 205 | return rc; |
@@ -190,13 +217,10 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid) | |||
190 | */ | 217 | */ |
191 | void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) | 218 | void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) |
192 | { | 219 | { |
193 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | ||
194 | struct sk_security_struct *sksec = sk->sk_security; | 220 | struct sk_security_struct *sksec = sk->sk_security; |
195 | struct netlbl_lsm_secattr secattr; | 221 | struct netlbl_lsm_secattr secattr; |
196 | u32 nlbl_peer_sid; | 222 | u32 nlbl_peer_sid; |
197 | 223 | ||
198 | sksec->sclass = isec->sclass; | ||
199 | |||
200 | rcu_read_lock(); | 224 | rcu_read_lock(); |
201 | 225 | ||
202 | if (sksec->nlbl_state != NLBL_REQUIRE) { | 226 | if (sksec->nlbl_state != NLBL_REQUIRE) { |
@@ -207,9 +231,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) | |||
207 | netlbl_secattr_init(&secattr); | 231 | netlbl_secattr_init(&secattr); |
208 | if (netlbl_sock_getattr(sk, &secattr) == 0 && | 232 | if (netlbl_sock_getattr(sk, &secattr) == 0 && |
209 | secattr.flags != NETLBL_SECATTR_NONE && | 233 | secattr.flags != NETLBL_SECATTR_NONE && |
210 | security_netlbl_secattr_to_sid(&secattr, | 234 | security_netlbl_secattr_to_sid(&secattr, &nlbl_peer_sid) == 0) |
211 | SECINITSID_NETMSG, | ||
212 | &nlbl_peer_sid) == 0) | ||
213 | sksec->peer_sid = nlbl_peer_sid; | 235 | sksec->peer_sid = nlbl_peer_sid; |
214 | netlbl_secattr_destroy(&secattr); | 236 | netlbl_secattr_destroy(&secattr); |
215 | 237 | ||
@@ -234,11 +256,8 @@ int selinux_netlbl_socket_post_create(struct socket *sock) | |||
234 | { | 256 | { |
235 | int rc = 0; | 257 | int rc = 0; |
236 | struct sock *sk = sock->sk; | 258 | struct sock *sk = sock->sk; |
237 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | ||
238 | struct sk_security_struct *sksec = sk->sk_security; | 259 | struct sk_security_struct *sksec = sk->sk_security; |
239 | 260 | ||
240 | sksec->sclass = isec->sclass; | ||
241 | |||
242 | rcu_read_lock(); | 261 | rcu_read_lock(); |
243 | if (sksec->nlbl_state == NLBL_REQUIRE) | 262 | if (sksec->nlbl_state == NLBL_REQUIRE) |
244 | rc = selinux_netlbl_sock_setsid(sk, sksec->sid); | 263 | rc = selinux_netlbl_sock_setsid(sk, sksec->sid); |
@@ -292,6 +311,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) | |||
292 | * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel | 311 | * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel |
293 | * @sksec: the sock's sk_security_struct | 312 | * @sksec: the sock's sk_security_struct |
294 | * @skb: the packet | 313 | * @skb: the packet |
314 | * @family: protocol family | ||
295 | * @ad: the audit data | 315 | * @ad: the audit data |
296 | * | 316 | * |
297 | * Description: | 317 | * Description: |
@@ -302,6 +322,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) | |||
302 | */ | 322 | */ |
303 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 323 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
304 | struct sk_buff *skb, | 324 | struct sk_buff *skb, |
325 | u16 family, | ||
305 | struct avc_audit_data *ad) | 326 | struct avc_audit_data *ad) |
306 | { | 327 | { |
307 | int rc; | 328 | int rc; |
@@ -313,16 +334,10 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | |||
313 | return 0; | 334 | return 0; |
314 | 335 | ||
315 | netlbl_secattr_init(&secattr); | 336 | netlbl_secattr_init(&secattr); |
316 | rc = netlbl_skbuff_getattr(skb, &secattr); | 337 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
317 | if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) { | 338 | if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) |
318 | rc = security_netlbl_secattr_to_sid(&secattr, | 339 | rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid); |
319 | SECINITSID_NETMSG, | 340 | else |
320 | &nlbl_sid); | ||
321 | if (rc == 0 && | ||
322 | (secattr.flags & NETLBL_SECATTR_CACHEABLE) && | ||
323 | (secattr.flags & NETLBL_SECATTR_CACHE)) | ||
324 | netlbl_cache_add(skb, &secattr); | ||
325 | } else | ||
326 | nlbl_sid = SECINITSID_UNLABELED; | 341 | nlbl_sid = SECINITSID_UNLABELED; |
327 | netlbl_secattr_destroy(&secattr); | 342 | netlbl_secattr_destroy(&secattr); |
328 | if (rc != 0) | 343 | if (rc != 0) |