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