xref: /freebsd/sys/security/mac/mac_pipe.c (revision 83b7b0edcab422d62d6f847c421006a2a41c4e91)
17bc82500SRobert Watson /*-
273275908SRobert Watson  * Copyright (c) 2002, 2003 Networks Associates Technology, Inc.
37bc82500SRobert Watson  * All rights reserved.
47bc82500SRobert Watson  *
56201265bSRobert Watson  * This software was developed for the FreeBSD Project in part by Network
66201265bSRobert Watson  * Associates Laboratories, the Security Research Division of Network
76201265bSRobert Watson  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
86201265bSRobert Watson  * as part of the DARPA CHATS research program.
97bc82500SRobert Watson  *
107bc82500SRobert Watson  * Redistribution and use in source and binary forms, with or without
117bc82500SRobert Watson  * modification, are permitted provided that the following conditions
127bc82500SRobert Watson  * are met:
137bc82500SRobert Watson  * 1. Redistributions of source code must retain the above copyright
147bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer.
157bc82500SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
167bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
177bc82500SRobert Watson  *    documentation and/or other materials provided with the distribution.
187bc82500SRobert Watson  *
197bc82500SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
207bc82500SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
217bc82500SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
227bc82500SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
237bc82500SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
247bc82500SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
257bc82500SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
267bc82500SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
277bc82500SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
287bc82500SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
297bc82500SRobert Watson  * SUCH DAMAGE.
307bc82500SRobert Watson  */
31677b542eSDavid E. O'Brien 
32677b542eSDavid E. O'Brien #include <sys/cdefs.h>
33677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
34677b542eSDavid E. O'Brien 
357bc82500SRobert Watson #include "opt_mac.h"
36f9d0d524SRobert Watson 
377bc82500SRobert Watson #include <sys/param.h>
3895fab37eSRobert Watson #include <sys/kernel.h>
3995fab37eSRobert Watson #include <sys/lock.h>
40b656366bSBruce Evans #include <sys/malloc.h>
4195fab37eSRobert Watson #include <sys/mutex.h>
4295fab37eSRobert Watson #include <sys/mac.h>
43f51e5803SRobert Watson #include <sys/sbuf.h>
4495fab37eSRobert Watson #include <sys/systm.h>
4595fab37eSRobert Watson #include <sys/vnode.h>
4695fab37eSRobert Watson #include <sys/pipe.h>
4795fab37eSRobert Watson #include <sys/sysctl.h>
4895fab37eSRobert Watson 
4995fab37eSRobert Watson #include <sys/mac_policy.h>
5095fab37eSRobert Watson 
5173275908SRobert Watson #include <security/mac/mac_internal.h>
5295fab37eSRobert Watson 
53b88c98f6SRobert Watson static int	mac_enforce_pipe = 1;
54b88c98f6SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
55b88c98f6SRobert Watson     &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
56c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
57b88c98f6SRobert Watson 
58f050add5SRobert Watson #ifdef MAC_DEBUG
5973275908SRobert Watson static unsigned int nmacpipes;
60b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
6195fab37eSRobert Watson     &nmacpipes, 0, "number of pipes in use");
62f050add5SRobert Watson #endif
6395fab37eSRobert Watson 
6495fab37eSRobert Watson MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
6508bcdc58SRobert Watson 
6608bcdc58SRobert Watson void
67f7b951a8SRobert Watson mac_init_pipe_label(struct label *label)
68f7b951a8SRobert Watson {
69f7b951a8SRobert Watson 
70f7b951a8SRobert Watson 	mac_init_label(label);
71f7b951a8SRobert Watson 	MAC_PERFORM(init_pipe_label, label);
728d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacpipes);
73f7b951a8SRobert Watson }
74f7b951a8SRobert Watson 
7508bcdc58SRobert Watson void
7608bcdc58SRobert Watson mac_init_pipe(struct pipe *pipe)
7708bcdc58SRobert Watson {
7808bcdc58SRobert Watson 	struct label *label;
7908bcdc58SRobert Watson 
80a163d034SWarner Losh 	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
8108bcdc58SRobert Watson 	pipe->pipe_label = label;
8208bcdc58SRobert Watson 	pipe->pipe_peer->pipe_label = label;
83f7b951a8SRobert Watson 	mac_init_pipe_label(label);
8408bcdc58SRobert Watson }
8508bcdc58SRobert Watson 
862555374cSRobert Watson void
87f7b951a8SRobert Watson mac_destroy_pipe_label(struct label *label)
88f7b951a8SRobert Watson {
89f7b951a8SRobert Watson 
90f7b951a8SRobert Watson 	MAC_PERFORM(destroy_pipe_label, label);
91f7b951a8SRobert Watson 	mac_destroy_label(label);
928d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacpipes);
93f7b951a8SRobert Watson }
94f7b951a8SRobert Watson 
9587807196SRobert Watson void
9687807196SRobert Watson mac_destroy_pipe(struct pipe *pipe)
9708bcdc58SRobert Watson {
9808bcdc58SRobert Watson 
99f7b951a8SRobert Watson 	mac_destroy_pipe_label(pipe->pipe_label);
10087807196SRobert Watson 	free(pipe->pipe_label, M_MACPIPELABEL);
10187807196SRobert Watson }
10287807196SRobert Watson 
1032555374cSRobert Watson void
104f7b951a8SRobert Watson mac_copy_pipe_label(struct label *src, struct label *dest)
105f7b951a8SRobert Watson {
106f7b951a8SRobert Watson 
107f7b951a8SRobert Watson 	MAC_PERFORM(copy_pipe_label, src, dest);
108f7b951a8SRobert Watson }
109f7b951a8SRobert Watson 
11073275908SRobert Watson int
111f7b951a8SRobert Watson mac_externalize_pipe_label(struct label *label, char *elements,
11283b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
113f7b951a8SRobert Watson {
114f7b951a8SRobert Watson 	int error;
115f7b951a8SRobert Watson 
116da77b2faSRobert Watson 	MAC_EXTERNALIZE(pipe, label, elements, outbuf, outbuflen);
117f7b951a8SRobert Watson 
118f7b951a8SRobert Watson 	return (error);
119f7b951a8SRobert Watson }
120f7b951a8SRobert Watson 
12173275908SRobert Watson int
122f7b951a8SRobert Watson mac_internalize_pipe_label(struct label *label, char *string)
123f7b951a8SRobert Watson {
124f7b951a8SRobert Watson 	int error;
125f7b951a8SRobert Watson 
126da77b2faSRobert Watson 	MAC_INTERNALIZE(pipe, label, string);
127f7b951a8SRobert Watson 
128f7b951a8SRobert Watson 	return (error);
129f7b951a8SRobert Watson }
130f7b951a8SRobert Watson 
13195fab37eSRobert Watson void
13295fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe)
13395fab37eSRobert Watson {
13495fab37eSRobert Watson 
13595fab37eSRobert Watson 	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
13695fab37eSRobert Watson }
13795fab37eSRobert Watson 
13895fab37eSRobert Watson static void
13995fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
14095fab37eSRobert Watson {
14195fab37eSRobert Watson 
14295fab37eSRobert Watson 	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
14395fab37eSRobert Watson }
14495fab37eSRobert Watson 
14595fab37eSRobert Watson int
14695fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
14795fab37eSRobert Watson     void *data)
14895fab37eSRobert Watson {
14995fab37eSRobert Watson 	int error;
15095fab37eSRobert Watson 
1511aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
1521aa37f53SRobert Watson 
1531aa37f53SRobert Watson 	if (!mac_enforce_pipe)
1541aa37f53SRobert Watson 		return (0);
1551aa37f53SRobert Watson 
15695fab37eSRobert Watson 	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
15795fab37eSRobert Watson 
15895fab37eSRobert Watson 	return (error);
15995fab37eSRobert Watson }
16095fab37eSRobert Watson 
16195fab37eSRobert Watson int
162c024c3eeSRobert Watson mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
16395fab37eSRobert Watson {
16495fab37eSRobert Watson 	int error;
16595fab37eSRobert Watson 
1661aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
1671aa37f53SRobert Watson 
1681aa37f53SRobert Watson 	if (!mac_enforce_pipe)
1691aa37f53SRobert Watson 		return (0);
1701aa37f53SRobert Watson 
171c024c3eeSRobert Watson 	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
172c024c3eeSRobert Watson 
173c024c3eeSRobert Watson 	return (error);
174c024c3eeSRobert Watson }
175c024c3eeSRobert Watson 
176c024c3eeSRobert Watson int
177c024c3eeSRobert Watson mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
178c024c3eeSRobert Watson {
179c024c3eeSRobert Watson 	int error;
180c024c3eeSRobert Watson 
1811aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
1821aa37f53SRobert Watson 
1831aa37f53SRobert Watson 	if (!mac_enforce_pipe)
1841aa37f53SRobert Watson 		return (0);
1851aa37f53SRobert Watson 
186c024c3eeSRobert Watson 	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
18795fab37eSRobert Watson 
18895fab37eSRobert Watson 	return (error);
18995fab37eSRobert Watson }
19095fab37eSRobert Watson 
19195fab37eSRobert Watson static int
19295fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
19395fab37eSRobert Watson     struct label *newlabel)
19495fab37eSRobert Watson {
19595fab37eSRobert Watson 	int error;
19695fab37eSRobert Watson 
1971aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
1981aa37f53SRobert Watson 
1991aa37f53SRobert Watson 	if (!mac_enforce_pipe)
2001aa37f53SRobert Watson 		return (0);
2011aa37f53SRobert Watson 
20295fab37eSRobert Watson 	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
20395fab37eSRobert Watson 
20495fab37eSRobert Watson 	return (error);
20595fab37eSRobert Watson }
20695fab37eSRobert Watson 
20795fab37eSRobert Watson int
208c024c3eeSRobert Watson mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
209c024c3eeSRobert Watson {
210c024c3eeSRobert Watson 	int error;
211c024c3eeSRobert Watson 
2121aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2131aa37f53SRobert Watson 
2141aa37f53SRobert Watson 	if (!mac_enforce_pipe)
2151aa37f53SRobert Watson 		return (0);
2161aa37f53SRobert Watson 
217c024c3eeSRobert Watson 	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
218c024c3eeSRobert Watson 
219c024c3eeSRobert Watson 	return (error);
220c024c3eeSRobert Watson }
221c024c3eeSRobert Watson 
222c024c3eeSRobert Watson int
223c024c3eeSRobert Watson mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
224c024c3eeSRobert Watson {
225c024c3eeSRobert Watson 	int error;
226c024c3eeSRobert Watson 
2271aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2281aa37f53SRobert Watson 
2291aa37f53SRobert Watson 	if (!mac_enforce_pipe)
2301aa37f53SRobert Watson 		return (0);
2311aa37f53SRobert Watson 
232c024c3eeSRobert Watson 	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
233c024c3eeSRobert Watson 
234c024c3eeSRobert Watson 	return (error);
235c024c3eeSRobert Watson }
236c024c3eeSRobert Watson 
237c024c3eeSRobert Watson int
23895fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
23995fab37eSRobert Watson {
24095fab37eSRobert Watson 	int error;
24195fab37eSRobert Watson 
2421aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2431aa37f53SRobert Watson 
24495fab37eSRobert Watson 	error = mac_check_pipe_relabel(cred, pipe, label);
24595fab37eSRobert Watson 	if (error)
24695fab37eSRobert Watson 		return (error);
24795fab37eSRobert Watson 
24895fab37eSRobert Watson 	mac_relabel_pipe(cred, pipe, label);
24995fab37eSRobert Watson 
25095fab37eSRobert Watson 	return (0);
25195fab37eSRobert Watson }
252