Blame view

security/selinux/netlabel.c 15.8 KB
1ccea77e2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
5778eabd9   Paul Moore   SELinux: extract ...
2
3
4
5
6
7
  /*
   * SELinux NetLabel Support
   *
   * This file provides the necessary glue to tie NetLabel into the SELinux
   * subsystem.
   *
82c21bfab   Paul Moore   doc: Update the e...
8
   * Author: Paul Moore <paul@paul-moore.com>
5778eabd9   Paul Moore   SELinux: extract ...
9
10
11
   */
  
  /*
948bf85c1   Paul Moore   netlabel: Add fun...
12
   * (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008
5778eabd9   Paul Moore   SELinux: extract ...
13
14
15
16
   */
  
  #include <linux/spinlock.h>
  #include <linux/rcupdate.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
17
  #include <linux/gfp.h>
014ab19a6   Paul Moore   selinux: Set sock...
18
19
  #include <linux/ip.h>
  #include <linux/ipv6.h>
5778eabd9   Paul Moore   SELinux: extract ...
20
21
  #include <net/sock.h>
  #include <net/netlabel.h>
014ab19a6   Paul Moore   selinux: Set sock...
22
23
  #include <net/ip.h>
  #include <net/ipv6.h>
5778eabd9   Paul Moore   SELinux: extract ...
24
25
26
  
  #include "objsec.h"
  #include "security.h"
d4ee4231a   Adrian Bunk   selinux: selinux/...
27
  #include "netlabel.h"
5778eabd9   Paul Moore   SELinux: extract ...
28
29
  
  /**
5dbe1eb0c   Paul Moore   SELinux: Allow Ne...
30
31
32
33
34
35
36
37
38
39
40
41
   * selinux_netlbl_sidlookup_cached - Cache a SID lookup
   * @skb: the packet
   * @secattr: the NetLabel security attributes
   * @sid: the SID
   *
   * Description:
   * Query the SELinux security server to lookup the correct SID for the given
   * security attributes.  If the query is successful, cache the result to speed
   * up future lookups.  Returns zero on success, negative values on failure.
   *
   */
  static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
4fee5242b   Huw Davies   calipso: Add a la...
42
  					   u16 family,
5dbe1eb0c   Paul Moore   SELinux: Allow Ne...
43
44
45
46
  					   struct netlbl_lsm_secattr *secattr,
  					   u32 *sid)
  {
  	int rc;
aa8e712ce   Stephen Smalley   selinux: wrap glo...
47
  	rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid);
5dbe1eb0c   Paul Moore   SELinux: Allow Ne...
48
49
50
  	if (rc == 0 &&
  	    (secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
  	    (secattr->flags & NETLBL_SECATTR_CACHE))
4fee5242b   Huw Davies   calipso: Add a la...
51
  		netlbl_cache_add(skb, family, secattr);
5dbe1eb0c   Paul Moore   SELinux: Allow Ne...
52
53
54
55
56
  
  	return rc;
  }
  
  /**
6c5b3fc01   Paul Moore   selinux: Cache Ne...
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
   * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr
   * @sk: the socket
   *
   * Description:
   * Generate the NetLabel security attributes for a socket, making full use of
   * the socket's attribute cache.  Returns a pointer to the security attributes
   * on success, NULL on failure.
   *
   */
  static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
  {
  	int rc;
  	struct sk_security_struct *sksec = sk->sk_security;
  	struct netlbl_lsm_secattr *secattr;
  
  	if (sksec->nlbl_secattr != NULL)
  		return sksec->nlbl_secattr;
  
  	secattr = netlbl_secattr_alloc(GFP_ATOMIC);
  	if (secattr == NULL)
  		return NULL;
aa8e712ce   Stephen Smalley   selinux: wrap glo...
78
79
  	rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid,
  					    secattr);
