xref: /freebsd/sys/security/mac/mac_pipe.c (revision 685dc743)
1 /*-
2  * Copyright (c) 2002-2003 Networks Associates Technology, Inc.
3  * Copyright (c) 2006 SPARTA, Inc.
4  * Copyright (c) 2009 Robert N. M. Watson
5  * All rights reserved.
6  *
7  * This software was developed for the FreeBSD Project in part by Network
8  * Associates Laboratories, the Security Research Division of Network
9  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
10  * as part of the DARPA CHATS research program.
11  *
12  * This software was enhanced by SPARTA ISSO under SPAWAR contract
13  * N66001-04-C-6019 ("SEFOS").
14  *
15  * This software was developed at the University of Cambridge Computer
16  * Laboratory with support from a grant from Google, Inc.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions
20  * are met:
21  * 1. Redistributions of source code must retain the above copyright
22  *    notice, this list of conditions and the following disclaimer.
23  * 2. Redistributions in binary form must reproduce the above copyright
24  *    notice, this list of conditions and the following disclaimer in the
25  *    documentation and/or other materials provided with the distribution.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  */
39 
40 #include <sys/cdefs.h>
41 #include "opt_mac.h"
42 
43 #include <sys/param.h>
44 #include <sys/kernel.h>
45 #include <sys/lock.h>
46 #include <sys/malloc.h>
47 #include <sys/module.h>
48 #include <sys/mutex.h>
49 #include <sys/sbuf.h>
50 #include <sys/sdt.h>
51 #include <sys/systm.h>
52 #include <sys/vnode.h>
53 #include <sys/pipe.h>
54 #include <sys/sysctl.h>
55 
56 #include <security/mac/mac_framework.h>
57 #include <security/mac/mac_internal.h>
58 #include <security/mac/mac_policy.h>
59 
60 struct label *
mac_pipe_label_alloc(void)61 mac_pipe_label_alloc(void)
62 {
63 	struct label *label;
64 
65 	label = mac_labelzone_alloc(M_WAITOK);
66 	MAC_POLICY_PERFORM(pipe_init_label, label);
67 	return (label);
68 }
69 
70 void
mac_pipe_init(struct pipepair * pp)71 mac_pipe_init(struct pipepair *pp)
72 {
73 
74 	if (mac_labeled & MPC_OBJECT_PIPE)
75 		pp->pp_label = mac_pipe_label_alloc();
76 	else
77 		pp->pp_label = NULL;
78 }
79 
80 void
mac_pipe_label_free(struct label * label)81 mac_pipe_label_free(struct label *label)
82 {
83 
84 	MAC_POLICY_PERFORM_NOSLEEP(pipe_destroy_label, label);
85 	mac_labelzone_free(label);
86 }
87 
88 void
mac_pipe_destroy(struct pipepair * pp)89 mac_pipe_destroy(struct pipepair *pp)
90 {
91 
92 	if (pp->pp_label != NULL) {
93 		mac_pipe_label_free(pp->pp_label);
94 		pp->pp_label = NULL;
95 	}
96 }
97 
98 void
mac_pipe_copy_label(struct label * src,struct label * dest)99 mac_pipe_copy_label(struct label *src, struct label *dest)
100 {
101 
102 	MAC_POLICY_PERFORM_NOSLEEP(pipe_copy_label, src, dest);
103 }
104 
105 int
mac_pipe_externalize_label(struct label * label,char * elements,char * outbuf,size_t outbuflen)106 mac_pipe_externalize_label(struct label *label, char *elements,
107     char *outbuf, size_t outbuflen)
108 {
109 	int error;
110 
111 	MAC_POLICY_EXTERNALIZE(pipe, label, elements, outbuf, outbuflen);
112 
113 	return (error);
114 }
115 
116 int
mac_pipe_internalize_label(struct label * label,char * string)117 mac_pipe_internalize_label(struct label *label, char *string)
118 {
119 	int error;
120 
121 	MAC_POLICY_INTERNALIZE(pipe, label, string);
122 
123 	return (error);
124 }
125 
126 void
mac_pipe_create(struct ucred * cred,struct pipepair * pp)127 mac_pipe_create(struct ucred *cred, struct pipepair *pp)
128 {
129 
130 	MAC_POLICY_PERFORM_NOSLEEP(pipe_create, cred, pp, pp->pp_label);
131 }
132 
133 static void
mac_pipe_relabel(struct ucred * cred,struct pipepair * pp,struct label * newlabel)134 mac_pipe_relabel(struct ucred *cred, struct pipepair *pp,
135     struct label *newlabel)
136 {
137 
138 	MAC_POLICY_PERFORM_NOSLEEP(pipe_relabel, cred, pp, pp->pp_label,
139 	    newlabel);
140 }
141 
142 MAC_CHECK_PROBE_DEFINE4(pipe_check_ioctl, "struct ucred *",
143     "struct pipepair *", "unsigned long", "void *");
144 
145 int
mac_pipe_check_ioctl(struct ucred * cred,struct pipepair * pp,unsigned long cmd,void * data)146 mac_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
147     unsigned long cmd, void *data)
148 {
149 	int error;
150 
151 	mtx_assert(&pp->pp_mtx, MA_OWNED);
152 
153 	MAC_POLICY_CHECK_NOSLEEP(pipe_check_ioctl, cred, pp, pp->pp_label,
154 	    cmd, data);
155 	MAC_CHECK_PROBE4(pipe_check_ioctl, error, cred, pp, cmd, data);
156 
157 	return (error);
158 }
159 
160 MAC_CHECK_PROBE_DEFINE2(pipe_check_poll, "struct ucred *",
161     "struct pipepair *");
162 
163 int
mac_pipe_check_poll_impl(struct ucred * cred,struct pipepair * pp)164 mac_pipe_check_poll_impl(struct ucred *cred, struct pipepair *pp)
165 {
166 	int error;
167 
168 	mtx_assert(&pp->pp_mtx, MA_OWNED);
169 
170 	MAC_POLICY_CHECK_NOSLEEP(pipe_check_poll, cred, pp, pp->pp_label);
171 	MAC_CHECK_PROBE2(pipe_check_poll, error, cred, pp);
172 
173 	return (error);
174 }
175 
176 MAC_CHECK_PROBE_DEFINE2(pipe_check_read, "struct ucred *",
177     "struct pipepair *");
178 
179 int
mac_pipe_check_read_impl(struct ucred * cred,struct pipepair * pp)180 mac_pipe_check_read_impl(struct ucred *cred, struct pipepair *pp)
181 {
182 	int error;
183 
184 	mtx_assert(&pp->pp_mtx, MA_OWNED);
185 
186 	MAC_POLICY_CHECK_NOSLEEP(pipe_check_read, cred, pp, pp->pp_label);
187 	MAC_CHECK_PROBE2(pipe_check_read, error, cred, pp);
188 
189 	return (error);
190 }
191 
192 MAC_CHECK_PROBE_DEFINE3(pipe_check_relabel, "struct ucred *",
193     "struct pipepair *", "struct label *");
194 
195 static int
mac_pipe_check_relabel(struct ucred * cred,struct pipepair * pp,struct label * newlabel)196 mac_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
197     struct label *newlabel)
198 {
199 	int error;
200 
201 	mtx_assert(&pp->pp_mtx, MA_OWNED);
202 
203 	MAC_POLICY_CHECK_NOSLEEP(pipe_check_relabel, cred, pp, pp->pp_label,
204 	    newlabel);
205 	MAC_CHECK_PROBE3(pipe_check_relabel, error, cred, pp, newlabel);
206 
207 	return (error);
208 }
209 
210 MAC_CHECK_PROBE_DEFINE2(pipe_check_stat, "struct ucred *",
211     "struct pipepair *");
212 
213 int
mac_pipe_check_stat(struct ucred * cred,struct pipepair * pp)214 mac_pipe_check_stat(struct ucred *cred, struct pipepair *pp)
215 {
216 	int error;
217 
218 	mtx_assert(&pp->pp_mtx, MA_OWNED);
219 
220 	MAC_POLICY_CHECK_NOSLEEP(pipe_check_stat, cred, pp, pp->pp_label);
221 	MAC_CHECK_PROBE2(pipe_check_stat, error, cred, pp);
222 
223 	return (error);
224 }
225 
226 MAC_CHECK_PROBE_DEFINE2(pipe_check_write, "struct ucred *",
227     "struct pipepair *");
228 
229 int
mac_pipe_check_write(struct ucred * cred,struct pipepair * pp)230 mac_pipe_check_write(struct ucred *cred, struct pipepair *pp)
231 {
232 	int error;
233 
234 	mtx_assert(&pp->pp_mtx, MA_OWNED);
235 
236 	MAC_POLICY_CHECK_NOSLEEP(pipe_check_write, cred, pp, pp->pp_label);
237 	MAC_CHECK_PROBE2(pipe_check_write, error, cred, pp);
238 
239 	return (error);
240 }
241 
242 int
mac_pipe_label_set(struct ucred * cred,struct pipepair * pp,struct label * label)243 mac_pipe_label_set(struct ucred *cred, struct pipepair *pp,
244     struct label *label)
245 {
246 	int error;
247 
248 	mtx_assert(&pp->pp_mtx, MA_OWNED);
249 
250 	error = mac_pipe_check_relabel(cred, pp, label);
251 	if (error)
252 		return (error);
253 
254 	mac_pipe_relabel(cred, pp, label);
255 
256 	return (0);
257 }
258