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