@@ -67,6 +67,38 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
67
67
return rc ;
68
68
}
69
69
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
+ */
80
+ static 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
+
70
102
/**
71
103
* selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
72
104
* @sk: the socket to label
@@ -80,17 +112,15 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
80
112
{
81
113
int rc ;
82
114
struct sk_security_struct * sksec = sk -> sk_security ;
83
- struct netlbl_lsm_secattr secattr ;
115
+ struct netlbl_lsm_secattr * secattr ;
84
116
85
117
if (sksec -> nlbl_state != NLBL_REQUIRE )
86
118
return 0 ;
87
119
88
- netlbl_secattr_init (& secattr );
89
-
90
- rc = security_netlbl_sid_to_secattr (sksec -> sid , & secattr );
91
- if (rc != 0 )
92
- goto sock_setsid_return ;
93
- rc = netlbl_sock_setattr (sk , & secattr );
120
+ secattr = selinux_netlbl_sock_genattr (sk );
121
+ if (secattr == NULL )
122
+ return - ENOMEM ;
123
+ rc = netlbl_sock_setattr (sk , secattr );
94
124
switch (rc ) {
95
125
case 0 :
96
126
sksec -> nlbl_state = NLBL_LABELED ;
@@ -101,8 +131,6 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
101
131
break ;
102
132
}
103
133
104
- sock_setsid_return :
105
- netlbl_secattr_destroy (& secattr );
106
134
return rc ;
107
135
}
108
136
@@ -136,6 +164,20 @@ void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
136
164
netlbl_skbuff_err (skb , error , gateway );
137
165
}
138
166
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
+ */
175
+ void 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
+
139
181
/**
140
182
* selinux_netlbl_sk_security_reset - Reset the NetLabel fields
141
183
* @ssec: the sk_security_struct
@@ -209,7 +251,8 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
209
251
u32 sid )
210
252
{
211
253
int rc ;
212
- struct netlbl_lsm_secattr secattr ;
254
+ struct netlbl_lsm_secattr secattr_storage ;
255
+ struct netlbl_lsm_secattr * secattr = NULL ;
213
256
struct sock * sk ;
214
257
215
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
262
struct sk_security_struct * sksec = sk -> sk_security ;
220
263
if (sksec -> nlbl_state != NLBL_REQSKB )
221
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 );
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 );
275
+ rc = netlbl_skbuff_setattr (skb , family , secattr );
229
276
230
277
skbuff_setsid_return :
231
- netlbl_secattr_destroy (& secattr );
278
+ if (secattr == & secattr_storage )
279
+ netlbl_secattr_destroy (secattr );
232
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
294
int rc ;
247
295
struct sk_security_struct * sksec = sk -> sk_security ;
248
- struct netlbl_lsm_secattr secattr ;
296
+ struct netlbl_lsm_secattr * secattr ;
249
297
struct inet_sock * sk_inet = inet_sk (sk );
250
298
struct sockaddr_in addr ;
251
299
252
300
if (sksec -> nlbl_state != NLBL_REQUIRE )
253
301
return ;
254
302
255
- netlbl_secattr_init ( & secattr );
256
- if (security_netlbl_sid_to_secattr ( sksec -> sid , & secattr ) != 0 )
257
- goto inet_conn_established_return ;
303
+ secattr = selinux_netlbl_sock_genattr ( sk );
304
+ if (secattr == NULL )
305
+ return ;
258
306
259
- rc = netlbl_sock_setattr (sk , & secattr );
307
+ rc = netlbl_sock_setattr (sk , secattr );
260
308
switch (rc ) {
261
309
case 0 :
262
310
sksec -> nlbl_state = NLBL_LABELED ;
@@ -266,13 +314,13 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
266
314
* labeling protocols */
267
315
if (family != PF_INET ) {
268
316
sksec -> nlbl_state = NLBL_UNSET ;
269
- goto inet_conn_established_return ;
317
+ return ;
270
318
}
271
319
272
320
addr .sin_family = family ;
273
321
addr .sin_addr .s_addr = sk_inet -> daddr ;
274
322
if (netlbl_conn_setattr (sk , (struct sockaddr * )& addr ,
275
- & secattr ) != 0 ) {
323
+ secattr ) != 0 ) {
276
324
/* we failed to label the connected socket (could be
277
325
* for a variety of reasons, the actual "why" isn't
278
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
348
* return an error code */
301
349
break ;
302
350
}
303
-
304
- inet_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
513
int rc ;
470
514
struct sk_security_struct * sksec = sk -> sk_security ;
471
- struct netlbl_lsm_secattr secattr ;
515
+ struct netlbl_lsm_secattr * secattr ;
472
516
473
517
if (sksec -> nlbl_state != NLBL_REQSKB &&
474
518
sksec -> nlbl_state != NLBL_CONNLABELED )
475
519
return 0 ;
476
520
477
- netlbl_secattr_init (& secattr );
478
521
local_bh_disable ();
479
522
bh_lock_sock_nested (sk );
480
523
@@ -487,17 +530,17 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
487
530
rc = 0 ;
488
531
goto socket_connect_return ;
489
532
}
490
- rc = security_netlbl_sid_to_secattr (sksec -> sid , & secattr );
491
- if (rc != 0 )
533
+ secattr = selinux_netlbl_sock_genattr (sk );
534
+ if (secattr == NULL ) {
535
+ rc = - ENOMEM ;
492
536
goto socket_connect_return ;
493
- rc = netlbl_conn_setattr ( sk , addr , & secattr );
494
- if ( rc != 0 )
495
- goto socket_connect_return ;
496
- sksec -> nlbl_state = NLBL_CONNLABELED ;
537
+ }
538
+ rc = netlbl_conn_setattr ( sk , addr , secattr );
539
+ if ( rc == 0 )
540
+ sksec -> nlbl_state = NLBL_CONNLABELED ;
497
541
498
542
socket_connect_return :
499
543
bh_unlock_sock (sk );
500
544
local_bh_enable ();
501
- netlbl_secattr_destroy (& secattr );
502
545
return rc ;
503
546
}
0 commit comments