6c5b3fc01   Paul Moore   selinux: Cache Ne...
80
81
82
83
84
85
86
87
88
89
  	if (rc != 0) {
  		netlbl_secattr_free(secattr);
  		return NULL;
  	}
  	sksec->nlbl_secattr = secattr;
  
  	return secattr;
  }
  
  /**
050d032b2   Paul Moore   selinux: ensure t...
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
   * selinux_netlbl_sock_getattr - Get the cached NetLabel secattr
   * @sk: the socket
   * @sid: the SID
   *
   * Query the socket's cached secattr and if the SID matches the cached value
   * return the cache, otherwise return NULL.
   *
   */
  static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
  							const struct sock *sk,
  							u32 sid)
  {
  	struct sk_security_struct *sksec = sk->sk_security;
  	struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
  
  	if (secattr == NULL)
  		return NULL;
  
  	if ((secattr->flags & NETLBL_SECATTR_SECID) &&
  	    (secattr->attr.secid == sid))
  		return secattr;
  
  	return NULL;
  }
  
  /**
5778eabd9   Paul Moore   SELinux: extract ...
116
117
118
119
120
121
122
123
124
125
126
127
   * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
   *
   * Description:
   * Invalidate the NetLabel security attribute mapping cache.
   *
   */
  void selinux_netlbl_cache_invalidate(void)
  {
  	netlbl_cache_invalidate();
  }
  
  /**
dfaebe982   Paul Moore   selinux: Fix miss...
128
129
130
131
132
133
134
135
136
137
138
139
   * selinux_netlbl_err - Handle a NetLabel packet error
   * @skb: the packet
   * @error: the error code
   * @gateway: true if host is acting as a gateway, false otherwise
   *
   * Description:
   * When a packet is dropped due to a call to avc_has_perm() pass the error
   * code to the NetLabel subsystem so any protocol specific processing can be
   * done.  This is safe to call even if you are unsure if NetLabel labeling is
   * present on the packet, NetLabel is smart enough to only act when it should.
   *
   */
a04e71f63   Huw Davies   netlabel: Pass a ...
140
  void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway)
dfaebe982   Paul Moore   selinux: Fix miss...
141
  {
a04e71f63   Huw Davies   netlabel: Pass a ...
142
  	netlbl_skbuff_err(skb, family, error, gateway);
dfaebe982   Paul Moore   selinux: Fix miss...
143
144
145
  }
  
  /**
6c5b3fc01   Paul Moore   selinux: Cache Ne...
146
   * selinux_netlbl_sk_security_free - Free the NetLabel fields
dd3e7836b   Eric Paris   selinux: always c...
147
   * @sksec: the sk_security_struct
6c5b3fc01   Paul Moore   selinux: Cache Ne...
148
149
150
151
152
   *
   * Description:
   * Free all of the memory in the NetLabel fields of a sk_security_struct.
   *
   */
dd3e7836b   Eric Paris   selinux: always c...
153
  void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec)
6c5b3fc01   Paul Moore   selinux: Cache Ne...
154
  {
dd3e7836b   Eric Paris   selinux: always c...
155
156
  	if (sksec->nlbl_secattr != NULL)
  		netlbl_secattr_free(sksec->nlbl_secattr);
6c5b3fc01   Paul Moore   selinux: Cache Ne...
157
158
159
  }
  
  /**
5778eabd9   Paul Moore   SELinux: extract ...
160
   * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
dd3e7836b   Eric Paris   selinux: always c...
161
   * @sksec: the sk_security_struct
5778eabd9   Paul Moore   SELinux: extract ...
162
163
164
165
   * @family: the socket family
   *
   * Description:
   * Called when the NetLabel state of a sk_security_struct needs to be reset.
25985edce   Lucas De Marchi   Fix common misspe...
166
   * The caller is responsible for all the NetLabel sk_security_struct locking.
5778eabd9   Paul Moore   SELinux: extract ...
167
168
   *
   */
dd3e7836b   Eric Paris   selinux: always c...
169
  void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec)
