Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/security/mac/mac_syscalls.c
102325 views
1
/*-
2
* Copyright (c) 1999-2002, 2006, 2009 Robert N. M. Watson
3
* Copyright (c) 2001 Ilmar S. Habibulin
4
* Copyright (c) 2001-2005 Networks Associates Technology, Inc.
5
* Copyright (c) 2005-2006 SPARTA, Inc.
6
* Copyright (c) 2008 Apple Inc.
7
* All rights reserved.
8
*
9
* This software was developed by Robert Watson and Ilmar Habibulin for the
10
* TrustedBSD Project.
11
*
12
* This software was developed for the FreeBSD Project in part by Network
13
* Associates Laboratories, the Security Research Division of Network
14
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
15
* as part of the DARPA CHATS research program.
16
*
17
* This software was enhanced by SPARTA ISSO under SPAWAR contract
18
* N66001-04-C-6019 ("SEFOS").
19
*
20
* This software was developed at the University of Cambridge Computer
21
* Laboratory with support from a grant from Google, Inc.
22
*
23
* Redistribution and use in source and binary forms, with or without
24
* modification, are permitted provided that the following conditions
25
* are met:
26
* 1. Redistributions of source code must retain the above copyright
27
* notice, this list of conditions and the following disclaimer.
28
* 2. Redistributions in binary form must reproduce the above copyright
29
* notice, this list of conditions and the following disclaimer in the
30
* documentation and/or other materials provided with the distribution.
31
*
32
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
33
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
36
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42
* SUCH DAMAGE.
43
*/
44
45
#include <sys/cdefs.h>
46
#include "opt_mac.h"
47
48
#include <sys/param.h>
49
#include <sys/abi_compat.h>
50
#include <sys/capsicum.h>
51
#include <sys/fcntl.h>
52
#include <sys/jail.h>
53
#include <sys/jaildesc.h>
54
#include <sys/kernel.h>
55
#include <sys/lock.h>
56
#include <sys/malloc.h>
57
#include <sys/mutex.h>
58
#include <sys/mac.h>
59
#include <sys/proc.h>
60
#include <sys/systm.h>
61
#include <sys/sysctl.h>
62
#include <sys/sysent.h>
63
#include <sys/sysproto.h>
64
#include <sys/vnode.h>
65
#include <sys/mount.h>
66
#include <sys/file.h>
67
#include <sys/namei.h>
68
#include <sys/socket.h>
69
#include <sys/pipe.h>
70
#include <sys/socketvar.h>
71
72
#include <security/mac/mac_framework.h>
73
#include <security/mac/mac_internal.h>
74
#include <security/mac/mac_policy.h>
75
#include <security/mac/mac_syscalls.h>
76
77
#ifdef MAC
78
79
FEATURE(security_mac, "Mandatory Access Control Framework support");
80
81
static int kern___mac_get_path(struct thread *td, const char *path_p,
82
struct mac *mac_p, int follow);
83
static int kern___mac_set_path(struct thread *td, const char *path_p,
84
struct mac *mac_p, int follow);
85
86
#ifdef COMPAT_FREEBSD32
87
struct mac32 {
88
uint32_t m_buflen; /* size_t */
89
uint32_t m_string; /* char * */
90
};
91
#endif
92
93
static int
94
mac_label_copyin_string(struct mac *const mac, char **const u_string,
95
int flag)
96
{
97
char *buffer;
98
int error;
99
100
error = mac_check_structmac_consistent(mac);
101
if (error != 0)
102
return (error);
103
104
/* 'm_buflen' not too big checked by function call above. */
105
buffer = malloc(mac->m_buflen, M_MACTEMP, flag);
106
if (buffer == NULL)
107
return (ENOMEM);
108
109
error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
110
if (error != 0) {
111
free(buffer, M_MACTEMP);
112
return (error);
113
}
114
115
MPASS(error == 0);
116
if (u_string != NULL)
117
*u_string = mac->m_string;
118
mac->m_string = buffer;
119
return (0);
120
}
121
122
/*
123
* Copyin a 'struct mac', including the string pointed to by 'm_string'.
124
*
125
* On success (0 returned), fills '*mac', whose associated storage must be freed
126
* after use by calling free_copied_label() (which see). On success, 'u_string'
127
* if not NULL is filled with the userspace address for 'u_mac->m_string'.
128
*/
129
int
130
mac_label_copyin(const void *const u_mac, struct mac *const mac,
131
char **const u_string)
132
{
133
int error;
134
135
#ifdef COMPAT_FREEBSD32
136
if (SV_CURPROC_FLAG(SV_ILP32)) {
137
struct mac32 mac32;
138
139
error = copyin(u_mac, &mac32, sizeof(mac32));
140
if (error != 0)
141
return (error);
142
143
CP(mac32, *mac, m_buflen);
144
PTRIN_CP(mac32, *mac, m_string);
145
} else
146
#endif
147
{
148
error = copyin(u_mac, mac, sizeof(*mac));
149
if (error != 0)
150
return (error);
151
}
152
153
return (mac_label_copyin_string(mac, u_string, M_WAITOK));
154
}
155
156
void
157
free_copied_label(const struct mac *const mac)
158
{
159
free(mac->m_string, M_MACTEMP);
160
}
161
162
int
163
sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
164
{
165
char *buffer, *u_buffer;
166
struct mac mac;
167
struct proc *tproc;
168
struct ucred *tcred;
169
int error;
170
171
error = mac_label_copyin(uap->mac_p, &mac, &u_buffer);
172
if (error)
173
return (error);
174
175
tproc = pfind(uap->pid);
176
if (tproc == NULL) {
177
error = ESRCH;
178
goto free_mac_and_exit;
179
}
180
181
tcred = NULL; /* Satisfy gcc. */
182
error = p_cansee(td, tproc);
183
if (error == 0)
184
tcred = crhold(tproc->p_ucred);
185
PROC_UNLOCK(tproc);
186
if (error)
187
goto free_mac_and_exit;
188
189
buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
190
error = mac_cred_externalize_label(tcred->cr_label, mac.m_string,
191
buffer, mac.m_buflen);
192
if (error == 0)
193
error = copyout(buffer, u_buffer, strlen(buffer)+1);
194
free(buffer, M_MACTEMP);
195
crfree(tcred);
196
197
free_mac_and_exit:
198
free_copied_label(&mac);
199
return (error);
200
}
201
202
int
203
sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
204
{
205
char *buffer, *u_buffer;
206
struct mac mac;
207
int error;
208
209
error = mac_label_copyin(uap->mac_p, &mac, &u_buffer);
210
if (error)
211
return (error);
212
213
buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
214
error = mac_cred_externalize_label(td->td_ucred->cr_label,
215
mac.m_string, buffer, mac.m_buflen);
216
if (error == 0)
217
error = copyout(buffer, u_buffer, strlen(buffer)+1);
218
219
free(buffer, M_MACTEMP);
220
free_copied_label(&mac);
221
return (error);
222
}
223
224
/*
225
* Performs preparation (including allocations) for mac_set_proc().
226
*
227
* No lock should be held while calling this function. On success,
228
* mac_set_proc_finish() must be called to free the data associated to
229
* 'mac_set_proc_data', even if mac_set_proc_core() fails. 'mac_set_proc_data'
230
* is not set in case of error, and is set to a non-NULL value on success.
231
*/
232
int
233
mac_set_proc_prepare(struct thread *const td, const struct mac *const mac,
234
void **const mac_set_proc_data)
235
{
236
struct label *intlabel;
237
int error;
238
239
PROC_LOCK_ASSERT(td->td_proc, MA_NOTOWNED);
240
241
if (!(mac_labeled & MPC_OBJECT_CRED))
242
return (EINVAL);
243
244
intlabel = mac_cred_label_alloc();
245
error = mac_cred_internalize_label(intlabel, mac->m_string);
246
if (error) {
247
mac_cred_label_free(intlabel);
248
return (error);
249
}
250
251
*mac_set_proc_data = intlabel;
252
return (0);
253
}
254
255
/*
256
* Actually sets the MAC label on 'newcred'.
257
*
258
* The current process' lock *must* be held. This function only sets the label
259
* on 'newcred', but does not put 'newcred' in place on the current process'
260
* (consequently, it also does not call setsugid()). 'mac_set_proc_data' must
261
* be the pointer returned by mac_set_proc_prepare(). If called, this function
262
* must be so between a successful call to mac_set_proc_prepare() and
263
* mac_set_proc_finish(), but calling it is not mandatory (e.g., if some other
264
* error occured under the process lock that obsoletes setting the MAC label).
265
*/
266
int
267
mac_set_proc_core(struct thread *const td, struct ucred *const newcred,
268
void *const mac_set_proc_data)
269
{
270
struct label *const intlabel = mac_set_proc_data;
271
struct proc *const p = td->td_proc;
272
int error;
273
274
MPASS(td == curthread);
275
PROC_LOCK_ASSERT(p, MA_OWNED);
276
277
error = mac_cred_check_relabel(p->p_ucred, intlabel);
278
if (error)
279
return (error);
280
281
mac_cred_relabel(newcred, intlabel);
282
return (0);
283
}
284
285
/*
286
* Performs mac_set_proc() last operations, without the process lock.
287
*
288
* 'proc_label_set' indicates whether the label was actually set by a call to
289
* mac_set_proc_core() that succeeded. 'mac_set_proc_data' must be the pointer
290
* returned by mac_set_proc_prepare(), and its associated data will be freed.
291
*/
292
void
293
mac_set_proc_finish(struct thread *const td, bool proc_label_set,
294
void *const mac_set_proc_data)
295
{
296
struct label *const intlabel = mac_set_proc_data;
297
298
PROC_LOCK_ASSERT(td->td_proc, MA_NOTOWNED);
299
300
if (proc_label_set)
301
mac_proc_vm_revoke(td);
302
mac_cred_label_free(intlabel);
303
}
304
305
int
306
mac_get_prison(struct thread *const td, struct prison *pr,
307
struct vfsoptlist *opts)
308
{
309
char *buffer = NULL, *u_buffer;
310
struct label *intlabel = NULL;
311
struct mac mac;
312
int error;
313
bool locked = true;
314
315
mtx_assert(&pr->pr_mtx, MA_OWNED);
316
#ifdef COMPAT_FREEBSD32
317
if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
318
struct mac32 mac32;
319
320
error = vfs_copyopt(opts, "mac.label", &mac32, sizeof(mac32));
321
if (error == 0) {
322
CP(mac32, mac, m_buflen);
323
PTRIN_CP(mac32, mac, m_string);
324
}
325
} else
326
#endif
327
error = vfs_copyopt(opts, "mac.label", &mac, sizeof(mac));
328
if (error) {
329
if (error != ENOENT)
330
vfs_opterror(opts, "bad mac.label");
331
goto out_nomac;
332
}
333
334
intlabel = mac_prison_label_alloc(M_NOWAIT);
335
if (intlabel == NULL) {
336
error = ENOMEM;
337
goto out;
338
}
339
340
if ((mac_labeled & MPC_OBJECT_PRISON) != 0)
341
mac_prison_copy_label(pr->pr_label, intlabel);
342
343
/*
344
* Externalization may want to acquire an rmlock. We already tapped out
345
* a copy of the label from when the jail_get(2) operation started and
346
* we're expected to be called near the end of jail_get(2) when the lock
347
* is about to be dropped anyways, so this is safe.
348
*/
349
mtx_unlock(&pr->pr_mtx);
350
locked = false;
351
352
error = mac_label_copyin_string(&mac, &u_buffer, M_WAITOK);
353
if (error) {
354
vfs_opterror(opts, "mac.label: string copy failure");
355
goto out;
356
}
357
358
buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
359
if (buffer == NULL) {
360
error = ENOMEM;
361
goto out;
362
}
363
364
error = mac_prison_externalize_label(intlabel, mac.m_string,
365
buffer, mac.m_buflen);
366
367
if (error == 0)
368
error = copyout(buffer, u_buffer, strlen(buffer)+1);
369
370
out:
371
mac_prison_label_free(intlabel);
372
free_copied_label(&mac);
373
free(buffer, M_MACTEMP);
374
375
out_nomac:
376
if (locked) {
377
MPASS(error != 0);
378
mtx_unlock(&pr->pr_mtx);
379
}
380
381
return (error);
382
}
383
384
int
385
mac_set_prison_prepare(struct thread *const td, struct vfsoptlist *opts,
386
void **const mac_set_prison_data)
387
{
388
struct mac mac;
389
struct label *intlabel;
390
int error;
391
392
#ifdef COMPAT_FREEBSD32
393
if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
394
struct mac32 mac32;
395
396
error = vfs_copyopt(opts, "mac.label", &mac32, sizeof(mac32));
397
if (error == 0) {
398
CP(mac32, mac, m_buflen);
399
PTRIN_CP(mac32, mac, m_string);
400
}
401
} else
402
#endif
403
error = vfs_copyopt(opts, "mac.label", &mac, sizeof(mac));
404
if (error) {
405
if (error != ENOENT)
406
vfs_opterror(opts, "bad mac.label");
407
return (error);
408
}
409
410
error = mac_label_copyin_string(&mac, NULL, M_WAITOK);
411
if (error) {
412
vfs_opterror(opts, "mac.label: string copy failure");
413
return (error);
414
}
415
416
/*
417
* If the option wasn't set, then we return ENOENT above. If we don't
418
* have any policies applicable to prisons, we can return EINVAL early.
419
*/
420
if (!(mac_labeled & MPC_OBJECT_PRISON)) {
421
vfs_opterror(opts, "no labelled jail policies");
422
return (EINVAL);
423
}
424
425
intlabel = mac_prison_label_alloc(M_WAITOK);
426
error = mac_prison_internalize_label(intlabel, mac.m_string);
427
if (error) {
428
mac_prison_label_free(intlabel);
429
vfs_opterror(opts, "internalize_label error");
430
return (error);
431
}
432
433
*mac_set_prison_data = intlabel;
434
return (0);
435
}
436
437
int
438
mac_set_prison_core(struct thread *const td, struct prison *pr,
439
void *const mac_set_prison_data)
440
{
441
struct label *const intlabel = mac_set_prison_data;
442
443
return (mac_prison_label_set(td->td_ucred, pr, intlabel));
444
}
445
446
void
447
mac_set_prison_finish(struct thread *const td, bool prison_label_set __unused,
448
void *const mac_set_prison_data)
449
{
450
struct label *const intlabel = mac_set_prison_data;
451
452
mac_prison_label_free(intlabel);
453
}
454
455
int
456
sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
457
{
458
struct ucred *newcred, *oldcred;
459
void *intlabel;
460
struct proc *const p = td->td_proc;
461
struct mac mac;
462
int error;
463
464
error = mac_label_copyin(uap->mac_p, &mac, NULL);
465
if (error)
466
return (error);
467
468
error = mac_set_proc_prepare(td, &mac, &intlabel);
469
if (error)
470
goto free_label;
471
472
newcred = crget();
473
474
PROC_LOCK(p);
475
oldcred = p->p_ucred;
476
crcopy(newcred, oldcred);
477
478
error = mac_set_proc_core(td, newcred, intlabel);
479
if (error) {
480
PROC_UNLOCK(p);
481
crfree(newcred);
482
goto finish;
483
}
484
485
setsugid(p);
486
proc_set_cred(p, newcred);
487
PROC_UNLOCK(p);
488
489
crfree(oldcred);
490
finish:
491
mac_set_proc_finish(td, error == 0, intlabel);
492
free_label:
493
free_copied_label(&mac);
494
return (error);
495
}
496
497
int
498
sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
499
{
500
char *u_buffer, *buffer;
501
struct label *intlabel;
502
struct file *fp;
503
struct mac mac;
504
struct vnode *vp;
505
struct pipe *pipe;
506
struct prison *pr;
507
struct socket *so;
508
cap_rights_t rights;
509
int error;
510
511
error = mac_label_copyin(uap->mac_p, &mac, &u_buffer);
512
if (error)
513
return (error);
514
515
buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
516
error = fget(td, uap->fd, cap_rights_init_one(&rights, CAP_MAC_GET),
517
&fp);
518
if (error)
519
goto out;
520
521
switch (fp->f_type) {
522
case DTYPE_FIFO:
523
case DTYPE_VNODE:
524
if (!(mac_labeled & MPC_OBJECT_VNODE)) {
525
error = EINVAL;
526
goto out_fdrop;
527
}
528
vp = fp->f_vnode;
529
intlabel = mac_vnode_label_alloc();
530
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
531
mac_vnode_copy_label(vp->v_label, intlabel);
532
VOP_UNLOCK(vp);
533
error = mac_vnode_externalize_label(intlabel, mac.m_string,
534
buffer, mac.m_buflen);
535
mac_vnode_label_free(intlabel);
536
break;
537
538
case DTYPE_PIPE:
539
if (!(mac_labeled & MPC_OBJECT_PIPE)) {
540
error = EINVAL;
541
goto out_fdrop;
542
}
543
pipe = fp->f_data;
544
intlabel = mac_pipe_label_alloc();
545
PIPE_LOCK(pipe);
546
mac_pipe_copy_label(pipe->pipe_pair->pp_label, intlabel);
547
PIPE_UNLOCK(pipe);
548
error = mac_pipe_externalize_label(intlabel, mac.m_string,
549
buffer, mac.m_buflen);
550
mac_pipe_label_free(intlabel);
551
break;
552
553
case DTYPE_SOCKET:
554
if (!(mac_labeled & MPC_OBJECT_SOCKET)) {
555
error = EINVAL;
556
goto out_fdrop;
557
}
558
so = fp->f_data;
559
intlabel = mac_socket_label_alloc(M_WAITOK);
560
SOCK_LOCK(so);
561
mac_socket_copy_label(so->so_label, intlabel);
562
SOCK_UNLOCK(so);
563
error = mac_socket_externalize_label(intlabel, mac.m_string,
564
buffer, mac.m_buflen);
565
mac_socket_label_free(intlabel);
566
break;
567
568
case DTYPE_JAILDESC:
569
if (!(mac_labeled & MPC_OBJECT_PRISON)) {
570
error = EINVAL;
571
goto out_fdrop;
572
}
573
574
error = jaildesc_get_prison(fp, &pr);
575
if (error != 0)
576
goto out_fdrop;
577
578
intlabel = mac_prison_label_alloc(M_WAITOK);
579
mac_prison_copy_label(pr->pr_label, intlabel);
580
prison_free(pr);
581
582
error = mac_prison_externalize_label(intlabel, mac.m_string,
583
buffer, mac.m_buflen);
584
mac_prison_label_free(intlabel);
585
break;
586
587
default:
588
error = EINVAL;
589
}
590
if (error == 0)
591
error = copyout(buffer, u_buffer, strlen(buffer)+1);
592
out_fdrop:
593
fdrop(fp, td);
594
out:
595
free(buffer, M_MACTEMP);
596
free_copied_label(&mac);
597
return (error);
598
}
599
600
int
601
sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
602
{
603
604
return (kern___mac_get_path(td, uap->path_p, uap->mac_p, FOLLOW));
605
}
606
607
int
608
sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
609
{
610
611
return (kern___mac_get_path(td, uap->path_p, uap->mac_p, NOFOLLOW));
612
}
613
614
static int
615
kern___mac_get_path(struct thread *td, const char *path_p, struct mac *mac_p,
616
int follow)
617
{
618
char *u_buffer, *buffer;
619
struct nameidata nd;
620
struct label *intlabel;
621
struct mac mac;
622
int error;
623
624
if (!(mac_labeled & MPC_OBJECT_VNODE))
625
return (EINVAL);
626
627
error = mac_label_copyin(mac_p, &mac, &u_buffer);
628
if (error)
629
return (error);
630
631
buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
632
NDINIT(&nd, LOOKUP, LOCKLEAF | follow, UIO_USERSPACE, path_p);
633
error = namei(&nd);
634
if (error)
635
goto out;
636
637
intlabel = mac_vnode_label_alloc();
638
mac_vnode_copy_label(nd.ni_vp->v_label, intlabel);
639
error = mac_vnode_externalize_label(intlabel, mac.m_string, buffer,
640
mac.m_buflen);
641
vput(nd.ni_vp);
642
NDFREE_PNBUF(&nd);
643
mac_vnode_label_free(intlabel);
644
645
if (error == 0)
646
error = copyout(buffer, u_buffer, strlen(buffer)+1);
647
648
out:
649
free(buffer, M_MACTEMP);
650
free_copied_label(&mac);
651
652
return (error);
653
}
654
655
int
656
sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
657
{
658
struct label *intlabel;
659
struct pipe *pipe;
660
struct prison *pr;
661
struct socket *so;
662
struct file *fp;
663
struct mount *mp;
664
struct vnode *vp;
665
struct mac mac;
666
cap_rights_t rights;
667
int error;
668
669
error = mac_label_copyin(uap->mac_p, &mac, NULL);
670
if (error)
671
return (error);
672
673
error = fget(td, uap->fd, cap_rights_init_one(&rights, CAP_MAC_SET),
674
&fp);
675
if (error)
676
goto out;
677
678
switch (fp->f_type) {
679
case DTYPE_FIFO:
680
case DTYPE_VNODE:
681
if (!(mac_labeled & MPC_OBJECT_VNODE)) {
682
error = EINVAL;
683
goto out_fdrop;
684
}
685
intlabel = mac_vnode_label_alloc();
686
error = mac_vnode_internalize_label(intlabel, mac.m_string);
687
if (error) {
688
mac_vnode_label_free(intlabel);
689
break;
690
}
691
vp = fp->f_vnode;
692
error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH);
693
if (error != 0) {
694
mac_vnode_label_free(intlabel);
695
break;
696
}
697
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
698
error = vn_setlabel(vp, intlabel, td->td_ucred);
699
VOP_UNLOCK(vp);
700
vn_finished_write(mp);
701
mac_vnode_label_free(intlabel);
702
break;
703
704
case DTYPE_PIPE:
705
if (!(mac_labeled & MPC_OBJECT_PIPE)) {
706
error = EINVAL;
707
goto out_fdrop;
708
}
709
intlabel = mac_pipe_label_alloc();
710
error = mac_pipe_internalize_label(intlabel, mac.m_string);
711
if (error == 0) {
712
pipe = fp->f_data;
713
PIPE_LOCK(pipe);
714
error = mac_pipe_label_set(td->td_ucred,
715
pipe->pipe_pair, intlabel);
716
PIPE_UNLOCK(pipe);
717
}
718
mac_pipe_label_free(intlabel);
719
break;
720
721
case DTYPE_SOCKET:
722
if (!(mac_labeled & MPC_OBJECT_SOCKET)) {
723
error = EINVAL;
724
goto out_fdrop;
725
}
726
intlabel = mac_socket_label_alloc(M_WAITOK);
727
error = mac_socket_internalize_label(intlabel, mac.m_string);
728
if (error == 0) {
729
so = fp->f_data;
730
error = mac_socket_label_set(td->td_ucred, so,
731
intlabel);
732
}
733
mac_socket_label_free(intlabel);
734
break;
735
736
case DTYPE_JAILDESC:
737
if (!(mac_labeled & MPC_OBJECT_PRISON)) {
738
error = EINVAL;
739
goto out_fdrop;
740
}
741
742
pr = NULL;
743
intlabel = mac_prison_label_alloc(M_WAITOK);
744
error = mac_prison_internalize_label(intlabel, mac.m_string);
745
if (error == 0)
746
error = jaildesc_get_prison(fp, &pr);
747
if (error == 0) {
748
prison_lock(pr);
749
error = mac_prison_label_set(td->td_ucred, pr,
750
intlabel);
751
prison_free_locked(pr);
752
}
753
754
mac_prison_label_free(intlabel);
755
break;
756
757
default:
758
error = EINVAL;
759
}
760
out_fdrop:
761
fdrop(fp, td);
762
out:
763
free_copied_label(&mac);
764
return (error);
765
}
766
767
int
768
sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
769
{
770
771
return (kern___mac_set_path(td, uap->path_p, uap->mac_p, FOLLOW));
772
}
773
774
int
775
sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
776
{
777
778
return (kern___mac_set_path(td, uap->path_p, uap->mac_p, NOFOLLOW));
779
}
780
781
static int
782
kern___mac_set_path(struct thread *td, const char *path_p, struct mac *mac_p,
783
int follow)
784
{
785
struct label *intlabel;
786
struct nameidata nd;
787
struct mount *mp;
788
struct mac mac;
789
int error;
790
791
if (!(mac_labeled & MPC_OBJECT_VNODE))
792
return (EINVAL);
793
794
error = mac_label_copyin(mac_p, &mac, NULL);
795
if (error)
796
return (error);
797
798
intlabel = mac_vnode_label_alloc();
799
error = mac_vnode_internalize_label(intlabel, mac.m_string);
800
free_copied_label(&mac);
801
if (error)
802
goto out;
803
804
NDINIT(&nd, LOOKUP, LOCKLEAF | follow, UIO_USERSPACE, path_p);
805
error = namei(&nd);
806
if (error == 0) {
807
error = vn_start_write(nd.ni_vp, &mp, V_WAIT | V_PCATCH);
808
if (error == 0) {
809
error = vn_setlabel(nd.ni_vp, intlabel,
810
td->td_ucred);
811
vn_finished_write(mp);
812
}
813
vput(nd.ni_vp);
814
NDFREE_PNBUF(&nd);
815
}
816
out:
817
mac_vnode_label_free(intlabel);
818
return (error);
819
}
820
821
int
822
sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap)
823
{
824
struct mac_policy_conf *mpc;
825
char target[MAC_MAX_POLICY_NAME];
826
int error;
827
828
error = copyinstr(uap->policy, target, sizeof(target), NULL);
829
if (error)
830
return (error);
831
832
error = ENOSYS;
833
LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
834
if (strcmp(mpc->mpc_name, target) == 0 &&
835
mpc->mpc_ops->mpo_syscall != NULL) {
836
error = mpc->mpc_ops->mpo_syscall(td,
837
uap->call, uap->arg);
838
goto out;
839
}
840
}
841
842
if (!LIST_EMPTY(&mac_policy_list)) {
843
mac_policy_slock_sleep();
844
LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
845
if (strcmp(mpc->mpc_name, target) == 0 &&
846
mpc->mpc_ops->mpo_syscall != NULL) {
847
error = mpc->mpc_ops->mpo_syscall(td,
848
uap->call, uap->arg);
849
break;
850
}
851
}
852
mac_policy_sunlock_sleep();
853
}
854
out:
855
return (error);
856
}
857
858
#else /* !MAC */
859
860
int
861
sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
862
{
863
864
return (ENOSYS);
865
}
866
867
int
868
sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
869
{
870
871
return (ENOSYS);
872
}
873
874
int
875
sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
876
{
877
878
return (ENOSYS);
879
}
880
881
int
882
sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
883
{
884
885
return (ENOSYS);
886
}
887
888
int
889
sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
890
{
891
892
return (ENOSYS);
893
}
894
895
int
896
sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
897
{
898
899
return (ENOSYS);
900
}
901
902
int
903
sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
904
{
905
906
return (ENOSYS);
907
}
908
909
int
910
sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
911
{
912
913
return (ENOSYS);
914
}
915
916
int
917
sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
918
{
919
920
return (ENOSYS);
921
}
922
923
int
924
sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap)
925
{
926
927
return (ENOSYS);
928
}
929
930
#endif /* !MAC */
931
932