1 // SPDX-License-Identifier: CDDL-1.0 2 /* 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License (the "License"). 7 * You may not use this file except in compliance with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or https://opensource.org/licenses/CDDL-1.0. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 25 * Copyright 2013, Joyent, Inc. All rights reserved. 26 * Copyright (C) 2016 Lawrence Livermore National Security, LLC. 27 * 28 * For Linux the vast majority of this enforcement is already handled via 29 * the standard Linux VFS permission checks. However certain administrative 30 * commands which bypass the standard mechanisms may need to make use of 31 * this functionality. 32 */ 33 34 #include <sys/policy.h> 35 #include <linux/security.h> 36 #include <linux/vfs_compat.h> 37 38 /* 39 * The passed credentials cannot be directly verified because Linux only 40 * provides and interface to check the *current* process credentials. In 41 * order to handle this the capable() test is only run when the passed 42 * credentials match the current process credentials or the kcred. In 43 * all other cases this function must fail and return the passed err. 44 */ 45 static int 46 priv_policy_ns(const cred_t *cr, int capability, int err, 47 struct user_namespace *ns) 48 { 49 if (cr != CRED() && (cr != kcred)) 50 return (err); 51 52 #if defined(CONFIG_USER_NS) 53 if (!(ns ? ns_capable(ns, capability) : capable(capability))) 54 #else 55 if (!capable(capability)) 56 #endif 57 return (err); 58 59 return (0); 60 } 61 62 static int 63 priv_policy(const cred_t *cr, int capability, int err) 64 { 65 return (priv_policy_ns(cr, capability, err, cr->user_ns)); 66 } 67 68 static int 69 priv_policy_user(const cred_t *cr, int capability, int err) 70 { 71 /* 72 * All priv_policy_user checks are preceded by kuid/kgid_has_mapping() 73 * checks. If we cannot do them, we shouldn't be using ns_capable() 74 * since we don't know whether the affected files are valid in our 75 * namespace. 76 */ 77 #if defined(CONFIG_USER_NS) 78 return (priv_policy_ns(cr, capability, err, cr->user_ns)); 79 #else 80 return (priv_policy_ns(cr, capability, err, NULL)); 81 #endif 82 } 83 84 /* 85 * Checks for operations that are either client-only or are used by 86 * both clients and servers. 87 */ 88 int 89 secpolicy_nfs(const cred_t *cr) 90 { 91 return (priv_policy(cr, CAP_SYS_ADMIN, EPERM)); 92 } 93 94 /* 95 * Catch all system configuration. 96 */ 97 int 98 secpolicy_sys_config(const cred_t *cr, boolean_t checkonly) 99 { 100 return (priv_policy(cr, CAP_SYS_ADMIN, EPERM)); 101 } 102 103 /* 104 * Like secpolicy_vnode_access() but we get the actual wanted mode and the 105 * current mode of the file, not the missing bits. 106 * 107 * Enforced in the Linux VFS. 108 */ 109 int 110 secpolicy_vnode_access2(const cred_t *cr, struct inode *ip, uid_t owner, 111 mode_t curmode, mode_t wantmode) 112 { 113 return (0); 114 } 115 116 /* 117 * This is a special routine for ZFS; it is used to determine whether 118 * any of the privileges in effect allow any form of access to the 119 * file. There's no reason to audit this or any reason to record 120 * this. More work is needed to do the "KPLD" stuff. 121 */ 122 int 123 secpolicy_vnode_any_access(const cred_t *cr, struct inode *ip, uid_t owner) 124 { 125 if (crgetuid(cr) == owner) 126 return (0); 127 128 if (zpl_inode_owner_or_capable(zfs_init_idmap, ip)) 129 return (0); 130 131 #if defined(CONFIG_USER_NS) 132 if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner))) 133 return (EPERM); 134 #endif 135 136 if (priv_policy_user(cr, CAP_DAC_OVERRIDE, EPERM) == 0) 137 return (0); 138 139 if (priv_policy_user(cr, CAP_DAC_READ_SEARCH, EPERM) == 0) 140 return (0); 141 142 return (EPERM); 143 } 144 145 /* 146 * Determine if subject can chown owner of a file. 147 */ 148 int 149 secpolicy_vnode_chown(const cred_t *cr, uid_t owner) 150 { 151 if (crgetuid(cr) == owner) 152 return (0); 153 154 #if defined(CONFIG_USER_NS) 155 if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner))) 156 return (EPERM); 157 #endif 158 159 return (priv_policy_user(cr, CAP_FOWNER, EPERM)); 160 } 161 162 /* 163 * Determine if subject can change group ownership of a file. 164 */ 165 int 166 secpolicy_vnode_create_gid(const cred_t *cr) 167 { 168 return (priv_policy(cr, CAP_SETGID, EPERM)); 169 } 170 171 /* 172 * Policy determines whether we can remove an entry from a directory, 173 * regardless of permission bits. 174 */ 175 int 176 secpolicy_vnode_remove(const cred_t *cr) 177 { 178 return (priv_policy(cr, CAP_FOWNER, EPERM)); 179 } 180 181 /* 182 * Determine that subject can modify the mode of a file. allzone privilege 183 * needed when modifying root owned object. 184 */ 185 int 186 secpolicy_vnode_setdac(const cred_t *cr, uid_t owner) 187 { 188 if (crgetuid(cr) == owner) 189 return (0); 190 191 #if defined(CONFIG_USER_NS) 192 if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner))) 193 return (EPERM); 194 #endif 195 196 return (priv_policy_user(cr, CAP_FOWNER, EPERM)); 197 } 198 199 /* 200 * Are we allowed to retain the set-uid/set-gid bits when 201 * changing ownership or when writing to a file? 202 * "issuid" should be true when set-uid; only in that case 203 * root ownership is checked (setgid is assumed). 204 * 205 * Enforced in the Linux VFS. 206 */ 207 int 208 secpolicy_vnode_setid_retain(struct znode *zp __maybe_unused, const cred_t *cr, 209 boolean_t issuidroot) 210 { 211 return (priv_policy_user(cr, CAP_FSETID, EPERM)); 212 } 213 214 /* 215 * Determine that subject can set the file setgid flag. 216 */ 217 int 218 secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid, zidmap_t *mnt_ns, 219 struct user_namespace *fs_ns) 220 { 221 gid = zfs_gid_to_vfsgid(mnt_ns, fs_ns, gid); 222 #if defined(CONFIG_USER_NS) 223 if (!kgid_has_mapping(cr->user_ns, SGID_TO_KGID(gid))) 224 return (EPERM); 225 #endif 226 if (crgetgid(cr) != gid && !groupmember(gid, cr)) 227 return (priv_policy_user(cr, CAP_FSETID, EPERM)); 228 229 return (0); 230 } 231 232 /* 233 * Determine if the subject can inject faults in the ZFS fault injection 234 * framework. Requires all privileges. 235 */ 236 int 237 secpolicy_zinject(const cred_t *cr) 238 { 239 return (priv_policy(cr, CAP_SYS_ADMIN, EACCES)); 240 } 241 242 /* 243 * Determine if the subject has permission to manipulate ZFS datasets 244 * (not pools). Equivalent to the SYS_MOUNT privilege. 245 */ 246 int 247 secpolicy_zfs(const cred_t *cr) 248 { 249 return (priv_policy(cr, CAP_SYS_ADMIN, EACCES)); 250 } 251 252 /* 253 * Equivalent to secpolicy_zfs(), but works even if the cred_t is not that of 254 * the current process. Takes both cred_t and proc_t so that this can work 255 * easily on all platforms. 256 */ 257 int 258 secpolicy_zfs_proc(const cred_t *cr, proc_t *proc) 259 { 260 if (!has_capability(proc, CAP_SYS_ADMIN)) 261 return (EACCES); 262 return (0); 263 } 264 265 void 266 secpolicy_setid_clear(vattr_t *vap, cred_t *cr) 267 { 268 if ((vap->va_mode & (S_ISUID | S_ISGID)) != 0 && 269 secpolicy_vnode_setid_retain(NULL, cr, 270 (vap->va_mode & S_ISUID) != 0 && 271 (vap->va_mask & AT_UID) != 0 && vap->va_uid == 0) != 0) { 272 vap->va_mask |= AT_MODE; 273 vap->va_mode &= ~(S_ISUID|S_ISGID); 274 } 275 } 276 277 /* 278 * Determine that subject can set the file setid flags. 279 */ 280 static int 281 secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner, zidmap_t *mnt_ns, 282 struct user_namespace *fs_ns) 283 { 284 owner = zfs_uid_to_vfsuid(mnt_ns, fs_ns, owner); 285 286 if (crgetuid(cr) == owner) 287 return (0); 288 289 #if defined(CONFIG_USER_NS) 290 if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner))) 291 return (EPERM); 292 #endif 293 294 return (priv_policy_user(cr, CAP_FSETID, EPERM)); 295 } 296 297 /* 298 * Determine that subject can make a file a "sticky". 299 * 300 * Enforced in the Linux VFS. 301 */ 302 static int 303 secpolicy_vnode_stky_modify(const cred_t *cr) 304 { 305 return (0); 306 } 307 308 int 309 secpolicy_setid_setsticky_clear(struct inode *ip, vattr_t *vap, 310 const vattr_t *ovap, cred_t *cr, zidmap_t *mnt_ns, 311 struct user_namespace *fs_ns) 312 { 313 int error; 314 315 if ((vap->va_mode & S_ISUID) != 0 && 316 (error = secpolicy_vnode_setid_modify(cr, 317 ovap->va_uid, mnt_ns, fs_ns)) != 0) { 318 return (error); 319 } 320 321 /* 322 * Check privilege if attempting to set the 323 * sticky bit on a non-directory. 324 */ 325 if (!S_ISDIR(ip->i_mode) && (vap->va_mode & S_ISVTX) != 0 && 326 secpolicy_vnode_stky_modify(cr) != 0) { 327 vap->va_mode &= ~S_ISVTX; 328 } 329 330 /* 331 * Check for privilege if attempting to set the 332 * group-id bit. 333 */ 334 if ((vap->va_mode & S_ISGID) != 0 && 335 secpolicy_vnode_setids_setgids(cr, ovap->va_gid, 336 mnt_ns, fs_ns) != 0) { 337 vap->va_mode &= ~S_ISGID; 338 } 339 340 return (0); 341 } 342 343 /* 344 * Check privileges for setting xvattr attributes 345 */ 346 int 347 secpolicy_xvattr(xvattr_t *xvap, uid_t owner, cred_t *cr, mode_t type) 348 { 349 return (secpolicy_vnode_chown(cr, owner)); 350 } 351 352 /* 353 * Check privileges for setattr attributes. 354 * 355 * Enforced in the Linux VFS. 356 */ 357 int 358 secpolicy_vnode_setattr(cred_t *cr, struct inode *ip, struct vattr *vap, 359 const struct vattr *ovap, int flags, 360 int unlocked_access(void *, int, cred_t *), void *node) 361 { 362 return (0); 363 } 364 365 /* 366 * Check privileges for links. 367 * 368 * Enforced in the Linux VFS. 369 */ 370 int 371 secpolicy_basic_link(const cred_t *cr) 372 { 373 return (0); 374 } 375