5778eabd9   Paul Moore   SELinux: extract ...
170
  {
dd3e7836b   Eric Paris   selinux: always c...
171
  	sksec->nlbl_state = NLBL_UNSET;
5778eabd9   Paul Moore   SELinux: extract ...
172
173
174
  }
  
  /**
5778eabd9   Paul Moore   SELinux: extract ...
175
176
   * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
   * @skb: the packet
75e22910c   Paul Moore   NetLabel: Add IP ...
177
   * @family: protocol family
220deb966   Paul Moore   SELinux: Better i...
178
   * @type: NetLabel labeling protocol type
5778eabd9   Paul Moore   SELinux: extract ...
179
180
181
182
183
184
185
186
   * @sid: the SID
   *
   * Description:
   * Call the NetLabel mechanism to get the security attributes of the given
   * packet and use those attributes to determine the correct context/SID to
   * assign to the packet.  Returns zero on success, negative values on failure.
   *
   */
75e22910c   Paul Moore   NetLabel: Add IP ...
187
188
  int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
  				 u16 family,
220deb966   Paul Moore   SELinux: Better i...
189
  				 u32 *type,
75e22910c   Paul Moore   NetLabel: Add IP ...
190
  				 u32 *sid)
5778eabd9   Paul Moore   SELinux: extract ...
191
192
193
  {
  	int rc;
  	struct netlbl_lsm_secattr secattr;
23bcdc1ad   Paul Moore   SELinux: enable d...
194
195
196
197
  	if (!netlbl_enabled()) {
  		*sid = SECSID_NULL;
  		return 0;
  	}
5778eabd9   Paul Moore   SELinux: extract ...
198
  	netlbl_secattr_init(&secattr);
75e22910c   Paul Moore   NetLabel: Add IP ...
199
  	rc = netlbl_skbuff_getattr(skb, family, &secattr);
5dbe1eb0c   Paul Moore   SELinux: Allow Ne...
200
  	if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
4fee5242b   Huw Davies   calipso: Add a la...
201
202
  		rc = selinux_netlbl_sidlookup_cached(skb, family,
  						     &secattr, sid);
5dbe1eb0c   Paul Moore   SELinux: Allow Ne...
203
  	else
5778eabd9   Paul Moore   SELinux: extract ...
204
  		*sid = SECSID_NULL;
220deb966   Paul Moore   SELinux: Better i...
205
  	*type = secattr.type;
5778eabd9   Paul Moore   SELinux: extract ...
206
207
208
209
210
211
  	netlbl_secattr_destroy(&secattr);
  
  	return rc;
  }
  
  /**
948bf85c1   Paul Moore   netlabel: Add fun...
212
213
214
215
216
217
218
   * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid
   * @skb: the packet
   * @family: protocol family
   * @sid: the SID
   *
   * Description
   * Call the NetLabel mechanism to set the label of a packet using @sid.
af901ca18   AndrĂ© Goddard Rosa   tree-wide: fix as...
219
   * Returns zero on success, negative values on failure.
948bf85c1   Paul Moore   netlabel: Add fun...
220
221
222
223
224
225
226
   *
   */
  int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
  				 u16 family,
  				 u32 sid)
  {
  	int rc;
6c5b3fc01   Paul Moore   selinux: Cache Ne...
227
228
  	struct netlbl_lsm_secattr secattr_storage;
  	struct netlbl_lsm_secattr *secattr = NULL;
948bf85c1   Paul Moore   netlabel: Add fun...
229
230
231
232
  	struct sock *sk;
  
  	/* if this is a locally generated packet check to see if it is already
  	 * being labeled by it's parent socket, if it is just exit */
54abc686c   Eric Dumazet   net: add skb_to_f...
233
  	sk = skb_to_full_sk(skb);
948bf85c1   Paul Moore   netlabel: Add fun...
234
235
  	if (sk != NULL) {
  		struct sk_security_struct *sksec = sk->sk_security;
d452930fd   Richard Haines   selinux: Add SCTP...
236

948bf85c1   Paul Moore   netlabel: Add fun...
237
238
  		if (sksec->nlbl_state != NLBL_REQSKB)
  			return 0;
050d032b2   Paul Moore   selinux: ensure t...
239
  		secattr = selinux_netlbl_sock_getattr(sk, sid);
6c5b3fc01   Paul Moore   selinux: Cache Ne...
240
241
242
243
  	}
  	if (secattr == NULL) {
  		secattr = &secattr_storage;
  		netlbl_secattr_init(secattr);
aa8e712ce   Stephen Smalley   selinux: wrap glo...
244
245
  		rc = security_netlbl_sid_to_secattr(&selinux_state, sid,
  						    secattr);
6c5b3fc01   Paul Moore   selinux: Cache Ne...
246
247
  		if (rc != 0)
  			goto skbuff_setsid_return;
948bf85c1   Paul Moore   netlabel: Add fun...
248
  	}
6c5b3fc01   Paul Moore   selinux: Cache Ne...
249
  	rc = netlbl_skbuff_setattr(skb, family, secattr);
948bf85c1   Paul Moore   netlabel: Add fun...
250
251
  
  skbuff_setsid_return:
6c5b3fc01   Paul Moore   selinux: Cache Ne...
252
253
  	if (secattr == &secattr_storage)
  		netlbl_secattr_destroy(secattr);
948bf85c1   Paul Moore   netlabel: Add fun...
254
255
256
257
  	return rc;
  }
  
  /**
d452930fd   Richard Haines   selinux: Add SCTP...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
   * selinux_netlbl_sctp_assoc_request - Label an incoming sctp association.
   * @ep: incoming association endpoint.
   * @skb: the packet.
   *
   * Description:
   * A new incoming connection is represented by @ep, ......
   * Returns zero on success, negative values on failure.
   *
   */
  int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
  				     struct sk_buff *skb)
  {
  	int rc;
  	struct netlbl_lsm_secattr secattr;
  	struct sk_security_struct *sksec = ep->base.sk->sk_security;
d452930fd   Richard Haines   selinux: Add SCTP...
273
  	struct sockaddr_in addr4;
d452930fd   Richard Haines   selinux: Add SCTP...
274
  	struct sockaddr_in6 addr6;
d452930fd   Richard Haines   selinux: Add SCTP...
275
276
277
278
279
280
  
  	if (ep->base.sk->sk_family != PF_INET &&
  				ep->base.sk->sk_family != PF_INET6)
  		return 0;
  
  	netlbl_secattr_init(&secattr);
aa8e712ce   Stephen Smalley   selinux: wrap glo...
281
282
  	rc = security_netlbl_sid_to_secattr(&selinux_state,
  					    ep->secid, &secattr);
d452930fd   Richard Haines   selinux: Add SCTP...
283
284
285
286
287
288
289
290
291
  	if (rc != 0)
  		goto assoc_request_return;
  
  	/* Move skb hdr address info to a struct sockaddr and then call
  	 * netlbl_conn_setattr().
  	 */
  	if (ip_hdr(skb)->version == 4) {
  		addr4.sin_family = AF_INET;
  		addr4.sin_addr.s_addr = ip_hdr(skb)->saddr;
98bbbb76f   Arnd Bergmann   selinux: avoid un...
292
293
  		rc = netlbl_conn_setattr(ep->base.sk, (void *)&addr4, &secattr);
  	} else if (IS_ENABLED(CONFIG_IPV6) && ip_hdr(skb)->version == 6) {
d452930fd   Richard Haines   selinux: Add SCTP...
294
295
  		addr6.sin6_family = AF_INET6;
  		addr6.sin6_addr = ipv6_hdr(skb)->saddr;
98bbbb76f   Arnd Bergmann   selinux: avoid un...
296
297
298
  		rc = netlbl_conn_setattr(ep->base.sk, (void *)&addr6, &secattr);
  	} else {
  		rc = -EAFNOSUPPORT;
d452930fd   Richard Haines   selinux: Add SCTP...
299
  	}
d452930fd   Richard Haines   selinux: Add SCTP...
300
301
302
303
304
305
306
307
308
  	if (rc == 0)
  		sksec->nlbl_state = NLBL_LABELED;
  
  assoc_request_return:
  	netlbl_secattr_destroy(&secattr);
  	return rc;
  }
  
  /**
389fb800a   Paul Moore   netlabel: Label i...
309
310
   * selinux_netlbl_inet_conn_request - Label an incoming stream connection
   * @req: incoming connection request socket
5778eabd9   Paul Moore   SELinux: extract ...
311
312
   *
   * Description:
389fb800a   Paul Moore   netlabel: Label i...
313
314
315
316
   * A new incoming connection request is represented by @req, we need to label
   * the new request_sock here and the stack will ensure the on-the-wire label
   * will get preserved when a full sock is created once the connection handshake
   * is complete.  Returns zero on success, negative values on failure.
5778eabd9   Paul Moore   SELinux: extract ...
317
318
   *
   */
