mac_process.c revision 121507
1100894Srwatson/*-
2100894Srwatson * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3100894Srwatson * Copyright (c) 2001 Ilmar S. Habibulin
4113681Srwatson * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
5100894Srwatson * All rights reserved.
6100894Srwatson *
7100894Srwatson * This software was developed by Robert Watson and Ilmar Habibulin for the
8100894Srwatson * TrustedBSD Project.
9100894Srwatson *
10106392Srwatson * This software was developed for the FreeBSD Project in part by Network
11106392Srwatson * Associates Laboratories, the Security Research Division of Network
12106392Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13106392Srwatson * as part of the DARPA CHATS research program.
14100894Srwatson *
15100894Srwatson * Redistribution and use in source and binary forms, with or without
16100894Srwatson * modification, are permitted provided that the following conditions
17100894Srwatson * are met:
18100894Srwatson * 1. Redistributions of source code must retain the above copyright
19100894Srwatson *    notice, this list of conditions and the following disclaimer.
20100894Srwatson * 2. Redistributions in binary form must reproduce the above copyright
21100894Srwatson *    notice, this list of conditions and the following disclaimer in the
22100894Srwatson *    documentation and/or other materials provided with the distribution.
23100894Srwatson *
24100894Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25100894Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26100894Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27100894Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28100894Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29100894Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30100894Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31100894Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32100894Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33100894Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34100894Srwatson * SUCH DAMAGE.
35100894Srwatson */
36116182Sobrien
37116182Sobrien#include <sys/cdefs.h>
38116182Sobrien__FBSDID("$FreeBSD: head/sys/security/mac/mac_process.c 121507 2003-10-25 15:28:20Z rwatson $");
39116182Sobrien
40100894Srwatson#include "opt_mac.h"
41101173Srwatson
42100894Srwatson#include <sys/param.h>
43106856Srwatson#include <sys/condvar.h>
44106468Srwatson#include <sys/imgact.h>
45100979Srwatson#include <sys/kernel.h>
46100979Srwatson#include <sys/lock.h>
47102949Sbde#include <sys/malloc.h>
48100979Srwatson#include <sys/mutex.h>
49100979Srwatson#include <sys/mac.h>
50100979Srwatson#include <sys/proc.h>
51116701Srwatson#include <sys/sbuf.h>
52100979Srwatson#include <sys/systm.h>
53100979Srwatson#include <sys/vnode.h>
54100979Srwatson#include <sys/mount.h>
55100979Srwatson#include <sys/file.h>
56100979Srwatson#include <sys/namei.h>
57100979Srwatson#include <sys/sysctl.h>
58100894Srwatson
59100979Srwatson#include <vm/vm.h>
60100979Srwatson#include <vm/pmap.h>
61100979Srwatson#include <vm/vm_map.h>
62100979Srwatson#include <vm/vm_object.h>
63100979Srwatson
64100979Srwatson#include <sys/mac_policy.h>
65100979Srwatson
66121361Srwatson#include <security/mac/mac_internal.h>
67100979Srwatson
68121361Srwatsonint	mac_enforce_process = 1;
69100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
70100979Srwatson    &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
71100979SrwatsonTUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
72100979Srwatson
73121361Srwatsonint	mac_enforce_vm = 1;
74103514SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
75103514Srwatson    &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
76104236SrwatsonTUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
77103514Srwatson
78103136Srwatsonstatic int	mac_mmap_revocation = 1;
79103136SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
80103136Srwatson    &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
81103136Srwatson    "relabel");
82121361Srwatson
83101892Srwatsonstatic int	mac_mmap_revocation_via_cow = 0;
84100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
85100979Srwatson    &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
86100979Srwatson    "copy-on-write semantics, or by removing all write access");
87100979Srwatson
88101988Srwatson#ifdef MAC_DEBUG
89121361Srwatsonstatic unsigned int nmaccreds, nmacprocs;
90104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
91100979Srwatson    &nmaccreds, 0, "number of ucreds in use");
92107105SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD,
93107105Srwatson    &nmacprocs, 0, "number of procs in use");
94101988Srwatson#endif
95100979Srwatson
96100979Srwatsonstatic void	mac_cred_mmapped_drop_perms_recurse(struct thread *td,
97100979Srwatson		    struct ucred *cred, struct vm_map *map);
98100979Srwatson
99100979Srwatsonvoid
100105694Srwatsonmac_init_cred_label(struct label *label)
101104521Srwatson{
102104521Srwatson
103105694Srwatson	mac_init_label(label);
104105694Srwatson	MAC_PERFORM(init_cred_label, label);
105119184Srwatson	MAC_DEBUG_COUNTER_INC(&nmaccreds);
106104521Srwatson}
107104521Srwatson
108104521Srwatsonvoid
109105694Srwatsonmac_init_cred(struct ucred *cred)
110105694Srwatson{
111105694Srwatson
112105694Srwatson	mac_init_cred_label(&cred->cr_label);
113105694Srwatson}
114105694Srwatson
115105694Srwatsonvoid
116107105Srwatsonmac_init_proc(struct proc *p)
117107105Srwatson{
118107105Srwatson
119107105Srwatson	mac_init_label(&p->p_label);
120107105Srwatson	MAC_PERFORM(init_proc_label, &p->p_label);
121119184Srwatson	MAC_DEBUG_COUNTER_INC(&nmacprocs);
122107105Srwatson}
123107105Srwatson
124105988Srwatsonvoid
125105694Srwatsonmac_destroy_cred_label(struct label *label)
126104521Srwatson{
127104521Srwatson
128105694Srwatson	MAC_PERFORM(destroy_cred_label, label);
129105694Srwatson	mac_destroy_label(label);
130119184Srwatson	MAC_DEBUG_COUNTER_DEC(&nmaccreds);
131104521Srwatson}
132104521Srwatson
133104521Srwatsonvoid
134105694Srwatsonmac_destroy_cred(struct ucred *cred)
135105694Srwatson{
136105694Srwatson
137105694Srwatson	mac_destroy_cred_label(&cred->cr_label);
138105694Srwatson}
139105694Srwatson
140105694Srwatsonvoid
141107105Srwatsonmac_destroy_proc(struct proc *p)
142107105Srwatson{
143107105Srwatson
144107105Srwatson	MAC_PERFORM(destroy_proc_label, &p->p_label);
145107105Srwatson	mac_destroy_label(&p->p_label);
146119184Srwatson	MAC_DEBUG_COUNTER_DEC(&nmacprocs);
147107105Srwatson}
148107105Srwatson
149121361Srwatsonint
150105694Srwatsonmac_externalize_cred_label(struct label *label, char *elements,
151105694Srwatson    char *outbuf, size_t outbuflen, int flags)
152105694Srwatson{
153104522Srwatson	int error;
154104522Srwatson
155121507Srwatson	MAC_EXTERNALIZE(cred, label, elements, outbuf, outbuflen);
156104522Srwatson
157104522Srwatson	return (error);
158104522Srwatson}
159104522Srwatson
160121361Srwatsonint
161105694Srwatsonmac_internalize_cred_label(struct label *label, char *string)
162105694Srwatson{
163105694Srwatson	int error;
164105694Srwatson
165121507Srwatson	MAC_INTERNALIZE(cred, label, string);
166105694Srwatson
167105694Srwatson	return (error);
168105694Srwatson}
169105694Srwatson
170104522Srwatson/*
171104522Srwatson * Initialize MAC label for the first kernel process, from which other
172104522Srwatson * kernel processes and threads are spawned.
173104522Srwatson */
174104521Srwatsonvoid
175104522Srwatsonmac_create_proc0(struct ucred *cred)
176104522Srwatson{
177104522Srwatson
178104522Srwatson	MAC_PERFORM(create_proc0, cred);
179104522Srwatson}
180104522Srwatson
181104522Srwatson/*
182104522Srwatson * Initialize MAC label for the first userland process, from which other
183104522Srwatson * userland processes and threads are spawned.
184104522Srwatson */
185104522Srwatsonvoid
186104522Srwatsonmac_create_proc1(struct ucred *cred)
187104522Srwatson{
188104522Srwatson
189104522Srwatson	MAC_PERFORM(create_proc1, cred);
190104522Srwatson}
191104522Srwatson
192104522Srwatsonvoid
193104522Srwatsonmac_thread_userret(struct thread *td)
194104522Srwatson{
195104522Srwatson
196104522Srwatson	MAC_PERFORM(thread_userret, td);
197104522Srwatson}
198104522Srwatson
199104522Srwatson/*
200104522Srwatson * When a new process is created, its label must be initialized.  Generally,
201104522Srwatson * this involves inheritence from the parent process, modulo possible
202104522Srwatson * deltas.  This function allows that processing to take place.
203104522Srwatson */
204104522Srwatsonvoid
205104522Srwatsonmac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
206104522Srwatson{
207104522Srwatson
208104522Srwatson	MAC_PERFORM(create_cred, parent_cred, child_cred);
209104522Srwatson}
210104522Srwatson
211105988Srwatsonint
212106468Srwatsonmac_execve_enter(struct image_params *imgp, struct mac *mac_p,
213106468Srwatson    struct label *execlabelstorage)
214106468Srwatson{
215106468Srwatson	struct mac mac;
216106468Srwatson	char *buffer;
217106468Srwatson	int error;
218106468Srwatson
219106468Srwatson	if (mac_p == NULL)
220106468Srwatson		return (0);
221106468Srwatson
222106468Srwatson	error = copyin(mac_p, &mac, sizeof(mac));
223106468Srwatson	if (error)
224106468Srwatson		return (error);
225106468Srwatson
226106468Srwatson	error = mac_check_structmac_consistent(&mac);
227106468Srwatson	if (error)
228106468Srwatson		return (error);
229106468Srwatson
230111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
231106468Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
232106468Srwatson	if (error) {
233106468Srwatson		free(buffer, M_MACTEMP);
234106468Srwatson		return (error);
235106468Srwatson	}
236106468Srwatson
237106468Srwatson	mac_init_cred_label(execlabelstorage);
238106468Srwatson	error = mac_internalize_cred_label(execlabelstorage, buffer);
239106468Srwatson	free(buffer, M_MACTEMP);
240106468Srwatson	if (error) {
241106468Srwatson		mac_destroy_cred_label(execlabelstorage);
242106468Srwatson		return (error);
243106468Srwatson	}
244106468Srwatson	imgp->execlabel = execlabelstorage;
245106468Srwatson	return (0);
246106468Srwatson}
247106468Srwatson
248100979Srwatsonvoid
249106468Srwatsonmac_execve_exit(struct image_params *imgp)
250100979Srwatson{
251106468Srwatson	if (imgp->execlabel != NULL)
252106468Srwatson		mac_destroy_cred_label(imgp->execlabel);
253106468Srwatson}
254100979Srwatson
255100979Srwatson/*
256100979Srwatson * When relabeling a process, call out to the policies for the maximum
257100979Srwatson * permission allowed for each object type we know about in its
258100979Srwatson * memory space, and revoke access (in the least surprising ways we
259100979Srwatson * know) when necessary.  The process lock is not held here.
260100979Srwatson */
261107271Srwatsonvoid
262100979Srwatsonmac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
263100979Srwatson{
264100979Srwatson
265100979Srwatson	/* XXX freeze all other threads */
266100979Srwatson	mac_cred_mmapped_drop_perms_recurse(td, cred,
267100979Srwatson	    &td->td_proc->p_vmspace->vm_map);
268100979Srwatson	/* XXX allow other threads to continue */
269100979Srwatson}
270100979Srwatson
271100979Srwatsonstatic __inline const char *
272100979Srwatsonprot2str(vm_prot_t prot)
273100979Srwatson{
274100979Srwatson
275100979Srwatson	switch (prot & VM_PROT_ALL) {
276100979Srwatson	case VM_PROT_READ:
277100979Srwatson		return ("r--");
278100979Srwatson	case VM_PROT_READ | VM_PROT_WRITE:
279100979Srwatson		return ("rw-");
280100979Srwatson	case VM_PROT_READ | VM_PROT_EXECUTE:
281100979Srwatson		return ("r-x");
282100979Srwatson	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
283100979Srwatson		return ("rwx");
284100979Srwatson	case VM_PROT_WRITE:
285100979Srwatson		return ("-w-");
286100979Srwatson	case VM_PROT_EXECUTE:
287100979Srwatson		return ("--x");
288100979Srwatson	case VM_PROT_WRITE | VM_PROT_EXECUTE:
289100979Srwatson		return ("-wx");
290100979Srwatson	default:
291100979Srwatson		return ("---");
292100979Srwatson	}
293100979Srwatson}
294100979Srwatson
295100979Srwatsonstatic void
296100979Srwatsonmac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
297100979Srwatson    struct vm_map *map)
298100979Srwatson{
299100979Srwatson	struct vm_map_entry *vme;
300104546Srwatson	int result;
301104546Srwatson	vm_prot_t revokeperms;
302100979Srwatson	vm_object_t object;
303100979Srwatson	vm_ooffset_t offset;
304100979Srwatson	struct vnode *vp;
305100979Srwatson
306103136Srwatson	if (!mac_mmap_revocation)
307103136Srwatson		return;
308103136Srwatson
309100979Srwatson	vm_map_lock_read(map);
310100979Srwatson	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
311100979Srwatson		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
312100979Srwatson			mac_cred_mmapped_drop_perms_recurse(td, cred,
313100979Srwatson			    vme->object.sub_map);
314100979Srwatson			continue;
315100979Srwatson		}
316100979Srwatson		/*
317100979Srwatson		 * Skip over entries that obviously are not shared.
318100979Srwatson		 */
319100979Srwatson		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
320100979Srwatson		    !vme->max_protection)
321100979Srwatson			continue;
322100979Srwatson		/*
323100979Srwatson		 * Drill down to the deepest backing object.
324100979Srwatson		 */
325100979Srwatson		offset = vme->offset;
326100979Srwatson		object = vme->object.vm_object;
327100979Srwatson		if (object == NULL)
328100979Srwatson			continue;
329100979Srwatson		while (object->backing_object != NULL) {
330100979Srwatson			object = object->backing_object;
331100979Srwatson			offset += object->backing_object_offset;
332100979Srwatson		}
333100979Srwatson		/*
334100979Srwatson		 * At the moment, vm_maps and objects aren't considered
335100979Srwatson		 * by the MAC system, so only things with backing by a
336100979Srwatson		 * normal object (read: vnodes) are checked.
337100979Srwatson		 */
338100979Srwatson		if (object->type != OBJT_VNODE)
339100979Srwatson			continue;
340100979Srwatson		vp = (struct vnode *)object->handle;
341100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
342104546Srwatson		result = vme->max_protection;
343104546Srwatson		mac_check_vnode_mmap_downgrade(cred, vp, &result);
344100979Srwatson		VOP_UNLOCK(vp, 0, td);
345100979Srwatson		/*
346100979Srwatson		 * Find out what maximum protection we may be allowing
347100979Srwatson		 * now but a policy needs to get removed.
348100979Srwatson		 */
349100979Srwatson		revokeperms = vme->max_protection & ~result;
350100979Srwatson		if (!revokeperms)
351100979Srwatson			continue;
352102949Sbde		printf("pid %ld: revoking %s perms from %#lx:%ld "
353102949Sbde		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
354102949Sbde		    prot2str(revokeperms), (u_long)vme->start,
355102949Sbde		    (long)(vme->end - vme->start),
356100979Srwatson		    prot2str(vme->max_protection), prot2str(vme->protection));
357100979Srwatson		vm_map_lock_upgrade(map);
358100979Srwatson		/*
359100979Srwatson		 * This is the really simple case: if a map has more
360100979Srwatson		 * max_protection than is allowed, but it's not being
361100979Srwatson		 * actually used (that is, the current protection is
362100979Srwatson		 * still allowed), we can just wipe it out and do
363100979Srwatson		 * nothing more.
364100979Srwatson		 */
365100979Srwatson		if ((vme->protection & revokeperms) == 0) {
366100979Srwatson			vme->max_protection -= revokeperms;
367100979Srwatson		} else {
368100979Srwatson			if (revokeperms & VM_PROT_WRITE) {
369100979Srwatson				/*
370100979Srwatson				 * In the more complicated case, flush out all
371100979Srwatson				 * pending changes to the object then turn it
372100979Srwatson				 * copy-on-write.
373100979Srwatson				 */
374100979Srwatson				vm_object_reference(object);
375100979Srwatson				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
376113955Salc				VM_OBJECT_LOCK(object);
377100979Srwatson				vm_object_page_clean(object,
378100979Srwatson				    OFF_TO_IDX(offset),
379100979Srwatson				    OFF_TO_IDX(offset + vme->end - vme->start +
380100979Srwatson					PAGE_MASK),
381100979Srwatson				    OBJPC_SYNC);
382113955Salc				VM_OBJECT_UNLOCK(object);
383100979Srwatson				VOP_UNLOCK(vp, 0, td);
384100979Srwatson				vm_object_deallocate(object);
385100979Srwatson				/*
386100979Srwatson				 * Why bother if there's no read permissions
387100979Srwatson				 * anymore?  For the rest, we need to leave
388100979Srwatson				 * the write permissions on for COW, or
389100979Srwatson				 * remove them entirely if configured to.
390100979Srwatson				 */
391100979Srwatson				if (!mac_mmap_revocation_via_cow) {
392100979Srwatson					vme->max_protection &= ~VM_PROT_WRITE;
393100979Srwatson					vme->protection &= ~VM_PROT_WRITE;
394100979Srwatson				} if ((revokeperms & VM_PROT_READ) == 0)
395100979Srwatson					vme->eflags |= MAP_ENTRY_COW |
396100979Srwatson					    MAP_ENTRY_NEEDS_COPY;
397100979Srwatson			}
398100979Srwatson			if (revokeperms & VM_PROT_EXECUTE) {
399100979Srwatson				vme->max_protection &= ~VM_PROT_EXECUTE;
400100979Srwatson				vme->protection &= ~VM_PROT_EXECUTE;
401100979Srwatson			}
402100979Srwatson			if (revokeperms & VM_PROT_READ) {
403100979Srwatson				vme->max_protection = 0;
404100979Srwatson				vme->protection = 0;
405100979Srwatson			}
406100979Srwatson			pmap_protect(map->pmap, vme->start, vme->end,
407100979Srwatson			    vme->protection & ~revokeperms);
408100979Srwatson			vm_map_simplify_entry(map, vme);
409100979Srwatson		}
410100979Srwatson		vm_map_lock_downgrade(map);
411100979Srwatson	}
412100979Srwatson	vm_map_unlock_read(map);
413100979Srwatson}
414100979Srwatson
415100979Srwatson/*
416100979Srwatson * When the subject's label changes, it may require revocation of privilege
417100979Srwatson * to mapped objects.  This can't be done on-the-fly later with a unified
418100979Srwatson * buffer cache.
419100979Srwatson */
420121361Srwatsonvoid
421100979Srwatsonmac_relabel_cred(struct ucred *cred, struct label *newlabel)
422100979Srwatson{
423100979Srwatson
424100979Srwatson	MAC_PERFORM(relabel_cred, cred, newlabel);
425100979Srwatson}
426100979Srwatson
427100979Srwatsonint
428100979Srwatsonmac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
429100979Srwatson{
430100979Srwatson	int error;
431100979Srwatson
432100979Srwatson	MAC_CHECK(check_cred_relabel, cred, newlabel);
433100979Srwatson
434100979Srwatson	return (error);
435100979Srwatson}
436100979Srwatson
437100979Srwatsonint
438100979Srwatsonmac_check_cred_visible(struct ucred *u1, struct ucred *u2)
439100979Srwatson{
440100979Srwatson	int error;
441100979Srwatson
442100979Srwatson	if (!mac_enforce_process)
443100979Srwatson		return (0);
444100979Srwatson
445100979Srwatson	MAC_CHECK(check_cred_visible, u1, u2);
446100979Srwatson
447100979Srwatson	return (error);
448100979Srwatson}
449100979Srwatson
450100979Srwatsonint
451100979Srwatsonmac_check_proc_debug(struct ucred *cred, struct proc *proc)
452100979Srwatson{
453100979Srwatson	int error;
454100979Srwatson
455102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
456102103Srwatson
457100979Srwatson	if (!mac_enforce_process)
458100979Srwatson		return (0);
459100979Srwatson
460100979Srwatson	MAC_CHECK(check_proc_debug, cred, proc);
461100979Srwatson
462100979Srwatson	return (error);
463100979Srwatson}
464100979Srwatson
465100979Srwatsonint
466100979Srwatsonmac_check_proc_sched(struct ucred *cred, struct proc *proc)
467100979Srwatson{
468100979Srwatson	int error;
469100979Srwatson
470102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
471102103Srwatson
472100979Srwatson	if (!mac_enforce_process)
473100979Srwatson		return (0);
474100979Srwatson
475100979Srwatson	MAC_CHECK(check_proc_sched, cred, proc);
476100979Srwatson
477100979Srwatson	return (error);
478100979Srwatson}
479100979Srwatson
480100979Srwatsonint
481100979Srwatsonmac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
482100979Srwatson{
483100979Srwatson	int error;
484100979Srwatson
485102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
486102103Srwatson
487100979Srwatson	if (!mac_enforce_process)
488100979Srwatson		return (0);
489100979Srwatson
490100979Srwatson	MAC_CHECK(check_proc_signal, cred, proc, signum);
491100979Srwatson
492100979Srwatson	return (error);
493100979Srwatson}
494