aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/netlabel.c
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2008-10-10 10:16:33 -0400
committerPaul Moore <paul.moore@hp.com>2008-10-10 10:16:33 -0400
commit6c5b3fc0147f79d714d2fe748b5869d7892ef2e7 (patch)
tree2cff691b2d4da2afd69660cb4ee647f6b553cdf9 /security/selinux/netlabel.c
parent014ab19a69c325f52d7bae54ceeda73d6307ae0c (diff)
selinux: Cache NetLabel secattrs in the socket's security struct
Previous work enabled the use of address based NetLabel selectors, which while highly useful, brought the potential for additional per-packet overhead when used. This patch attempts to mitigate some of that overhead by caching the NetLabel security attribute struct within the SELinux socket security structure. This should help eliminate the need to recreate the NetLabel secattr structure for each packet resulting in less overhead. Signed-off-by: Paul Moore <paul.moore@hp.com> Acked-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/netlabel.c')
-rw-r--r--security/selinux/netlabel.c115
1 files changed, 79 insertions, 36 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index b22b7dafa0e..f58701a7b72 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -68,6 +68,38 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
68} 68}
69 69
70/** 70/**
71 * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr
72 * @sk: the socket
73 *
74 * Description:
75 * Generate the NetLabel security attributes for a socket, making full use of
76 * the socket's attribute cache. Returns a pointer to the security attributes
77 * on success, NULL on failure.
78 *
79 */
80static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
81{
82 int rc;
83 struct sk_security_struct *sksec = sk->sk_security;
84 struct netlbl_lsm_secattr *secattr;
85
86 if (sksec->nlbl_secattr != NULL)
87 return sksec->nlbl_secattr;
88
89 secattr = netlbl_secattr_alloc(GFP_ATOMIC);
90 if (secattr == NULL)
91 return NULL;
92 rc = security_netlbl_sid_to_secattr(sksec->sid, secattr);
93 if (rc != 0) {
94 netlbl_secattr_free(secattr);
95 return NULL;
96 }
97 sksec->nlbl_secattr = secattr;
98
99 return secattr;
100}
101
102/**
71 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism 103 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
72 * @sk: the socket to label 104 * @sk: the socket to label
73 * 105 *
@@ -80,17 +112,15 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
80{ 112{
81 int rc; 113 int rc;
82 struct sk_security_struct *sksec = sk->sk_security; 114 struct sk_security_struct *sksec = sk->sk_security;
83 struct netlbl_lsm_secattr secattr; 115 struct netlbl_lsm_secattr *secattr;
84 116
85 if (sksec->nlbl_state != NLBL_REQUIRE) 117 if (sksec->nlbl_state != NLBL_REQUIRE)
86 return 0; 118 return 0;
87 119
88 netlbl_secattr_init(&secattr); 120 secattr = selinux_netlbl_sock_genattr(sk);
89 121 if (secattr == NULL)
90 rc = security_netlbl_sid_to_secattr(sksec->sid, &secattr); 122 return -ENOMEM;
91 if (rc != 0) 123 rc = netlbl_sock_setattr(sk, secattr);
92 goto sock_setsid_return;
93 rc = netlbl_sock_setattr(sk, &secattr);
94 switch (rc) { 124 switch (rc) {
95 case 0: 125 case 0:
96 sksec->nlbl_state = NLBL_LABELED; 126 sksec->nlbl_state = NLBL_LABELED;
@@ -101,8 +131,6 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
101 break; 131 break;
102 } 132 }
103 133
104sock_setsid_return:
105 netlbl_secattr_destroy(&secattr);
106 return rc; 134 return rc;
107} 135}
108 136
@@ -137,6 +165,20 @@ void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
137} 165}
138 166
139/** 167/**
168 * selinux_netlbl_sk_security_free - Free the NetLabel fields
169 * @sssec: the sk_security_struct
170 *
171 * Description:
172 * Free all of the memory in the NetLabel fields of a sk_security_struct.
173 *
174 */
175void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec)
176{
177 if (ssec->nlbl_secattr != NULL)
178 netlbl_secattr_free(ssec->nlbl_secattr);
179}
180
181/**
140 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields 182 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
141 * @ssec: the sk_security_struct 183 * @ssec: the sk_security_struct
142 * @family: the socket family 184 * @family: the socket family
@@ -209,7 +251,8 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
209 u32 sid) 251 u32 sid)
210{ 252{
211 int rc; 253 int rc;
212 struct netlbl_lsm_secattr secattr; 254 struct netlbl_lsm_secattr secattr_storage;
255 struct netlbl_lsm_secattr *secattr = NULL;
213 struct sock *sk; 256 struct sock *sk;
214 257
215 /* if this is a locally generated packet check to see if it is already 258 /* if this is a locally generated packet check to see if it is already
@@ -219,16 +262,21 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
219 struct sk_security_struct *sksec = sk->sk_security; 262 struct sk_security_struct *sksec = sk->sk_security;
220 if (sksec->nlbl_state != NLBL_REQSKB) 263 if (sksec->nlbl_state != NLBL_REQSKB)
221 return 0; 264 return 0;
265 secattr = sksec->nlbl_secattr;
266 }
267 if (secattr == NULL) {
268 secattr = &secattr_storage;
269 netlbl_secattr_init(secattr);
270 rc = security_netlbl_sid_to_secattr(sid, secattr);
271 if (rc != 0)
272 goto skbuff_setsid_return;
222 } 273 }
223 274
224 netlbl_secattr_init(&secattr); 275 rc = netlbl_skbuff_setattr(skb, family, secattr);
225 rc = security_netlbl_sid_to_secattr(sid, &secattr);
226 if (rc != 0)
227 goto skbuff_setsid_return;
228 rc = netlbl_skbuff_setattr(skb, family, &secattr);
229 276
230skbuff_setsid_return: 277skbuff_setsid_return:
231 netlbl_secattr_destroy(&secattr); 278 if (secattr == &secattr_storage)
279 netlbl_secattr_destroy(secattr);
232 return rc; 280 return rc;
233} 281}
234 282
@@ -245,18 +293,18 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
245{ 293{
246 int rc; 294 int rc;
247 struct sk_security_struct *sksec = sk->sk_security; 295 struct sk_security_struct *sksec = sk->sk_security;
248 struct netlbl_lsm_secattr secattr; 296 struct netlbl_lsm_secattr *secattr;
249 struct inet_sock *sk_inet = inet_sk(sk); 297 struct inet_sock *sk_inet = inet_sk(sk);
250 struct sockaddr_in addr; 298 struct sockaddr_in addr;
251 299
252 if (sksec->nlbl_state != NLBL_REQUIRE) 300 if (sksec->nlbl_state != NLBL_REQUIRE)
253 return; 301 return;
254 302
255 netlbl_secattr_init(&secattr); 303 secattr = selinux_netlbl_sock_genattr(sk);
256 if (security_netlbl_sid_to_secattr(sksec->sid, &secattr) != 0) 304 if (secattr == NULL)
257 goto inet_conn_established_return; 305 return;
258 306
259 rc = netlbl_sock_setattr(sk, &secattr); 307 rc = netlbl_sock_setattr(sk, secattr);
260 switch (rc) { 308 switch (rc) {
261 case 0: 309 case 0:
262 sksec->nlbl_state = NLBL_LABELED; 310 sksec->nlbl_state = NLBL_LABELED;
@@ -266,13 +314,13 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
266 * labeling protocols */ 314 * labeling protocols */
267 if (family != PF_INET) { 315 if (family != PF_INET) {
268 sksec->nlbl_state = NLBL_UNSET; 316 sksec->nlbl_state = NLBL_UNSET;
269 goto inet_conn_established_return; 317 return;
270 } 318 }
271 319
272 addr.sin_family = family; 320 addr.sin_family = family;
273 addr.sin_addr.s_addr = sk_inet->daddr; 321 addr.sin_addr.s_addr = sk_inet->daddr;
274 if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr, 322 if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
275 &secattr) != 0) { 323 secattr) != 0) {
276 /* we failed to label the connected socket (could be 324 /* we failed to label the connected socket (could be
277 * for a variety of reasons, the actual "why" isn't 325 * for a variety of reasons, the actual "why" isn't
278 * important here) so we have to go to our backup plan, 326 * important here) so we have to go to our backup plan,
@@ -300,10 +348,6 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
300 * return an error code */ 348 * return an error code */
301 break; 349 break;
302 } 350 }
303
304inet_conn_established_return:
305 netlbl_secattr_destroy(&secattr);
306 return;
307} 351}
308 352
309/** 353/**
@@ -468,13 +512,12 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
468{ 512{
469 int rc; 513 int rc;
470 struct sk_security_struct *sksec = sk->sk_security; 514 struct sk_security_struct *sksec = sk->sk_security;
471 struct netlbl_lsm_secattr secattr; 515 struct netlbl_lsm_secattr *secattr;
472 516
473 if (sksec->nlbl_state != NLBL_REQSKB && 517 if (sksec->nlbl_state != NLBL_REQSKB &&
474 sksec->nlbl_state != NLBL_CONNLABELED) 518 sksec->nlbl_state != NLBL_CONNLABELED)
475 return 0; 519 return 0;
476 520
477 netlbl_secattr_init(&secattr);
478 local_bh_disable(); 521 local_bh_disable();
479 bh_lock_sock_nested(sk); 522 bh_lock_sock_nested(sk);
480 523
@@ -487,17 +530,17 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
487 rc = 0; 530 rc = 0;
488 goto socket_connect_return; 531 goto socket_connect_return;
489 } 532 }
490 rc = security_netlbl_sid_to_secattr(sksec->sid, &secattr); 533 secattr = selinux_netlbl_sock_genattr(sk);
491 if (rc != 0) 534 if (secattr == NULL) {
535 rc = -ENOMEM;
492 goto socket_connect_return; 536 goto socket_connect_return;
493 rc = netlbl_conn_setattr(sk, addr, &secattr); 537 }
494 if (rc != 0) 538 rc = netlbl_conn_setattr(sk, addr, secattr);
495 goto socket_connect_return; 539 if (rc == 0)
496 sksec->nlbl_state = NLBL_CONNLABELED; 540 sksec->nlbl_state = NLBL_CONNLABELED;
497 541
498socket_connect_return: 542socket_connect_return:
499 bh_unlock_sock(sk); 543 bh_unlock_sock(sk);
500 local_bh_enable(); 544 local_bh_enable();
501 netlbl_secattr_destroy(&secattr);
502 return rc; 545 return rc;
503} 546}