389fb800a   Paul Moore   netlabel: Label i...
319
  int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
5778eabd9   Paul Moore   SELinux: extract ...
320
  {
014ab19a6   Paul Moore   selinux: Set sock...
321
  	int rc;
389fb800a   Paul Moore   netlabel: Label i...
322
  	struct netlbl_lsm_secattr secattr;
014ab19a6   Paul Moore   selinux: Set sock...
323

e1adea927   Huw Davies   calipso: Allow re...
324
  	if (family != PF_INET && family != PF_INET6)
389fb800a   Paul Moore   netlabel: Label i...
325
  		return 0;
014ab19a6   Paul Moore   selinux: Set sock...
326

389fb800a   Paul Moore   netlabel: Label i...
327
  	netlbl_secattr_init(&secattr);
aa8e712ce   Stephen Smalley   selinux: wrap glo...
328
329
  	rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid,
  					    &secattr);
389fb800a   Paul Moore   netlabel: Label i...
330
331
332
333
334
335
  	if (rc != 0)
  		goto inet_conn_request_return;
  	rc = netlbl_req_setattr(req, &secattr);
  inet_conn_request_return:
  	netlbl_secattr_destroy(&secattr);
  	return rc;
5778eabd9   Paul Moore   SELinux: extract ...
336
337
338
  }
  
  /**
389fb800a   Paul Moore   netlabel: Label i...
339
340
   * selinux_netlbl_inet_csk_clone - Initialize the newly created sock
   * @sk: the new sock
5778eabd9   Paul Moore   SELinux: extract ...
341
342
   *
   * Description:
389fb800a   Paul Moore   netlabel: Label i...
343
344
345
   * A new connection has been established using @sk, we've already labeled the
   * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but
   * we need to set the NetLabel state here since we now have a sock structure.
5778eabd9   Paul Moore   SELinux: extract ...
346
347
   *
   */
