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