xref: /netbsd-src/external/cddl/osnet/sys/kern/policy.c (revision c2f76ff004a2cb67efe5b12d97bd3ef7fe89e18d)
1 /*	$NetBSD: policy.c,v 1.2 2010/06/24 13:03:05 hannken 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@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 
65 int
66 secpolicy_zfs(kauth_cred_t cred)
67 {
68 
69 	return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
70 }
71 
72 int
73 secpolicy_sys_config(kauth_cred_t cred, int checkonly __unused)
74 {
75 
76 	return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
77 }
78 
79 int
80 secpolicy_zinject(kauth_cred_t cred)
81 {
82 
83 	return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
84 }
85 
86 int
87 secpolicy_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 
94 int
95 secpolicy_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  */
105 int
106 secpolicy_basic_link(kauth_cred_t cred)
107 {
108 
109 	return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
110 }
111 
112 int
113 secpolicy_vnode_stky_modify(kauth_cred_t cred)
114 {
115 
116 	return (EPERM);
117 }
118 
119 int
120 secpolicy_vnode_remove(kauth_cred_t cred)
121 {
122 
123 	return kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
124 }
125 
126 
127 int
128 secpolicy_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 
142 int
143 secpolicy_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  */
157 int
158 secpolicy_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 
165 int
166 secpolicy_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 
172 int
173 secpolicy_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 
182 int
183 secpolicy_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 
191 int
192 secpolicy_vnode_create_gid(struct kauth_cred *cred)
193 {
194 
195 	return (EPERM);
196 }
197 
198 int
199 secpolicy_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 
206 int
207 secpolicy_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 
229 int
230 secpolicy_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 
238 void
239 secpolicy_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
253 int
254 secpolicy_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 
262 int
263 secpolicy_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 
336 int
337 secpolicy_vnode_create_gid(kauth_cred_t cred)
338 {
339 
340 	return (EPERM);
341 }
342 
343 int
344 secpolicy_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 
350 void
351 secpolicy_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