Deleted Added
full compact
mac_socket.c (165469) mac_socket.c (168955)
1/*-
2 * Copyright (c) 1999-2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
5 * Copyright (c) 2005 SPARTA, Inc.
6 * All rights reserved.
7 *
8 * This software was developed by Robert Watson and Ilmar Habibulin for the
9 * TrustedBSD Project.
10 *
11 * This software was developed for the FreeBSD Project in part by McAfee
12 * Research, the Technology Research Division of Network Associates, Inc.
13 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
14 * DARPA CHATS research program.
15 *
16 * This software was enhanced by SPARTA ISSO under SPAWAR contract
17 * N66001-04-C-6019 ("SEFOS").
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 */
40
41#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1999-2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
5 * Copyright (c) 2005 SPARTA, Inc.
6 * All rights reserved.
7 *
8 * This software was developed by Robert Watson and Ilmar Habibulin for the
9 * TrustedBSD Project.
10 *
11 * This software was developed for the FreeBSD Project in part by McAfee
12 * Research, the Technology Research Division of Network Associates, Inc.
13 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
14 * DARPA CHATS research program.
15 *
16 * This software was enhanced by SPARTA ISSO under SPAWAR contract
17 * N66001-04-C-6019 ("SEFOS").
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/sys/security/mac/mac_socket.c 165469 2006-12-22 23:34:47Z rwatson $");
42__FBSDID("$FreeBSD: head/sys/security/mac/mac_socket.c 168955 2007-04-22 19:55:56Z rwatson $");
43
44#include "opt_mac.h"
45
46#include <sys/param.h>
47#include <sys/kernel.h>
48#include <sys/lock.h>
49#include <sys/malloc.h>
50#include <sys/mutex.h>
51#include <sys/mac.h>
52#include <sys/sbuf.h>
53#include <sys/systm.h>
54#include <sys/mount.h>
55#include <sys/file.h>
56#include <sys/namei.h>
57#include <sys/protosw.h>
58#include <sys/socket.h>
59#include <sys/socketvar.h>
60#include <sys/sysctl.h>
61
62#include <net/bpfdesc.h>
63#include <net/if.h>
64#include <net/if_var.h>
65
66#include <netinet/in.h>
67#include <netinet/in_pcb.h>
68#include <netinet/ip_var.h>
69
70#include <security/mac/mac_framework.h>
71#include <security/mac/mac_internal.h>
72#include <security/mac/mac_policy.h>
73
74/*
75 * Currently, sockets hold two labels: the label of the socket itself, and a
76 * peer label, which may be used by policies to hold a copy of the label of
77 * any remote endpoint.
78 *
79 * Possibly, this peer label should be maintained at the protocol layer
80 * (inpcb, unpcb, etc), as this would allow protocol-aware code to maintain
81 * the label consistently. For example, it might be copied live from a
82 * remote socket for UNIX domain sockets rather than keeping a local copy on
83 * this endpoint, but be cached and updated based on packets received for
84 * TCP/IP.
85 */
86
87struct label *
88mac_socket_label_alloc(int flag)
89{
90 struct label *label;
91 int error;
92
93 label = mac_labelzone_alloc(flag);
94 if (label == NULL)
95 return (NULL);
96
97 MAC_CHECK(init_socket_label, label, flag);
98 if (error) {
99 MAC_PERFORM(destroy_socket_label, label);
100 mac_labelzone_free(label);
101 return (NULL);
102 }
103 return (label);
104}
105
106static struct label *
107mac_socket_peer_label_alloc(int flag)
108{
109 struct label *label;
110 int error;
111
112 label = mac_labelzone_alloc(flag);
113 if (label == NULL)
114 return (NULL);
115
116 MAC_CHECK(init_socket_peer_label, label, flag);
117 if (error) {
118 MAC_PERFORM(destroy_socket_peer_label, label);
119 mac_labelzone_free(label);
120 return (NULL);
121 }
122 return (label);
123}
124
125int
126mac_init_socket(struct socket *so, int flag)
127{
128
129 so->so_label = mac_socket_label_alloc(flag);
130 if (so->so_label == NULL)
131 return (ENOMEM);
132 so->so_peerlabel = mac_socket_peer_label_alloc(flag);
133 if (so->so_peerlabel == NULL) {
134 mac_socket_label_free(so->so_label);
135 so->so_label = NULL;
136 return (ENOMEM);
137 }
138 return (0);
139}
140
141void
142mac_socket_label_free(struct label *label)
143{
144
145 MAC_PERFORM(destroy_socket_label, label);
146 mac_labelzone_free(label);
147}
148
149static void
150mac_socket_peer_label_free(struct label *label)
151{
152
153 MAC_PERFORM(destroy_socket_peer_label, label);
154 mac_labelzone_free(label);
155}
156
157void
43
44#include "opt_mac.h"
45
46#include <sys/param.h>
47#include <sys/kernel.h>
48#include <sys/lock.h>
49#include <sys/malloc.h>
50#include <sys/mutex.h>
51#include <sys/mac.h>
52#include <sys/sbuf.h>
53#include <sys/systm.h>
54#include <sys/mount.h>
55#include <sys/file.h>
56#include <sys/namei.h>
57#include <sys/protosw.h>
58#include <sys/socket.h>
59#include <sys/socketvar.h>
60#include <sys/sysctl.h>
61
62#include <net/bpfdesc.h>
63#include <net/if.h>
64#include <net/if_var.h>
65
66#include <netinet/in.h>
67#include <netinet/in_pcb.h>
68#include <netinet/ip_var.h>
69
70#include <security/mac/mac_framework.h>
71#include <security/mac/mac_internal.h>
72#include <security/mac/mac_policy.h>
73
74/*
75 * Currently, sockets hold two labels: the label of the socket itself, and a
76 * peer label, which may be used by policies to hold a copy of the label of
77 * any remote endpoint.
78 *
79 * Possibly, this peer label should be maintained at the protocol layer
80 * (inpcb, unpcb, etc), as this would allow protocol-aware code to maintain
81 * the label consistently. For example, it might be copied live from a
82 * remote socket for UNIX domain sockets rather than keeping a local copy on
83 * this endpoint, but be cached and updated based on packets received for
84 * TCP/IP.
85 */
86
87struct label *
88mac_socket_label_alloc(int flag)
89{
90 struct label *label;
91 int error;
92
93 label = mac_labelzone_alloc(flag);
94 if (label == NULL)
95 return (NULL);
96
97 MAC_CHECK(init_socket_label, label, flag);
98 if (error) {
99 MAC_PERFORM(destroy_socket_label, label);
100 mac_labelzone_free(label);
101 return (NULL);
102 }
103 return (label);
104}
105
106static struct label *
107mac_socket_peer_label_alloc(int flag)
108{
109 struct label *label;
110 int error;
111
112 label = mac_labelzone_alloc(flag);
113 if (label == NULL)
114 return (NULL);
115
116 MAC_CHECK(init_socket_peer_label, label, flag);
117 if (error) {
118 MAC_PERFORM(destroy_socket_peer_label, label);
119 mac_labelzone_free(label);
120 return (NULL);
121 }
122 return (label);
123}
124
125int
126mac_init_socket(struct socket *so, int flag)
127{
128
129 so->so_label = mac_socket_label_alloc(flag);
130 if (so->so_label == NULL)
131 return (ENOMEM);
132 so->so_peerlabel = mac_socket_peer_label_alloc(flag);
133 if (so->so_peerlabel == NULL) {
134 mac_socket_label_free(so->so_label);
135 so->so_label = NULL;
136 return (ENOMEM);
137 }
138 return (0);
139}
140
141void
142mac_socket_label_free(struct label *label)
143{
144
145 MAC_PERFORM(destroy_socket_label, label);
146 mac_labelzone_free(label);
147}
148
149static void
150mac_socket_peer_label_free(struct label *label)
151{
152
153 MAC_PERFORM(destroy_socket_peer_label, label);
154 mac_labelzone_free(label);
155}
156
157void
158mac_destroy_socket(struct socket *socket)
158mac_destroy_socket(struct socket *so)
159{
160
159{
160
161 mac_socket_label_free(socket->so_label);
162 socket->so_label = NULL;
163 mac_socket_peer_label_free(socket->so_peerlabel);
164 socket->so_peerlabel = NULL;
161 mac_socket_label_free(so->so_label);
162 so->so_label = NULL;
163 mac_socket_peer_label_free(so->so_peerlabel);
164 so->so_peerlabel = NULL;
165}
166
167void
168mac_copy_socket_label(struct label *src, struct label *dest)
169{
170
171 MAC_PERFORM(copy_socket_label, src, dest);
172}
173
174int
175mac_externalize_socket_label(struct label *label, char *elements,
176 char *outbuf, size_t outbuflen)
177{
178 int error;
179
180 MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
181
182 return (error);
183}
184
185static int
186mac_externalize_socket_peer_label(struct label *label, char *elements,
187 char *outbuf, size_t outbuflen)
188{
189 int error;
190
191 MAC_EXTERNALIZE(socket_peer, label, elements, outbuf, outbuflen);
192
193 return (error);
194}
195
196int
197mac_internalize_socket_label(struct label *label, char *string)
198{
199 int error;
200
201 MAC_INTERNALIZE(socket, label, string);
202
203 return (error);
204}
205
206void
165}
166
167void
168mac_copy_socket_label(struct label *src, struct label *dest)
169{
170
171 MAC_PERFORM(copy_socket_label, src, dest);
172}
173
174int
175mac_externalize_socket_label(struct label *label, char *elements,
176 char *outbuf, size_t outbuflen)
177{
178 int error;
179
180 MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
181
182 return (error);
183}
184
185static int
186mac_externalize_socket_peer_label(struct label *label, char *elements,
187 char *outbuf, size_t outbuflen)
188{
189 int error;
190
191 MAC_EXTERNALIZE(socket_peer, label, elements, outbuf, outbuflen);
192
193 return (error);
194}
195
196int
197mac_internalize_socket_label(struct label *label, char *string)
198{
199 int error;
200
201 MAC_INTERNALIZE(socket, label, string);
202
203 return (error);
204}
205
206void
207mac_create_socket(struct ucred *cred, struct socket *socket)
207mac_create_socket(struct ucred *cred, struct socket *so)
208{
209
208{
209
210 MAC_PERFORM(create_socket, cred, socket, socket->so_label);
210 MAC_PERFORM(create_socket, cred, so, so->so_label);
211}
212
213void
211}
212
213void
214mac_create_socket_from_socket(struct socket *oldsocket,
215 struct socket *newsocket)
214mac_create_socket_from_socket(struct socket *oldso, struct socket *newso)
216{
217
215{
216
218 SOCK_LOCK_ASSERT(oldsocket);
219 MAC_PERFORM(create_socket_from_socket, oldsocket, oldsocket->so_label,
220 newsocket, newsocket->so_label);
217 SOCK_LOCK_ASSERT(oldso);
218
219 MAC_PERFORM(create_socket_from_socket, oldso, oldso->so_label, newso,
220 newso->so_label);
221}
222
223static void
221}
222
223static void
224mac_relabel_socket(struct ucred *cred, struct socket *socket,
224mac_relabel_socket(struct ucred *cred, struct socket *so,
225 struct label *newlabel)
226{
227
225 struct label *newlabel)
226{
227
228 SOCK_LOCK_ASSERT(socket);
229 MAC_PERFORM(relabel_socket, cred, socket, socket->so_label, newlabel);
228 SOCK_LOCK_ASSERT(so);
229
230 MAC_PERFORM(relabel_socket, cred, so, so->so_label, newlabel);
230}
231
232void
231}
232
233void
233mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
234mac_set_socket_peer_from_mbuf(struct mbuf *m, struct socket *so)
234{
235 struct label *label;
236
235{
236 struct label *label;
237
237 SOCK_LOCK_ASSERT(socket);
238 SOCK_LOCK_ASSERT(so);
238
239
239 label = mac_mbuf_to_label(mbuf);
240 label = mac_mbuf_to_label(m);
240
241
241 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
242 socket->so_peerlabel);
242 MAC_PERFORM(set_socket_peer_from_mbuf, m, label, so,
243 so->so_peerlabel);
243}
244
245void
244}
245
246void
246mac_set_socket_peer_from_socket(struct socket *oldsocket,
247 struct socket *newsocket)
247mac_set_socket_peer_from_socket(struct socket *oldso, struct socket *newso)
248{
249
250 /*
251 * XXXRW: only hold the socket lock on one at a time, as one socket
252 * is the original, and one is the new. However, it's called in both
253 * directions, so we can't assert the lock here currently.
254 */
248{
249
250 /*
251 * XXXRW: only hold the socket lock on one at a time, as one socket
252 * is the original, and one is the new. However, it's called in both
253 * directions, so we can't assert the lock here currently.
254 */
255 MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
256 oldsocket->so_label, newsocket, newsocket->so_peerlabel);
255 MAC_PERFORM(set_socket_peer_from_socket, oldso, oldso->so_label,
256 newso, newso->so_peerlabel);
257}
258
259void
257}
258
259void
260mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
260mac_create_mbuf_from_socket(struct socket *so, struct mbuf *m)
261{
262 struct label *label;
263
261{
262 struct label *label;
263
264 label = mac_mbuf_to_label(mbuf);
264 SOCK_LOCK_ASSERT(so);
265
265
266 SOCK_LOCK_ASSERT(socket);
267 MAC_PERFORM(create_mbuf_from_socket, socket, socket->so_label, mbuf,
268 label);
266 label = mac_mbuf_to_label(m);
267
268 MAC_PERFORM(create_mbuf_from_socket, so, so->so_label, m, label);
269}
270
271int
269}
270
271int
272mac_check_socket_accept(struct ucred *cred, struct socket *socket)
272mac_check_socket_accept(struct ucred *cred, struct socket *so)
273{
274 int error;
275
273{
274 int error;
275
276 SOCK_LOCK_ASSERT(socket);
276 SOCK_LOCK_ASSERT(so);
277
277
278 MAC_CHECK(check_socket_accept, cred, socket, socket->so_label);
278 MAC_CHECK(check_socket_accept, cred, so, so->so_label);
279
280 return (error);
281}
282
283int
279
280 return (error);
281}
282
283int
284mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
285 struct sockaddr *sockaddr)
284mac_check_socket_bind(struct ucred *ucred, struct socket *so,
285 struct sockaddr *sa)
286{
287 int error;
288
286{
287 int error;
288
289 SOCK_LOCK_ASSERT(socket);
289 SOCK_LOCK_ASSERT(so);
290
290
291 MAC_CHECK(check_socket_bind, ucred, socket, socket->so_label,
292 sockaddr);
291 MAC_CHECK(check_socket_bind, ucred, so, so->so_label, sa);
293
294 return (error);
295}
296
297int
292
293 return (error);
294}
295
296int
298mac_check_socket_connect(struct ucred *cred, struct socket *socket,
299 struct sockaddr *sockaddr)
297mac_check_socket_connect(struct ucred *cred, struct socket *so,
298 struct sockaddr *sa)
300{
301 int error;
302
299{
300 int error;
301
303 SOCK_LOCK_ASSERT(socket);
302 SOCK_LOCK_ASSERT(so);
304
303
305 MAC_CHECK(check_socket_connect, cred, socket, socket->so_label,
306 sockaddr);
304 MAC_CHECK(check_socket_connect, cred, so, so->so_label, sa);
307
308 return (error);
309}
310
311int
305
306 return (error);
307}
308
309int
312mac_check_socket_create(struct ucred *cred, int domain, int type,
313 int protocol)
310mac_check_socket_create(struct ucred *cred, int domain, int type, int proto)
314{
315 int error;
316
311{
312 int error;
313
317 MAC_CHECK(check_socket_create, cred, domain, type, protocol);
314 MAC_CHECK(check_socket_create, cred, domain, type, proto);
318
319 return (error);
320}
321
322int
315
316 return (error);
317}
318
319int
323mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
320mac_check_socket_deliver(struct socket *so, struct mbuf *m)
324{
325 struct label *label;
326 int error;
327
321{
322 struct label *label;
323 int error;
324
328 SOCK_LOCK_ASSERT(socket);
325 SOCK_LOCK_ASSERT(so);
329
326
330 label = mac_mbuf_to_label(mbuf);
327 label = mac_mbuf_to_label(m);
331
328
332 MAC_CHECK(check_socket_deliver, socket, socket->so_label, mbuf,
333 label);
329 MAC_CHECK(check_socket_deliver, so, so->so_label, m, label);
334
335 return (error);
336}
337
338int
330
331 return (error);
332}
333
334int
339mac_check_socket_listen(struct ucred *cred, struct socket *socket)
335mac_check_socket_listen(struct ucred *cred, struct socket *so)
340{
341 int error;
342
336{
337 int error;
338
343 SOCK_LOCK_ASSERT(socket);
339 SOCK_LOCK_ASSERT(so);
344
340
345 MAC_CHECK(check_socket_listen, cred, socket, socket->so_label);
341 MAC_CHECK(check_socket_listen, cred, so, so->so_label);
342
346 return (error);
347}
348
349int
350mac_check_socket_poll(struct ucred *cred, struct socket *so)
351{
352 int error;
353
354 SOCK_LOCK_ASSERT(so);
355
356 MAC_CHECK(check_socket_poll, cred, so, so->so_label);
343 return (error);
344}
345
346int
347mac_check_socket_poll(struct ucred *cred, struct socket *so)
348{
349 int error;
350
351 SOCK_LOCK_ASSERT(so);
352
353 MAC_CHECK(check_socket_poll, cred, so, so->so_label);
354
357 return (error);
358}
359
360int
361mac_check_socket_receive(struct ucred *cred, struct socket *so)
362{
363 int error;
364
365 SOCK_LOCK_ASSERT(so);
366
367 MAC_CHECK(check_socket_receive, cred, so, so->so_label);
368
369 return (error);
370}
371
372static int
355 return (error);
356}
357
358int
359mac_check_socket_receive(struct ucred *cred, struct socket *so)
360{
361 int error;
362
363 SOCK_LOCK_ASSERT(so);
364
365 MAC_CHECK(check_socket_receive, cred, so, so->so_label);
366
367 return (error);
368}
369
370static int
373mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
371mac_check_socket_relabel(struct ucred *cred, struct socket *so,
374 struct label *newlabel)
375{
376 int error;
377
372 struct label *newlabel)
373{
374 int error;
375
378 SOCK_LOCK_ASSERT(socket);
376 SOCK_LOCK_ASSERT(so);
379
377
380 MAC_CHECK(check_socket_relabel, cred, socket, socket->so_label,
381 newlabel);
378 MAC_CHECK(check_socket_relabel, cred, so, so->so_label, newlabel);
382
383 return (error);
384}
385
386int
387mac_check_socket_send(struct ucred *cred, struct socket *so)
388{
389 int error;
390
391 SOCK_LOCK_ASSERT(so);
392
393 MAC_CHECK(check_socket_send, cred, so, so->so_label);
394
395 return (error);
396}
397
398int
399mac_check_socket_stat(struct ucred *cred, struct socket *so)
400{
401 int error;
402
403 SOCK_LOCK_ASSERT(so);
404
405 MAC_CHECK(check_socket_stat, cred, so, so->so_label);
406
407 return (error);
408}
409
410int
379
380 return (error);
381}
382
383int
384mac_check_socket_send(struct ucred *cred, struct socket *so)
385{
386 int error;
387
388 SOCK_LOCK_ASSERT(so);
389
390 MAC_CHECK(check_socket_send, cred, so, so->so_label);
391
392 return (error);
393}
394
395int
396mac_check_socket_stat(struct ucred *cred, struct socket *so)
397{
398 int error;
399
400 SOCK_LOCK_ASSERT(so);
401
402 MAC_CHECK(check_socket_stat, cred, so, so->so_label);
403
404 return (error);
405}
406
407int
411mac_check_socket_visible(struct ucred *cred, struct socket *socket)
408mac_check_socket_visible(struct ucred *cred, struct socket *so)
412{
413 int error;
414
409{
410 int error;
411
415 SOCK_LOCK_ASSERT(socket);
412 SOCK_LOCK_ASSERT(so);
416
413
417 MAC_CHECK(check_socket_visible, cred, socket, socket->so_label);
414 MAC_CHECK(check_socket_visible, cred, so, so->so_label);
418
419 return (error);
420}
421
422int
423mac_socket_label_set(struct ucred *cred, struct socket *so,
424 struct label *label)
425{
426 int error;
427
428 /*
429 * We acquire the socket lock when we perform the test and set, but
430 * have to release it as the pcb code needs to acquire the pcb lock,
431 * which will precede the socket lock in the lock order. However,
432 * this is fine, as any race will simply result in the inpcb being
433 * refreshed twice, but still consistently, as the inpcb code will
434 * acquire the socket lock before refreshing, holding both locks.
435 */
436 SOCK_LOCK(so);
437 error = mac_check_socket_relabel(cred, so, label);
438 if (error) {
439 SOCK_UNLOCK(so);
440 return (error);
441 }
442
443 mac_relabel_socket(cred, so, label);
444 SOCK_UNLOCK(so);
445
446 /*
447 * If the protocol has expressed interest in socket layer changes,
448 * such as if it needs to propagate changes to a cached pcb label
449 * from the socket, notify it of the label change while holding the
450 * socket lock.
451 */
452 if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL)
453 (so->so_proto->pr_usrreqs->pru_sosetlabel)(so);
454
455 return (0);
456}
457
458int
459mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
460{
461 struct label *intlabel;
462 char *buffer;
463 int error;
464
465 error = mac_check_structmac_consistent(mac);
466 if (error)
467 return (error);
468
469 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
470 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
471 if (error) {
472 free(buffer, M_MACTEMP);
473 return (error);
474 }
475
476 intlabel = mac_socket_label_alloc(M_WAITOK);
477 error = mac_internalize_socket_label(intlabel, buffer);
478 free(buffer, M_MACTEMP);
479 if (error)
480 goto out;
481
482 error = mac_socket_label_set(cred, so, intlabel);
483out:
484 mac_socket_label_free(intlabel);
485 return (error);
486}
487
488int
489mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
490{
491 char *buffer, *elements;
492 struct label *intlabel;
493 int error;
494
495 error = mac_check_structmac_consistent(mac);
496 if (error)
497 return (error);
498
499 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
500 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
501 if (error) {
502 free(elements, M_MACTEMP);
503 return (error);
504 }
505
506 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
507 intlabel = mac_socket_label_alloc(M_WAITOK);
508 SOCK_LOCK(so);
509 mac_copy_socket_label(so->so_label, intlabel);
510 SOCK_UNLOCK(so);
511 error = mac_externalize_socket_label(intlabel, elements, buffer,
512 mac->m_buflen);
513 mac_socket_label_free(intlabel);
514 if (error == 0)
515 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
516
517 free(buffer, M_MACTEMP);
518 free(elements, M_MACTEMP);
519
520 return (error);
521}
522
523int
524mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so,
525 struct mac *mac)
526{
527 char *elements, *buffer;
528 struct label *intlabel;
529 int error;
530
531 error = mac_check_structmac_consistent(mac);
532 if (error)
533 return (error);
534
535 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
536 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
537 if (error) {
538 free(elements, M_MACTEMP);
539 return (error);
540 }
541
542 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
543 intlabel = mac_socket_label_alloc(M_WAITOK);
544 SOCK_LOCK(so);
545 mac_copy_socket_label(so->so_peerlabel, intlabel);
546 SOCK_UNLOCK(so);
547 error = mac_externalize_socket_peer_label(intlabel, elements, buffer,
548 mac->m_buflen);
549 mac_socket_label_free(intlabel);
550 if (error == 0)
551 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
552
553 free(buffer, M_MACTEMP);
554 free(elements, M_MACTEMP);
555
556 return (error);
557}
415
416 return (error);
417}
418
419int
420mac_socket_label_set(struct ucred *cred, struct socket *so,
421 struct label *label)
422{
423 int error;
424
425 /*
426 * We acquire the socket lock when we perform the test and set, but
427 * have to release it as the pcb code needs to acquire the pcb lock,
428 * which will precede the socket lock in the lock order. However,
429 * this is fine, as any race will simply result in the inpcb being
430 * refreshed twice, but still consistently, as the inpcb code will
431 * acquire the socket lock before refreshing, holding both locks.
432 */
433 SOCK_LOCK(so);
434 error = mac_check_socket_relabel(cred, so, label);
435 if (error) {
436 SOCK_UNLOCK(so);
437 return (error);
438 }
439
440 mac_relabel_socket(cred, so, label);
441 SOCK_UNLOCK(so);
442
443 /*
444 * If the protocol has expressed interest in socket layer changes,
445 * such as if it needs to propagate changes to a cached pcb label
446 * from the socket, notify it of the label change while holding the
447 * socket lock.
448 */
449 if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL)
450 (so->so_proto->pr_usrreqs->pru_sosetlabel)(so);
451
452 return (0);
453}
454
455int
456mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
457{
458 struct label *intlabel;
459 char *buffer;
460 int error;
461
462 error = mac_check_structmac_consistent(mac);
463 if (error)
464 return (error);
465
466 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
467 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
468 if (error) {
469 free(buffer, M_MACTEMP);
470 return (error);
471 }
472
473 intlabel = mac_socket_label_alloc(M_WAITOK);
474 error = mac_internalize_socket_label(intlabel, buffer);
475 free(buffer, M_MACTEMP);
476 if (error)
477 goto out;
478
479 error = mac_socket_label_set(cred, so, intlabel);
480out:
481 mac_socket_label_free(intlabel);
482 return (error);
483}
484
485int
486mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
487{
488 char *buffer, *elements;
489 struct label *intlabel;
490 int error;
491
492 error = mac_check_structmac_consistent(mac);
493 if (error)
494 return (error);
495
496 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
497 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
498 if (error) {
499 free(elements, M_MACTEMP);
500 return (error);
501 }
502
503 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
504 intlabel = mac_socket_label_alloc(M_WAITOK);
505 SOCK_LOCK(so);
506 mac_copy_socket_label(so->so_label, intlabel);
507 SOCK_UNLOCK(so);
508 error = mac_externalize_socket_label(intlabel, elements, buffer,
509 mac->m_buflen);
510 mac_socket_label_free(intlabel);
511 if (error == 0)
512 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
513
514 free(buffer, M_MACTEMP);
515 free(elements, M_MACTEMP);
516
517 return (error);
518}
519
520int
521mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so,
522 struct mac *mac)
523{
524 char *elements, *buffer;
525 struct label *intlabel;
526 int error;
527
528 error = mac_check_structmac_consistent(mac);
529 if (error)
530 return (error);
531
532 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
533 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
534 if (error) {
535 free(elements, M_MACTEMP);
536 return (error);
537 }
538
539 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
540 intlabel = mac_socket_label_alloc(M_WAITOK);
541 SOCK_LOCK(so);
542 mac_copy_socket_label(so->so_peerlabel, intlabel);
543 SOCK_UNLOCK(so);
544 error = mac_externalize_socket_peer_label(intlabel, elements, buffer,
545 mac->m_buflen);
546 mac_socket_label_free(intlabel);
547 if (error == 0)
548 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
549
550 free(buffer, M_MACTEMP);
551 free(elements, M_MACTEMP);
552
553 return (error);
554}