policy.c revision 1.6.28.1 1 /* $NetBSD: policy.c,v 1.6.28.1 2018/06/25 07:25:25 pgoyette Exp $ */
2
3 /*-
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*-
33 * Copyright (c) 2007 Pawel Jakub Dawidek <pjd (at) FreeBSD.org>
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 */
57
58 /*
59 * CDDL HEADER START
60 *
61 * The contents of this file are subject to the terms of the
62 * Common Development and Distribution License (the "License").
63 * You may not use this file except in compliance with the License.
64 *
65 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
66 * or http://www.opensolaris.org/os/licensing.
67 * See the License for the specific language governing permissions
68 * and limitations under the License.
69 *
70 * When distributing Covered Code, include this CDDL HEADER in each
71 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
72 * If applicable, add the following below this CDDL HEADER, with the
73 * fields enclosed by brackets "[]" replaced with your own identifying
74 * information: Portions Copyright [yyyy] [name of copyright owner]
75 *
76 * CDDL HEADER END
77 */
78 /*
79 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
80 * Copyright 2012, Joyent, Inc. All rights reserved.
81 */
82
83 #include <sys/param.h>
84 #include <sys/vnode.h>
85 #include <sys/mount.h>
86 #include <sys/stat.h>
87 #include <sys/policy.h>
88
89 int
90 secpolicy_nfs(cred_t *cr)
91 {
92
93 return kauth_authorize_generic(cr, KAUTH_GENERIC_ISSUSER, NULL);
94 }
95
96 int
97 secpolicy_zfs(cred_t *cred)
98 {
99
100 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
101 }
102
103 int
104 secpolicy_sys_config(cred_t *cred, int checkonly __unused)
105 {
106
107 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
108 }
109
110 int
111 secpolicy_zinject(cred_t *cred)
112 {
113
114 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
115 }
116
117 int
118 secpolicy_fs_mount(cred_t *cred, vnode_t *mvp, struct mount *vfsp)
119 {
120
121 return kauth_authorize_system(cred, KAUTH_SYSTEM_MOUNT,
122 KAUTH_REQ_SYSTEM_MOUNT_NEW, vfsp, NULL, NULL);
123 }
124
125 int
126 secpolicy_fs_unmount(cred_t *cred, struct mount *vfsp)
127 {
128
129 return kauth_authorize_system(cred, KAUTH_SYSTEM_MOUNT,
130 KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT, vfsp, NULL, NULL);
131 }
132
133 int
134 secpolicy_fs_owner(struct mount *mp, cred_t *cr)
135 {
136
137 return (EPERM);
138 }
139
140 /*
141 * This check is done in kern_link(), so we could just return 0 here.
142 */
143 int
144 secpolicy_basic_link(vnode_t *vp, cred_t *cred)
145 {
146
147 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
148 }
149
150 int
151 secpolicy_vnode_stky_modify(cred_t *cred)
152 {
153
154 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
155 }
156
157 int
158 secpolicy_vnode_remove(vnode_t *vp, cred_t *cred)
159 {
160
161 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
162 }
163
164
165 int
166 secpolicy_vnode_owner(vnode_t *vp, cred_t *cred, uid_t owner)
167 {
168
169 if (owner == kauth_cred_getuid(cred))
170 return (0);
171
172 if (secpolicy_fs_owner(vp->v_mount, cred) == 0)
173 return (0);
174
175 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
176 }
177
178 int
179 secpolicy_vnode_access(cred_t *cred, vnode_t *vp, uid_t owner,
180 int mode)
181 {
182
183 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
184 }
185
186 /*
187 * Like secpolicy_vnode_access() but we get the actual wanted mode and the
188 * current mode of the file, not the missing bits.
189 */
190 int
191 secpolicy_vnode_access2(cred_t *cr, vnode_t *vp, uid_t owner,
192 accmode_t curmode, accmode_t wantmode)
193 {
194 accmode_t mode;
195
196 mode = ~curmode & wantmode;
197
198 if (mode == 0)
199 return (0);
200
201 return (secpolicy_vnode_access(cr, vp, owner, mode));
202 }
203
204 int
205 secpolicy_vnode_any_access(cred_t *cr, vnode_t *vp, uid_t owner)
206 {
207
208 return kauth_authorize_generic(cr, KAUTH_GENERIC_ISSUSER, NULL);
209 }
210
211 int
212 secpolicy_xvattr(vnode_t *vp, xvattr_t *xvap, uid_t owner, cred_t *cred, vtype_t vtype)
213 {
214
215 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
216 }
217
218 int
219 secpolicy_vnode_setid_retain(vnode_t *vp, cred_t *cred, boolean_t issuidroot __unused)
220 {
221
222 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
223 }
224
225 int
226 secpolicy_vnode_setids_setgids(vnode_t *vp, cred_t *cred, gid_t gid)
227 {
228
229 if (groupmember(gid, cred))
230 return (0);
231
232 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
233 }
234
235 int
236 secpolicy_vnode_chown(vnode_t *vp, cred_t *cred, uid_t owner)
237 {
238
239 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
240 }
241
242 int
243 secpolicy_vnode_create_gid(cred_t *cred)
244 {
245
246 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
247 }
248
249 int
250 secpolicy_vnode_utime_modify(cred_t *cred)
251 {
252
253 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
254 }
255
256 int
257 secpolicy_vnode_setdac(vnode_t *vp, cred_t *cred, uid_t owner)
258 {
259
260 if (owner == kauth_cred_getuid(cred))
261 return (0);
262
263 return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
264 }
265
266 int
267 secpolicy_setid_setsticky_clear(vnode_t *vp, struct vattr *vap,
268 const struct vattr *ovap, cred_t *cred)
269 {
270 /*
271 * Privileged processes may set the sticky bit on non-directories,
272 * as well as set the setgid bit on a file with a group that the process
273 * is not a member of. Both of these are allowed in jail(8).
274 */
275 if (vp->v_type != VDIR && (vap->va_mode & S_ISTXT)) {
276 if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL))
277 return (EFTYPE);
278 }
279 /*
280 * Check for privilege if attempting to set the
281 * group-id bit.
282 */
283 if ((vap->va_mode & S_ISGID) != 0)
284 return (secpolicy_vnode_setids_setgids(vp, cred, ovap->va_gid));
285
286 return (0);
287 }
288
289 /*
290 * XXX Copied from illumos. Should not be here; should be under
291 * external/cddl/osnet/dist. Not sure why it is even in illumos's
292 * policy.c rather than somewhere in vnode.c or something.
293 */
294 int
295 secpolicy_vnode_setattr(cred_t *cred, vnode_t *vp, struct vattr *vap,
296 const struct vattr *ovap, int flags,
297 int unlocked_access(void *, int, cred_t *), void *node)
298 {
299 int mask = vap->va_mask;
300 int error = 0;
301 boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
302
303 if (mask & AT_SIZE) {
304 if (vp->v_type == VDIR) {
305 error = EISDIR;
306 goto out;
307 }
308
309 /*
310 * If ATTR_NOACLCHECK is set in the flags, then we don't
311 * perform the secondary unlocked_access() call since the
312 * ACL (if any) is being checked there.
313 */
314 if (skipaclchk == B_FALSE) {
315 error = unlocked_access(node, VWRITE, cred);
316 if (error)
317 goto out;
318 }
319 }
320 if (mask & AT_MODE) {
321 /*
322 * If not the owner of the file then check privilege
323 * for two things: the privilege to set the mode at all
324 * and, if we're setting setuid, we also need permissions
325 * to add the set-uid bit, if we're not the owner.
326 * In the specific case of creating a set-uid root
327 * file, we need even more permissions.
328 */
329 if ((error = secpolicy_vnode_setdac(vp, cred, ovap->va_uid)) != 0)
330 goto out;
331
332 if ((error = secpolicy_setid_setsticky_clear(vp, vap,
333 ovap, cred)) != 0)
334 goto out;
335 } else
336 vap->va_mode = ovap->va_mode;
337
338 if (mask & (AT_UID|AT_GID)) {
339 boolean_t checkpriv = B_FALSE;
340
341 /*
342 * Chowning files.
343 *
344 * If you are the file owner:
345 * chown to other uid FILE_CHOWN_SELF
346 * chown to gid (non-member) FILE_CHOWN_SELF
347 * chown to gid (member) <none>
348 *
349 * Instead of PRIV_FILE_CHOWN_SELF, FILE_CHOWN is also
350 * acceptable but the first one is reported when debugging.
351 *
352 * If you are not the file owner:
353 * chown from root PRIV_FILE_CHOWN + zone
354 * chown from other to any PRIV_FILE_CHOWN
355 *
356 */
357 if (kauth_cred_getuid(cred) != ovap->va_uid) {
358 checkpriv = B_TRUE;
359 } else {
360 if (((mask & AT_UID) && vap->va_uid != ovap->va_uid) ||
361 ((mask & AT_GID) && vap->va_gid != ovap->va_gid &&
362 !groupmember(vap->va_gid, cred))) {
363 checkpriv = B_TRUE;
364 }
365 }
366 /*
367 * If necessary, check privilege to see if update can be done.
368 */
369 if (checkpriv &&
370 (error = secpolicy_vnode_chown(vp, cred, ovap->va_uid)) != 0) {
371 goto out;
372 }
373
374 /*
375 * If the file has either the set UID or set GID bits
376 * set and the caller can set the bits, then leave them.
377 */
378 secpolicy_setid_clear(vap, vp, cred);
379 }
380 if (mask & (AT_ATIME|AT_MTIME)) {
381 /*
382 * If not the file owner and not otherwise privileged,
383 * always return an error when setting the
384 * time other than the current (ATTR_UTIME flag set).
385 * If setting the current time (ATTR_UTIME not set) then
386 * unlocked_access will check permissions according to policy.
387 */
388 if (kauth_cred_getuid(cred) != ovap->va_uid) {
389 if (flags & ATTR_UTIME)
390 error = secpolicy_vnode_utime_modify(cred);
391 else if (skipaclchk == B_FALSE) {
392 error = unlocked_access(node, VWRITE, cred);
393 if (error == EACCES &&
394 secpolicy_vnode_utime_modify(cred) == 0)
395 error = 0;
396 }
397 if (error)
398 goto out;
399 }
400 }
401
402 /*
403 * Check for optional attributes here by checking the following:
404 */
405 if (mask & AT_XVATTR)
406 error = secpolicy_xvattr(vp, (xvattr_t *)vap, ovap->va_uid,
407 cred, vp->v_type);
408 out:
409 return (error);
410 }
411
412 void
413 secpolicy_setid_clear(struct vattr *vap, vnode_t *vp, cred_t *cred)
414 {
415 if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) != 0)
416 return;
417
418 if ((vap->va_mode & (S_ISUID | S_ISGID)) != 0) {
419 vap->va_mask |= AT_MODE;
420 vap->va_mode &= ~(S_ISUID|S_ISGID);
421 }
422
423 return;
424 }
425
426 int
427 secpolicy_smb(cred_t *cr)
428 {
429
430 return kauth_authorize_generic(cr, KAUTH_GENERIC_ISSUSER, NULL);
431 }
432
433 void
434 secpolicy_fs_mount_clearopts(cred_t *cr, struct mount *vfsp)
435 {
436
437 printf("%s writeme\n", __func__);
438 }
439