aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--security/selinux/hooks.c1
-rw-r--r--security/selinux/include/netlabel.h7
-rw-r--r--security/selinux/include/objsec.h7
-rw-r--r--security/selinux/netlabel.c115
4 files changed, 91 insertions, 39 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 632ac3e80a6..3aa811eba25 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -291,6 +291,7 @@ static void sk_free_security(struct sock *sk)
291 struct sk_security_struct *ssec = sk->sk_security; 291 struct sk_security_struct *ssec = sk->sk_security;
292 292
293 sk->sk_security = NULL; 293 sk->sk_security = NULL;
294 selinux_netlbl_sk_security_free(ssec);
294 kfree(ssec); 295 kfree(ssec);
295} 296}
296 297
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index 982bac0ac32..b913c8d0603 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -41,6 +41,7 @@ void selinux_netlbl_cache_invalidate(void);
41 41
42void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); 42void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway);
43 43
44void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec);
44void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 45void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
45 int family); 46 int family);
46 47
@@ -77,6 +78,12 @@ static inline void selinux_netlbl_err(struct sk_buff *skb,
77 return; 78 return;
78} 79}
79 80
81static inline void selinux_netlbl_sk_security_free(
82 struct sk_security_struct *ssec)
83{
84 return;
85}
86
80static inline void selinux_netlbl_sk_security_reset( 87static inline void selinux_netlbl_sk_security_reset(
81 struct sk_security_struct *ssec, 88 struct sk_security_struct *ssec,
82 int family) 89 int family)
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index ad34787c6c0..f8be8d7fa26 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -109,9 +109,6 @@ struct netport_security_struct {
109}; 109};
110 110
111struct sk_security_struct { 111struct sk_security_struct {
112 u32 sid; /* SID of this object */
113 u32 peer_sid; /* SID of peer */
114 u16 sclass; /* sock security class */
115#ifdef CONFIG_NETLABEL 112#ifdef CONFIG_NETLABEL
116 enum { /* NetLabel state */ 113 enum { /* NetLabel state */
117 NLBL_UNSET = 0, 114 NLBL_UNSET = 0,
@@ -120,7 +117,11 @@ struct sk_security_struct {
120 NLBL_REQSKB, 117 NLBL_REQSKB,
121 NLBL_CONNLABELED, 118 NLBL_CONNLABELED,
122 } nlbl_state; 119 } nlbl_state;
120 struct netlbl_lsm_secattr *nlbl_secattr; /* NetLabel sec attributes */
123#endif 121#endif
122 u32 sid; /* SID of this object */
123 u32 peer_sid; /* SID of peer */
124 u16 sclass; /* sock security class */
124}; 125};
125 126
126struct key_security_struct { 127struct key_security_struct {
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)