389fb800a   Paul Moore   netlabel: Label i...
348
  void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
5778eabd9   Paul Moore   SELinux: extract ...
349
  {
389fb800a   Paul Moore   netlabel: Label i...
350
351
352
353
354
355
  	struct sk_security_struct *sksec = sk->sk_security;
  
  	if (family == PF_INET)
  		sksec->nlbl_state = NLBL_LABELED;
  	else
  		sksec->nlbl_state = NLBL_UNSET;
5778eabd9   Paul Moore   SELinux: extract ...
356
357
358
  }
  
  /**
d452930fd   Richard Haines   selinux: Add SCTP...
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
   * selinux_netlbl_sctp_sk_clone - Copy state to the newly created sock
   * @sk: current sock
   * @newsk: the new sock
   *
   * Description:
   * Called whenever a new socket is created by accept(2) or sctp_peeloff(3).
   */
  void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
  {
  	struct sk_security_struct *sksec = sk->sk_security;
  	struct sk_security_struct *newsksec = newsk->sk_security;
  
  	newsksec->nlbl_state = sksec->nlbl_state;
  }
  
  /**
389fb800a   Paul Moore   netlabel: Label i...
375
376
377
   * selinux_netlbl_socket_post_create - Label a socket using NetLabel
   * @sock: the socket to label
   * @family: protocol family
5778eabd9   Paul Moore   SELinux: extract ...
378
379
   *
   * Description:
389fb800a   Paul Moore   netlabel: Label i...
380
381
   * Attempt to label a socket using the NetLabel mechanism using the given
   * SID.  Returns zero values on success, negative values on failure.
5778eabd9   Paul Moore   SELinux: extract ...
382
383
   *
   */
