11590Srgrimes/*	$NetBSD: policy.c,v 1.1 2009/08/07 20:57:57 haad Exp $	*/
21590Srgrimes
31590Srgrimes/*-
41590Srgrimes * Copyright (c) 2009 The NetBSD Foundation, Inc.
523695Speter * All rights reserved.
61590Srgrimes *
71590Srgrimes * 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@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#include <sys/param.h>
59#include <sys/priv.h>
60#include <sys/vnode.h>
61#include <sys/mount.h>
62#include <sys/stat.h>
63#include <sys/policy.h>
64
65int
66secpolicy_zfs(kauth_cred_t cred)
67{
68
69	return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
70}
71
72int
73secpolicy_sys_config(kauth_cred_t cred, int checkonly __unused)
74{
75
76	return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
77}
78
79int
80secpolicy_zinject(kauth_cred_t cred)
81{
82
83	return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
84}
85
86int
87secpolicy_fs_mount(kauth_cred_t cred, vnode_t *mvp, struct mount *vfsp)
88{
89
90	return kauth_authorize_system(cred, KAUTH_SYSTEM_MOUNT,
91	    KAUTH_REQ_SYSTEM_MOUNT_NEW, vfsp, NULL, NULL);
92}
93
94int
95secpolicy_fs_unmount(kauth_cred_t cred, struct mount *vfsp)
96{
97
98	return kauth_authorize_system(cred, KAUTH_SYSTEM_MOUNT,
99	    KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT, vfsp, NULL, NULL);
100}
101
102/*
103 * This check is done in kern_link(), so we could just return 0 here.
104 */
105int
106secpolicy_basic_link(kauth_cred_t cred)
107{
108
109	return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
110}
111
112int
113secpolicy_vnode_stky_modify(kauth_cred_t cred)
114{
115
116	return (EPERM);
117}
118
119int
120secpolicy_vnode_remove(kauth_cred_t cred)
121{
122
123	return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
124}
125
126
127int
128secpolicy_vnode_owner(cred_t *cred, uid_t owner)
129{
130	uid_t uid;
131
132	uid = crgetuid(cred);
133
134	if (owner == uid)
135		 return (0);
136
137	return 0;
138//	return kauth_authorize_system(cred, KAUTH_SYSTEM_MOUNT,
139//	    KAUTH_REQ_SYSTEM_MOUNT_NEW, vfsp, NULL, NULL);
140}
141
142int
143secpolicy_vnode_access(kauth_cred_t cred, struct vnode *vp, uint64_t owner,
144    int mode)
145{
146	int error;
147
148	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
149	error = VOP_ACCESS(vp, mode, cred);
150	VOP_UNLOCK(vp);
151	return error;
152}
153
154/*
155 * Check privileges for setting xvattr attributes
156 */
157int
158secpolicy_xvattr(xvattr_t *xvap, uid_t owner, cred_t *cr, vtype_t vtype)
159{
160/*	return kauth_authorize_system(cred, KAUTH_SYSTEM_MOUNT,
161	KAUTH_REQ_SYSTEM_MOUNT_UPDATE, vfsp, NULL, NULL);*/
162	return 0;
163}
164
165int
166secpolicy_vnode_setid_retain(kauth_cred_t cred, boolean_t issuidroot __unused)
167{
168
169	return  (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL));
170}
171
172int
173secpolicy_vnode_setids_setgids(kauth_cred_t cred, gid_t gid)
174{
175
176	if (!groupmember(gid, cred))
177		return  (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
178			NULL));
179	return (0);
180}
181
182int
183secpolicy_vnode_chown(struct kauth_cred *cred, boolean_t check_self)
184{
185
186	return  (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
187		NULL));
188	/* return (priv_check_cred(cred, PRIV_VFS_CHOWN, 0)); */
189}
190
191int
192secpolicy_vnode_create_gid(struct kauth_cred *cred)
193{
194
195	return (EPERM);
196}
197
198int
199secpolicy_vnode_setdac(struct kauth_cred *cred, uid_t owner)
200{
201
202	return 0;
203	/*return (priv_check_cred(cred, PRIV_VFS_ADMIN, 0));*/
204}
205
206int
207secpolicy_setid_setsticky_clear(struct vnode *vp, struct vattr *vap,
208    const struct vattr *ovap, kauth_cred_t cred)
209{
210	/*
211	 * Privileged processes may set the sticky bit on non-directories,
212	 * as well as set the setgid bit on a file with a group that the process
213	 * is not a member of. Both of these are allowed in jail(8).
214	 */
215	if (vp->v_type != VDIR && (vap->va_mode & S_ISTXT)) {
216		if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) != 0)
217			return (EFTYPE);
218	}
219	/*
220	 * Check for privilege if attempting to set the
221	 * group-id bit.
222	 */
223	if ((vap->va_mode & S_ISGID) != 0)
224		return (secpolicy_vnode_setids_setgids(cred, ovap->va_gid));
225
226	return (0);
227}
228
229int
230secpolicy_vnode_setattr(kauth_cred_t cred, struct vnode *vp, struct vattr *vap,
231    const struct vattr *ovap, int flags,
232    int unlocked_access(void *, int, kauth_cred_t ), void *node)
233{
234
235	return 0;
236}
237
238void
239secpolicy_setid_clear(struct vattr *vap, kauth_cred_t cred)
240{
241	if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) != 0)
242		return;
243
244	if ((vap->va_mode & (S_ISUID | S_ISGID)) != 0) {
245			vap->va_mask |= AT_MODE;
246			vap->va_mode &= ~(S_ISUID|S_ISGID);
247	}
248
249	return;
250}
251
252#ifdef notyet
253int
254secpolicy_vnode_setdac(kauth_cred_t cred, uid_t owner)
255{
256
257	if (owner == cred->cr_uid)
258		return (0);
259	return (priv_check_cred(cred, PRIV_VFS_ADMIN, 0));
260}
261
262int
263secpolicy_vnode_setattr(kauth_cred_t cred, struct vnode *vp, struct vattr *vap,
264    const struct vattr *ovap, int flags,
265    int unlocked_access(void *, int, kauth_cred_t ), void *node)
266{
267	int mask = vap->va_mask;
268	int error;
269
270	if (mask & AT_SIZE) {
271		if (vp->v_type == VDIR)
272			return (EISDIR);
273		error = unlocked_access(node, VWRITE, cred);
274		if (error)
275			return (error);
276	}
277	if (mask & AT_MODE) {
278		/*
279		 * If not the owner of the file then check privilege
280		 * for two things: the privilege to set the mode at all
281		 * and, if we're setting setuid, we also need permissions
282		 * to add the set-uid bit, if we're not the owner.
283		 * In the specific case of creating a set-uid root
284		 * file, we need even more permissions.
285		 */
286		error = secpolicy_vnode_setdac(cred, ovap->va_uid);
287		if (error)
288			return (error);
289		error = secpolicy_setid_setsticky_clear(vp, vap, ovap, cred);
290		if (error)
291			return (error);
292	} else {
293		vap->va_mode = ovap->va_mode;
294	}
295	if (mask & (AT_UID | AT_GID)) {
296		error = secpolicy_vnode_setdac(cred, ovap->va_uid);
297		if (error)
298			return (error);
299
300		/*
301		 * To change the owner of a file, or change the group of a file to a
302		 * group of which we are not a member, the caller must have
303		 * privilege.
304		 */
305		if (((mask & AT_UID) && vap->va_uid != ovap->va_uid) ||
306		    ((mask & AT_GID) && vap->va_gid != ovap->va_gid &&
307		     !groupmember(vap->va_gid, cred))) {
308			error = priv_check_cred(cred, PRIV_VFS_CHOWN, 0);
309			if (error)
310				return (error);
311		}
312
313		if (((mask & AT_UID) && vap->va_uid != ovap->va_uid) ||
314		    ((mask & AT_GID) && vap->va_gid != ovap->va_gid)) {
315			secpolicy_setid_clear(vap, cred);
316		}
317	}
318	if (mask & (AT_ATIME | AT_MTIME)) {
319		/*
320		 * From utimes(2):
321		 * If times is NULL, ... The caller must be the owner of
322		 * the file, have permission to write the file, or be the
323		 * super-user.
324		 * If times is non-NULL, ... The caller must be the owner of
325		 * the file or be the super-user.
326		 */
327		error = secpolicy_vnode_setdac(cred, ovap->va_uid);
328		if (error && (vap->va_vaflags & VA_UTIMES_NULL))
329			error = unlocked_access(node, VWRITE, cred);
330		if (error)
331			return (error);
332	}
333	return (0);
334}
335
336int
337secpolicy_vnode_create_gid(kauth_cred_t cred)
338{
339
340	return (EPERM);
341}
342
343int
344secpolicy_vnode_setid_retain(kauth_cred_t cred, boolean_t issuidroot __unused)
345{
346
347	return (priv_check_cred(cred, PRIV_VFS_RETAINSUGID, 0));
348}
349
350void
351secpolicy_setid_clear(struct vattr *vap, kauth_cred_t cred)
352{
353
354	if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL))
355		return;
356
357	if ((vap->va_mode & (S_ISUID | S_ISGID)) != 0) {
358		if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID, 0)) {
359			vap->va_mask |= AT_MODE;
360			vap->va_mode &= ~(S_ISUID|S_ISGID);
361		}
362	}
363}
364#endif
365