1800c9408SRobert Watson /*- 28a36da99SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 38a36da99SPedro F. Giffuni * 4800c9408SRobert Watson * Copyright (c) 2006 nCircle Network Security, Inc. 56efcc2f2SRobert Watson * Copyright (c) 2009 Robert N. M. Watson 6*05e1e482SMariusz Zaborski * Copyright (c) 2020 Mariusz Zaborski <oshogbo@FreeBSD.org> 7800c9408SRobert Watson * All rights reserved. 8800c9408SRobert Watson * 9800c9408SRobert Watson * This software was developed by Robert N. M. Watson for the TrustedBSD 10800c9408SRobert Watson * Project under contract to nCircle Network Security, Inc. 11800c9408SRobert Watson * 12800c9408SRobert Watson * Redistribution and use in source and binary forms, with or without 13800c9408SRobert Watson * modification, are permitted provided that the following conditions 14800c9408SRobert Watson * are met: 15800c9408SRobert Watson * 1. Redistributions of source code must retain the above copyright 16800c9408SRobert Watson * notice, this list of conditions and the following disclaimer. 17800c9408SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 18800c9408SRobert Watson * notice, this list of conditions and the following disclaimer in the 19800c9408SRobert Watson * documentation and/or other materials provided with the distribution. 20800c9408SRobert Watson * 21800c9408SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22800c9408SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23800c9408SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24800c9408SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY, 25800c9408SRobert Watson * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26800c9408SRobert Watson * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27800c9408SRobert Watson * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28800c9408SRobert Watson * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29800c9408SRobert Watson * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30800c9408SRobert Watson * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31800c9408SRobert Watson * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32800c9408SRobert Watson */ 33800c9408SRobert Watson 34b916b56bSRobert Watson #include <sys/cdefs.h> 35b916b56bSRobert Watson __FBSDID("$FreeBSD$"); 36b916b56bSRobert Watson 37800c9408SRobert Watson #include <sys/param.h> 38800c9408SRobert Watson #include <sys/jail.h> 39800c9408SRobert Watson #include <sys/kernel.h> 40*05e1e482SMariusz Zaborski #include <sys/lock.h> 41*05e1e482SMariusz Zaborski #include <sys/mutex.h> 42*05e1e482SMariusz Zaborski #include <sys/sx.h> 43800c9408SRobert Watson #include <sys/priv.h> 44800c9408SRobert Watson #include <sys/proc.h> 456efcc2f2SRobert Watson #include <sys/sdt.h> 46800c9408SRobert Watson #include <sys/sysctl.h> 47800c9408SRobert Watson #include <sys/systm.h> 48800c9408SRobert Watson 49800c9408SRobert Watson #include <security/mac/mac_framework.h> 50800c9408SRobert Watson 51800c9408SRobert Watson /* 52800c9408SRobert Watson * `suser_enabled' (which can be set by the security.bsd.suser_enabled 53800c9408SRobert Watson * sysctl) determines whether the system 'super-user' policy is in effect. If 54800c9408SRobert Watson * it is nonzero, an effective uid of 0 connotes special privilege, 55800c9408SRobert Watson * overriding many mandatory and discretionary protections. If it is zero, 56800c9408SRobert Watson * uid 0 is offered no special privilege in the kernel security policy. 57800c9408SRobert Watson * Setting it to zero may seriously impact the functionality of many existing 58800c9408SRobert Watson * userland programs, and should not be done without careful consideration of 59800c9408SRobert Watson * the consequences. 60800c9408SRobert Watson */ 61*05e1e482SMariusz Zaborski 62*05e1e482SMariusz Zaborski static bool 63*05e1e482SMariusz Zaborski suser_enabled(struct ucred *cred) 64*05e1e482SMariusz Zaborski { 65*05e1e482SMariusz Zaborski 66*05e1e482SMariusz Zaborski return (prison_allow(cred, PR_ALLOW_SUSER) ? true : false); 67*05e1e482SMariusz Zaborski } 68*05e1e482SMariusz Zaborski 69*05e1e482SMariusz Zaborski static void inline 70*05e1e482SMariusz Zaborski prison_suser_set(struct prison *pr, int enabled) 71*05e1e482SMariusz Zaborski { 72*05e1e482SMariusz Zaborski 73*05e1e482SMariusz Zaborski if (enabled) { 74*05e1e482SMariusz Zaborski pr->pr_allow |= PR_ALLOW_SUSER; 75*05e1e482SMariusz Zaborski } else { 76*05e1e482SMariusz Zaborski pr->pr_allow &= ~PR_ALLOW_SUSER; 77*05e1e482SMariusz Zaborski } 78*05e1e482SMariusz Zaborski } 79*05e1e482SMariusz Zaborski 80*05e1e482SMariusz Zaborski static int 81*05e1e482SMariusz Zaborski sysctl_kern_suser_enabled(SYSCTL_HANDLER_ARGS) 82*05e1e482SMariusz Zaborski { 83*05e1e482SMariusz Zaborski struct prison *pr, *cpr; 84*05e1e482SMariusz Zaborski struct ucred *cred; 85*05e1e482SMariusz Zaborski int descend, error, enabled; 86*05e1e482SMariusz Zaborski 87*05e1e482SMariusz Zaborski cred = req->td->td_ucred; 88*05e1e482SMariusz Zaborski enabled = suser_enabled(cred); 89*05e1e482SMariusz Zaborski 90*05e1e482SMariusz Zaborski error = sysctl_handle_int(oidp, &enabled, 0, req); 91*05e1e482SMariusz Zaborski if (error || !req->newptr) 92*05e1e482SMariusz Zaborski return (error); 93*05e1e482SMariusz Zaborski 94*05e1e482SMariusz Zaborski pr = cred->cr_prison; 95*05e1e482SMariusz Zaborski sx_slock(&allprison_lock); 96*05e1e482SMariusz Zaborski mtx_lock(&pr->pr_mtx); 97*05e1e482SMariusz Zaborski 98*05e1e482SMariusz Zaborski prison_suser_set(pr, enabled); 99*05e1e482SMariusz Zaborski if (!enabled) { 100*05e1e482SMariusz Zaborski FOREACH_PRISON_DESCENDANT_LOCKED(pr, cpr, descend) { 101*05e1e482SMariusz Zaborski prison_suser_set(cpr, 0); 102*05e1e482SMariusz Zaborski } 103*05e1e482SMariusz Zaborski } 104*05e1e482SMariusz Zaborski mtx_unlock(&pr->pr_mtx); 105*05e1e482SMariusz Zaborski sx_sunlock(&allprison_lock); 106*05e1e482SMariusz Zaborski return (0); 107*05e1e482SMariusz Zaborski } 108*05e1e482SMariusz Zaborski 109*05e1e482SMariusz Zaborski SYSCTL_PROC(_security_bsd, OID_AUTO, suser_enabled, CTLTYPE_INT | 110*05e1e482SMariusz Zaborski CTLFLAG_RWTUN | CTLFLAG_PRISON, 0, 0, &sysctl_kern_suser_enabled, "I", 111*05e1e482SMariusz Zaborski "Processes with uid 0 have privilege"); 112800c9408SRobert Watson 1135eb0d283SAndrey Zonov static int unprivileged_mlock = 1; 114af3b2549SHans Petter Selasky SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_mlock, CTLFLAG_RWTUN, 1155eb0d283SAndrey Zonov &unprivileged_mlock, 0, "Allow non-root users to call mlock(2)"); 1165eb0d283SAndrey Zonov 117b19d66fdSJamie Gritton static int unprivileged_read_msgbuf = 1; 118b19d66fdSJamie Gritton SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf, 119b19d66fdSJamie Gritton CTLFLAG_RW, &unprivileged_read_msgbuf, 0, 120b19d66fdSJamie Gritton "Unprivileged processes may read the kernel message buffer"); 121b19d66fdSJamie Gritton 1226efcc2f2SRobert Watson SDT_PROVIDER_DEFINE(priv); 123d9fae5abSAndriy Gapon SDT_PROBE_DEFINE1(priv, kernel, priv_check, priv__ok, "int"); 124d9fae5abSAndriy Gapon SDT_PROBE_DEFINE1(priv, kernel, priv_check, priv__err, "int"); 1256efcc2f2SRobert Watson 1267b2ff0dcSMateusz Guzik static __always_inline int 1277b2ff0dcSMateusz Guzik priv_check_cred_pre(struct ucred *cred, int priv) 1287b2ff0dcSMateusz Guzik { 1297b2ff0dcSMateusz Guzik int error; 1307b2ff0dcSMateusz Guzik 1317b2ff0dcSMateusz Guzik #ifdef MAC 1327b2ff0dcSMateusz Guzik error = mac_priv_check(cred, priv); 1337b2ff0dcSMateusz Guzik #else 1347b2ff0dcSMateusz Guzik error = 0; 1357b2ff0dcSMateusz Guzik #endif 1367b2ff0dcSMateusz Guzik return (error); 1377b2ff0dcSMateusz Guzik } 1387b2ff0dcSMateusz Guzik 1397b2ff0dcSMateusz Guzik static __always_inline int 1407b2ff0dcSMateusz Guzik priv_check_cred_post(struct ucred *cred, int priv, int error, bool handled) 1417b2ff0dcSMateusz Guzik { 1427b2ff0dcSMateusz Guzik 1437b2ff0dcSMateusz Guzik if (__predict_true(handled)) 1447b2ff0dcSMateusz Guzik goto out; 1457b2ff0dcSMateusz Guzik /* 1467b2ff0dcSMateusz Guzik * Now check with MAC, if enabled, to see if a policy module grants 1477b2ff0dcSMateusz Guzik * privilege. 1487b2ff0dcSMateusz Guzik */ 1497b2ff0dcSMateusz Guzik #ifdef MAC 1507b2ff0dcSMateusz Guzik if (mac_priv_grant(cred, priv) == 0) { 1517b2ff0dcSMateusz Guzik error = 0; 1527b2ff0dcSMateusz Guzik goto out; 1537b2ff0dcSMateusz Guzik } 1547b2ff0dcSMateusz Guzik #endif 1557b2ff0dcSMateusz Guzik 1567b2ff0dcSMateusz Guzik /* 1577b2ff0dcSMateusz Guzik * The default is deny, so if no policies have granted it, reject 1587b2ff0dcSMateusz Guzik * with a privilege error here. 1597b2ff0dcSMateusz Guzik */ 1607b2ff0dcSMateusz Guzik error = EPERM; 1617b2ff0dcSMateusz Guzik out: 1627b2ff0dcSMateusz Guzik if (SDT_PROBES_ENABLED()) { 1637b2ff0dcSMateusz Guzik if (error) 1647b2ff0dcSMateusz Guzik SDT_PROBE1(priv, kernel, priv_check, priv__err, priv); 1657b2ff0dcSMateusz Guzik else 1667b2ff0dcSMateusz Guzik SDT_PROBE1(priv, kernel, priv_check, priv__ok, priv); 1677b2ff0dcSMateusz Guzik } 1687b2ff0dcSMateusz Guzik return (error); 1697b2ff0dcSMateusz Guzik } 1707b2ff0dcSMateusz Guzik 171800c9408SRobert Watson /* 172800c9408SRobert Watson * Check a credential for privilege. Lots of good reasons to deny privilege; 173800c9408SRobert Watson * only a few to grant it. 174800c9408SRobert Watson */ 175800c9408SRobert Watson int 176cc426dd3SMateusz Guzik priv_check_cred(struct ucred *cred, int priv) 177800c9408SRobert Watson { 178800c9408SRobert Watson int error; 179800c9408SRobert Watson 180800c9408SRobert Watson KASSERT(PRIV_VALID(priv), ("priv_check_cred: invalid privilege %d", 181800c9408SRobert Watson priv)); 182800c9408SRobert Watson 1837b2ff0dcSMateusz Guzik switch (priv) { 184a459a6cfSMateusz Guzik case PRIV_VFS_LOOKUP: 185a459a6cfSMateusz Guzik return (priv_check_cred_vfs_lookup(cred)); 1867b2ff0dcSMateusz Guzik case PRIV_VFS_GENERATION: 1877b2ff0dcSMateusz Guzik return (priv_check_cred_vfs_generation(cred)); 1887b2ff0dcSMateusz Guzik } 1897b2ff0dcSMateusz Guzik 1907251b786SRobert Watson /* 1917251b786SRobert Watson * We first evaluate policies that may deny the granting of 1927251b786SRobert Watson * privilege unilaterally. 1937251b786SRobert Watson */ 1947b2ff0dcSMateusz Guzik error = priv_check_cred_pre(cred, priv); 195800c9408SRobert Watson if (error) 1966efcc2f2SRobert Watson goto out; 197800c9408SRobert Watson 198800c9408SRobert Watson /* 199800c9408SRobert Watson * Jail policy will restrict certain privileges that may otherwise be 200800c9408SRobert Watson * be granted. 201800c9408SRobert Watson */ 202800c9408SRobert Watson error = prison_priv_check(cred, priv); 203800c9408SRobert Watson if (error) 2046efcc2f2SRobert Watson goto out; 205800c9408SRobert Watson 2065eb0d283SAndrey Zonov if (unprivileged_mlock) { 2075eb0d283SAndrey Zonov /* 2085eb0d283SAndrey Zonov * Allow unprivileged users to call mlock(2)/munlock(2) and 2095eb0d283SAndrey Zonov * mlockall(2)/munlockall(2). 2105eb0d283SAndrey Zonov */ 2115eb0d283SAndrey Zonov switch (priv) { 2125eb0d283SAndrey Zonov case PRIV_VM_MLOCK: 2135eb0d283SAndrey Zonov case PRIV_VM_MUNLOCK: 2145eb0d283SAndrey Zonov error = 0; 2155eb0d283SAndrey Zonov goto out; 2165eb0d283SAndrey Zonov } 2175eb0d283SAndrey Zonov } 2185eb0d283SAndrey Zonov 219b19d66fdSJamie Gritton if (unprivileged_read_msgbuf) { 220b19d66fdSJamie Gritton /* 221b19d66fdSJamie Gritton * Allow an unprivileged user to read the kernel message 222b19d66fdSJamie Gritton * buffer. 223b19d66fdSJamie Gritton */ 224b19d66fdSJamie Gritton if (priv == PRIV_MSGBUF) { 225b19d66fdSJamie Gritton error = 0; 226b19d66fdSJamie Gritton goto out; 227b19d66fdSJamie Gritton } 228b19d66fdSJamie Gritton } 229b19d66fdSJamie Gritton 230800c9408SRobert Watson /* 231800c9408SRobert Watson * Having determined if privilege is restricted by various policies, 2327251b786SRobert Watson * now determine if privilege is granted. At this point, any policy 2337251b786SRobert Watson * may grant privilege. For now, we allow short-circuit boolean 2347251b786SRobert Watson * evaluation, so may not call all policies. Perhaps we should. 235800c9408SRobert Watson * 236800c9408SRobert Watson * Superuser policy grants privilege based on the effective (or in 2377251b786SRobert Watson * the case of specific privileges, real) uid being 0. We allow the 2387251b786SRobert Watson * superuser policy to be globally disabled, although this is 2397251b786SRobert Watson * currenty of limited utility. 240800c9408SRobert Watson */ 241*05e1e482SMariusz Zaborski if (suser_enabled(cred)) { 2427251b786SRobert Watson switch (priv) { 2437251b786SRobert Watson case PRIV_MAXFILES: 2447251b786SRobert Watson case PRIV_MAXPROC: 2457251b786SRobert Watson case PRIV_PROC_LIMIT: 2466efcc2f2SRobert Watson if (cred->cr_ruid == 0) { 2476efcc2f2SRobert Watson error = 0; 2486efcc2f2SRobert Watson goto out; 2496efcc2f2SRobert Watson } 2507251b786SRobert Watson break; 25163619b6dSKyle Evans case PRIV_VFS_READ_DIR: 25263619b6dSKyle Evans /* 25363619b6dSKyle Evans * Allow PRIV_VFS_READ_DIR for root if we're not in a 25463619b6dSKyle Evans * jail, otherwise deny unless a MAC policy grants it. 25563619b6dSKyle Evans */ 25663619b6dSKyle Evans if (jailed(cred)) 25763619b6dSKyle Evans break; 25863619b6dSKyle Evans /* FALLTHROUGH */ 2597251b786SRobert Watson default: 2606efcc2f2SRobert Watson if (cred->cr_uid == 0) { 2616efcc2f2SRobert Watson error = 0; 2626efcc2f2SRobert Watson goto out; 2636efcc2f2SRobert Watson } 2647251b786SRobert Watson break; 265800c9408SRobert Watson } 266800c9408SRobert Watson } 267800c9408SRobert Watson 268800c9408SRobert Watson /* 2691e7df843SJamie Gritton * Writes to kernel/physical memory are a typical root-only operation, 2701e7df843SJamie Gritton * but non-root users are expected to be able to read it (provided they 2711e7df843SJamie Gritton * have permission to access /dev/[k]mem). 272c71e3362SJamie Gritton */ 273c71e3362SJamie Gritton if (priv == PRIV_KMEM_READ) { 274c71e3362SJamie Gritton error = 0; 275c71e3362SJamie Gritton goto out; 276c71e3362SJamie Gritton } 277c71e3362SJamie Gritton 278c71e3362SJamie Gritton /* 279b3079544SJamie Gritton * Allow unprivileged process debugging on a per-jail basis. 280b3079544SJamie Gritton * Do this here instead of prison_priv_check(), so it can also 281b3079544SJamie Gritton * apply to prison0. 282b3079544SJamie Gritton */ 283b3079544SJamie Gritton if (priv == PRIV_DEBUG_UNPRIV) { 284b3079544SJamie Gritton if (prison_allow(cred, PR_ALLOW_UNPRIV_DEBUG)) { 285b3079544SJamie Gritton error = 0; 286b3079544SJamie Gritton goto out; 287b3079544SJamie Gritton } 288b3079544SJamie Gritton } 289b3079544SJamie Gritton 2907b2ff0dcSMateusz Guzik return (priv_check_cred_post(cred, priv, error, false)); 2916efcc2f2SRobert Watson out: 2927b2ff0dcSMateusz Guzik return (priv_check_cred_post(cred, priv, error, true)); 293800c9408SRobert Watson } 294800c9408SRobert Watson 295800c9408SRobert Watson int 296800c9408SRobert Watson priv_check(struct thread *td, int priv) 297800c9408SRobert Watson { 298800c9408SRobert Watson 299800c9408SRobert Watson KASSERT(td == curthread, ("priv_check: td != curthread")); 300800c9408SRobert Watson 301cc426dd3SMateusz Guzik return (priv_check_cred(td->td_ucred, priv)); 302800c9408SRobert Watson } 3037b2ff0dcSMateusz Guzik 30495275911SMateusz Guzik static int __noinline 305a459a6cfSMateusz Guzik priv_check_cred_vfs_lookup_slow(struct ucred *cred) 306a459a6cfSMateusz Guzik { 307a459a6cfSMateusz Guzik int error; 308a459a6cfSMateusz Guzik 309a459a6cfSMateusz Guzik error = priv_check_cred_pre(cred, PRIV_VFS_LOOKUP); 310a459a6cfSMateusz Guzik if (error) 311a459a6cfSMateusz Guzik goto out; 312a459a6cfSMateusz Guzik 313*05e1e482SMariusz Zaborski if (cred->cr_uid == 0 && suser_enabled(cred)) { 314a459a6cfSMateusz Guzik error = 0; 315a459a6cfSMateusz Guzik goto out; 316a459a6cfSMateusz Guzik } 317a459a6cfSMateusz Guzik 318a459a6cfSMateusz Guzik return (priv_check_cred_post(cred, PRIV_VFS_LOOKUP, error, false)); 319a459a6cfSMateusz Guzik out: 320a459a6cfSMateusz Guzik return (priv_check_cred_post(cred, PRIV_VFS_LOOKUP, error, true)); 321a459a6cfSMateusz Guzik 322a459a6cfSMateusz Guzik } 323a459a6cfSMateusz Guzik 324a459a6cfSMateusz Guzik int 325a459a6cfSMateusz Guzik priv_check_cred_vfs_lookup(struct ucred *cred) 326a459a6cfSMateusz Guzik { 327a459a6cfSMateusz Guzik int error; 328a459a6cfSMateusz Guzik 329a459a6cfSMateusz Guzik if (__predict_false(mac_priv_check_fp_flag || 330a459a6cfSMateusz Guzik mac_priv_grant_fp_flag || SDT_PROBES_ENABLED())) 331a459a6cfSMateusz Guzik return (priv_check_cred_vfs_lookup_slow(cred)); 332a459a6cfSMateusz Guzik 333a459a6cfSMateusz Guzik error = EPERM; 334*05e1e482SMariusz Zaborski if (cred->cr_uid == 0 && suser_enabled(cred)) 335a459a6cfSMateusz Guzik error = 0; 336a459a6cfSMateusz Guzik return (error); 337a459a6cfSMateusz Guzik } 338a459a6cfSMateusz Guzik 339a459a6cfSMateusz Guzik int 340a459a6cfSMateusz Guzik priv_check_cred_vfs_lookup_nomac(struct ucred *cred) 341a459a6cfSMateusz Guzik { 342a459a6cfSMateusz Guzik int error; 343a459a6cfSMateusz Guzik 344a459a6cfSMateusz Guzik if (__predict_false(mac_priv_check_fp_flag || 345a459a6cfSMateusz Guzik mac_priv_grant_fp_flag || SDT_PROBES_ENABLED())) 346a459a6cfSMateusz Guzik return (EAGAIN); 347a459a6cfSMateusz Guzik 348a459a6cfSMateusz Guzik error = EPERM; 349*05e1e482SMariusz Zaborski if (cred->cr_uid == 0 && suser_enabled(cred)) 350a459a6cfSMateusz Guzik error = 0; 351a459a6cfSMateusz Guzik return (error); 352a459a6cfSMateusz Guzik } 353a459a6cfSMateusz Guzik 354a459a6cfSMateusz Guzik static int __noinline 35595275911SMateusz Guzik priv_check_cred_vfs_generation_slow(struct ucred *cred) 3567b2ff0dcSMateusz Guzik { 3577b2ff0dcSMateusz Guzik int error; 3587b2ff0dcSMateusz Guzik 3597b2ff0dcSMateusz Guzik error = priv_check_cred_pre(cred, PRIV_VFS_GENERATION); 3607b2ff0dcSMateusz Guzik if (error) 3617b2ff0dcSMateusz Guzik goto out; 3627b2ff0dcSMateusz Guzik 3637b2ff0dcSMateusz Guzik if (jailed(cred)) { 3647b2ff0dcSMateusz Guzik error = EPERM; 3657b2ff0dcSMateusz Guzik goto out; 3667b2ff0dcSMateusz Guzik } 3677b2ff0dcSMateusz Guzik 368*05e1e482SMariusz Zaborski if (cred->cr_uid == 0 && suser_enabled(cred)) { 3697b2ff0dcSMateusz Guzik error = 0; 3707b2ff0dcSMateusz Guzik goto out; 3717b2ff0dcSMateusz Guzik } 3727b2ff0dcSMateusz Guzik 3737b2ff0dcSMateusz Guzik return (priv_check_cred_post(cred, PRIV_VFS_GENERATION, error, false)); 3747b2ff0dcSMateusz Guzik out: 3757b2ff0dcSMateusz Guzik return (priv_check_cred_post(cred, PRIV_VFS_GENERATION, error, true)); 3767b2ff0dcSMateusz Guzik 3777b2ff0dcSMateusz Guzik } 37895275911SMateusz Guzik 37995275911SMateusz Guzik int 38095275911SMateusz Guzik priv_check_cred_vfs_generation(struct ucred *cred) 38195275911SMateusz Guzik { 38295275911SMateusz Guzik int error; 38395275911SMateusz Guzik 38495275911SMateusz Guzik if (__predict_false(mac_priv_check_fp_flag || 38595275911SMateusz Guzik mac_priv_grant_fp_flag || SDT_PROBES_ENABLED())) 38695275911SMateusz Guzik return (priv_check_cred_vfs_generation_slow(cred)); 38795275911SMateusz Guzik 38895275911SMateusz Guzik error = EPERM; 389*05e1e482SMariusz Zaborski if (!jailed(cred) && cred->cr_uid == 0 && suser_enabled(cred)) 39095275911SMateusz Guzik error = 0; 39195275911SMateusz Guzik return (error); 39295275911SMateusz Guzik } 393