389fb800a   Paul Moore   netlabel: Label i...
384
  int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
5778eabd9   Paul Moore   SELinux: extract ...
385
386
  {
  	int rc;
389fb800a   Paul Moore   netlabel: Label i...
387
388
  	struct sk_security_struct *sksec = sk->sk_security;
  	struct netlbl_lsm_secattr *secattr;
5778eabd9   Paul Moore   SELinux: extract ...
389

ceba1832b   Huw Davies   calipso: Set the ...
390
  	if (family != PF_INET && family != PF_INET6)
5778eabd9   Paul Moore   SELinux: extract ...
391
  		return 0;
f74af6e81   Paul Moore   SELinux: Correct ...
392

389fb800a   Paul Moore   netlabel: Label i...
393
394
395
396
397
398
399
400
401
402
  	secattr = selinux_netlbl_sock_genattr(sk);
  	if (secattr == NULL)
  		return -ENOMEM;
  	rc = netlbl_sock_setattr(sk, family, secattr);
  	switch (rc) {
  	case 0:
  		sksec->nlbl_state = NLBL_LABELED;
  		break;
  	case -EDESTADDRREQ:
  		sksec->nlbl_state = NLBL_REQSKB;
f74af6e81   Paul Moore   SELinux: Correct ...
403
  		rc = 0;
389fb800a   Paul Moore   netlabel: Label i...
404
405
  		break;
  	}
5778eabd9   Paul Moore   SELinux: extract ...
406
407
408
409
410
411
412
413
  
  	return rc;
  }
  
  /**
   * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
   * @sksec: the sock's sk_security_struct
   * @skb: the packet
75e22910c   Paul Moore   NetLabel: Add IP ...
414
   * @family: protocol family
5778eabd9   Paul Moore   SELinux: extract ...
415
416
417
418
419
420
421
422
423
424
   * @ad: the audit data
   *
   * Description:
   * Fetch the NetLabel security attributes from @skb and perform an access check
   * against the receiving socket.  Returns zero on success, negative values on
   * error.
   *
   */
  int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
  				struct sk_buff *skb,
75e22910c   Paul Moore   NetLabel: Add IP ...
425
  				u16 family,
2bf496903   Thomas Liu   SELinux: Convert ...
426
  				struct common_audit_data *ad)
5778eabd9   Paul Moore   SELinux: extract ...
427
428
  {
  	int rc;
f36158c41   Paul Moore   SELinux: use SECI...
429
430
431
  	u32 nlbl_sid;
  	u32 perm;
  	struct netlbl_lsm_secattr secattr;
5778eabd9   Paul Moore   SELinux: extract ...
432

23bcdc1ad   Paul Moore   SELinux: enable d...
433
434
  	if (!netlbl_enabled())
  		return 0;
f36158c41   Paul Moore   SELinux: use SECI...
435
  	netlbl_secattr_init(&secattr);
75e22910c   Paul Moore   NetLabel: Add IP ...
436
  	rc = netlbl_skbuff_getattr(skb, family, &secattr);
5dbe1eb0c   Paul Moore   SELinux: Allow Ne...
437
  	if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
4fee5242b   Huw Davies   calipso: Add a la...
438
439
  		rc = selinux_netlbl_sidlookup_cached(skb, family,
  						     &secattr, &nlbl_sid);
5dbe1eb0c   Paul Moore   SELinux: Allow Ne...
440
  	else
f36158c41   Paul Moore   SELinux: use SECI...
441
442
  		nlbl_sid = SECINITSID_UNLABELED;
  	netlbl_secattr_destroy(&secattr);
5778eabd9   Paul Moore   SELinux: extract ...
443
444
  	if (rc != 0)
  		return rc;
8d9107e8c   Linus Torvalds   Revert "SELinux: ...
445

5778eabd9   Paul Moore   SELinux: extract ...
446
447
  	switch (sksec->sclass) {
  	case SECCLASS_UDP_SOCKET:
f36158c41   Paul Moore   SELinux: use SECI...
448
  		perm = UDP_SOCKET__RECVFROM;
5778eabd9   Paul Moore   SELinux: extract ...
449
450
  		break;
  	case SECCLASS_TCP_SOCKET:
f36158c41   Paul Moore   SELinux: use SECI...
451
  		perm = TCP_SOCKET__RECVFROM;
5778eabd9   Paul Moore   SELinux: extract ...
452
453
  		break;
  	default:
f36158c41   Paul Moore   SELinux: use SECI...
454
  		perm = RAWIP_SOCKET__RECVFROM;
5778eabd9   Paul Moore   SELinux: extract ...
455
  	}
6b6bc6205   Stephen Smalley   selinux: wrap AVC...
456
457
  	rc = avc_has_perm(&selinux_state,
  			  sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
5778eabd9   Paul Moore   SELinux: extract ...
458
459
  	if (rc == 0)
  		return 0;
f36158c41   Paul Moore   SELinux: use SECI...
460
  	if (nlbl_sid != SECINITSID_UNLABELED)
a04e71f63   Huw Davies   netlabel: Pass a ...
461
  		netlbl_skbuff_err(skb, family, rc, 0);
5778eabd9   Paul Moore   SELinux: extract ...
462
463
464
465
  	return rc;
  }
  
  /**
1f440c99d   Huw Davies   netlabel: Prevent...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
   * selinux_netlbl_option - Is this a NetLabel option
   * @level: the socket level or protocol
   * @optname: the socket option name
   *
   * Description:
   * Returns true if @level and @optname refer to a NetLabel option.
   * Helper for selinux_netlbl_socket_setsockopt().
   */
  static inline int selinux_netlbl_option(int level, int optname)
  {
  	return (level == IPPROTO_IP && optname == IP_OPTIONS) ||
  		(level == IPPROTO_IPV6 && optname == IPV6_HOPOPTS);
  }
  
  /**
5778eabd9   Paul Moore   SELinux: extract ...
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
   * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
   * @sock: the socket
   * @level: the socket level or protocol
   * @optname: the socket option name
   *
   * Description:
   * Check the setsockopt() call and if the user is trying to replace the IP
   * options on a socket and a NetLabel is in place for the socket deny the
   * access; otherwise allow the access.  Returns zero when the access is
   * allowed, -EACCES when denied, and other negative values on error.
   *
   */
  int selinux_netlbl_socket_setsockopt(struct socket *sock,
  				     int level,
  				     int optname)
  {
  	int rc = 0;
ba6ff9f2b   Paul Moore   [NetLabel]: conso...
498
499
  	struct sock *sk = sock->sk;
  	struct sk_security_struct *sksec = sk->sk_security;
5778eabd9   Paul Moore   SELinux: extract ...
500
  	struct netlbl_lsm_secattr secattr;
1f440c99d   Huw Davies   netlabel: Prevent...
501
  	if (selinux_netlbl_option(level, optname) &&
014ab19a6   Paul Moore   selinux: Set sock...
502
503
  	    (sksec->nlbl_state == NLBL_LABELED ||
  	     sksec->nlbl_state == NLBL_CONNLABELED)) {
5778eabd9   Paul Moore   SELinux: extract ...
504
  		netlbl_secattr_init(&secattr);
ba6ff9f2b   Paul Moore   [NetLabel]: conso...
505
  		lock_sock(sk);
050d032b2   Paul Moore   selinux: ensure t...
506
507
508
  		/* call the netlabel function directly as we want to see the
  		 * on-the-wire label that is assigned via the socket's options
  		 * and not the cached netlabel/lsm attributes */
ba6ff9f2b   Paul Moore   [NetLabel]: conso...
509
510
  		rc = netlbl_sock_getattr(sk, &secattr);
  		release_sock(sk);
09c50b4a5   Paul Moore   selinux: Fix the ...
511
  		if (rc == 0)
5778eabd9   Paul Moore   SELinux: extract ...
512
  			rc = -EACCES;
09c50b4a5   Paul Moore   selinux: Fix the ...
513
514
  		else if (rc == -ENOMSG)
  			rc = 0;
5778eabd9   Paul Moore   SELinux: extract ...
515
516
  		netlbl_secattr_destroy(&secattr);
  	}
5778eabd9   Paul Moore   SELinux: extract ...
517
518
519
  
  	return rc;
  }
014ab19a6   Paul Moore   selinux: Set sock...
520
521
  
  /**
d452930fd   Richard Haines   selinux: Add SCTP...
522
523
   * selinux_netlbl_socket_connect_helper - Help label a client-side socket on
   * connect
014ab19a6   Paul Moore   selinux: Set sock...
524
525
526
527
528
529
530
531
   * @sk: the socket to label
   * @addr: the destination address
   *
   * Description:
   * Attempt to label a connected socket with NetLabel using the given address.
   * Returns zero values on success, negative values on failure.
   *
   */
d452930fd   Richard Haines   selinux: Add SCTP...
532
533
  static int selinux_netlbl_socket_connect_helper(struct sock *sk,
  						struct sockaddr *addr)
014ab19a6   Paul Moore   selinux: Set sock...
534
535
536
  {
  	int rc;
  	struct sk_security_struct *sksec = sk->sk_security;
6c5b3fc01   Paul Moore   selinux: Cache Ne...
537
  	struct netlbl_lsm_secattr *secattr;
014ab19a6   Paul Moore   selinux: Set sock...
538

014ab19a6   Paul Moore   selinux: Set sock...
539
540
541
542
543
544
545
  	/* connected sockets are allowed to disconnect when the address family
  	 * is set to AF_UNSPEC, if that is what is happening we want to reset
  	 * the socket */
  	if (addr->sa_family == AF_UNSPEC) {
  		netlbl_sock_delattr(sk);
  		sksec->nlbl_state = NLBL_REQSKB;
  		rc = 0;
d452930fd   Richard Haines   selinux: Add SCTP...
546
  		return rc;
014ab19a6   Paul Moore   selinux: Set sock...
547
  	}
6c5b3fc01   Paul Moore   selinux: Cache Ne...
548
549
550
  	secattr = selinux_netlbl_sock_genattr(sk);
  	if (secattr == NULL) {
  		rc = -ENOMEM;
d452930fd   Richard Haines   selinux: Add SCTP...
551
  		return rc;
6c5b3fc01   Paul Moore   selinux: Cache Ne...
552
553
554
555
  	}
  	rc = netlbl_conn_setattr(sk, addr, secattr);
  	if (rc == 0)
  		sksec->nlbl_state = NLBL_CONNLABELED;
014ab19a6   Paul Moore   selinux: Set sock...
556

d452930fd   Richard Haines   selinux: Add SCTP...
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
  	return rc;
  }
  
  /**
   * selinux_netlbl_socket_connect_locked - Label a client-side socket on
   * connect
   * @sk: the socket to label
   * @addr: the destination address
   *
   * Description:
   * Attempt to label a connected socket that already has the socket locked
   * with NetLabel using the given address.
   * Returns zero values on success, negative values on failure.
   *
   */
  int selinux_netlbl_socket_connect_locked(struct sock *sk,
  					 struct sockaddr *addr)
  {
  	struct sk_security_struct *sksec = sk->sk_security;
  
  	if (sksec->nlbl_state != NLBL_REQSKB &&
  	    sksec->nlbl_state != NLBL_CONNLABELED)
  		return 0;
  
  	return selinux_netlbl_socket_connect_helper(sk, addr);
  }
  
  /**
   * selinux_netlbl_socket_connect - Label a client-side socket on connect
   * @sk: the socket to label
   * @addr: the destination address
   *
   * Description:
   * Attempt to label a connected socket with NetLabel using the given address.
   * Returns zero values on success, negative values on failure.
   *
   */
  int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
  {
  	int rc;
  
  	lock_sock(sk);
  	rc = selinux_netlbl_socket_connect_locked(sk, addr);
42d64e1ad   Paul Moore   selinux: correct ...
600
  	release_sock(sk);
d452930fd   Richard Haines   selinux: Add SCTP...
601

014ab19a6   Paul Moore   selinux: Set sock...
602
603
  	return rc;
  }