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 6800c9408SRobert Watson * All rights reserved. 7800c9408SRobert Watson * 8800c9408SRobert Watson * This software was developed by Robert N. M. Watson for the TrustedBSD 9800c9408SRobert Watson * Project under contract to nCircle Network Security, Inc. 10800c9408SRobert Watson * 11800c9408SRobert Watson * Redistribution and use in source and binary forms, with or without 12800c9408SRobert Watson * modification, are permitted provided that the following conditions 13800c9408SRobert Watson * are met: 14800c9408SRobert Watson * 1. Redistributions of source code must retain the above copyright 15800c9408SRobert Watson * notice, this list of conditions and the following disclaimer. 16800c9408SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 17800c9408SRobert Watson * notice, this list of conditions and the following disclaimer in the 18800c9408SRobert Watson * documentation and/or other materials provided with the distribution. 19800c9408SRobert Watson * 20800c9408SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21800c9408SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22800c9408SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23800c9408SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY, 24800c9408SRobert Watson * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25800c9408SRobert Watson * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 26800c9408SRobert Watson * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27800c9408SRobert Watson * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28800c9408SRobert Watson * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29800c9408SRobert Watson * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30800c9408SRobert Watson * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31800c9408SRobert Watson */ 32800c9408SRobert Watson 33b916b56bSRobert Watson #include <sys/cdefs.h> 34b916b56bSRobert Watson __FBSDID("$FreeBSD$"); 35b916b56bSRobert Watson 36800c9408SRobert Watson #include <sys/param.h> 37800c9408SRobert Watson #include <sys/jail.h> 38800c9408SRobert Watson #include <sys/kernel.h> 39800c9408SRobert Watson #include <sys/priv.h> 40800c9408SRobert Watson #include <sys/proc.h> 416efcc2f2SRobert Watson #include <sys/sdt.h> 42800c9408SRobert Watson #include <sys/sysctl.h> 43800c9408SRobert Watson #include <sys/systm.h> 44800c9408SRobert Watson 45800c9408SRobert Watson #include <security/mac/mac_framework.h> 46800c9408SRobert Watson 47800c9408SRobert Watson /* 48800c9408SRobert Watson * `suser_enabled' (which can be set by the security.bsd.suser_enabled 49800c9408SRobert Watson * sysctl) determines whether the system 'super-user' policy is in effect. If 50800c9408SRobert Watson * it is nonzero, an effective uid of 0 connotes special privilege, 51800c9408SRobert Watson * overriding many mandatory and discretionary protections. If it is zero, 52800c9408SRobert Watson * uid 0 is offered no special privilege in the kernel security policy. 53800c9408SRobert Watson * Setting it to zero may seriously impact the functionality of many existing 54800c9408SRobert Watson * userland programs, and should not be done without careful consideration of 55800c9408SRobert Watson * the consequences. 56800c9408SRobert Watson */ 57bc6eca24SRobert Watson static int suser_enabled = 1; 58af3b2549SHans Petter Selasky SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RWTUN, 59800c9408SRobert Watson &suser_enabled, 0, "processes with uid 0 have privilege"); 60800c9408SRobert Watson 615eb0d283SAndrey Zonov static int unprivileged_mlock = 1; 62af3b2549SHans Petter Selasky SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_mlock, CTLFLAG_RWTUN, 635eb0d283SAndrey Zonov &unprivileged_mlock, 0, "Allow non-root users to call mlock(2)"); 645eb0d283SAndrey Zonov 65b19d66fdSJamie Gritton static int unprivileged_read_msgbuf = 1; 66b19d66fdSJamie Gritton SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf, 67b19d66fdSJamie Gritton CTLFLAG_RW, &unprivileged_read_msgbuf, 0, 68b19d66fdSJamie Gritton "Unprivileged processes may read the kernel message buffer"); 69b19d66fdSJamie Gritton 706efcc2f2SRobert Watson SDT_PROVIDER_DEFINE(priv); 71d9fae5abSAndriy Gapon SDT_PROBE_DEFINE1(priv, kernel, priv_check, priv__ok, "int"); 72d9fae5abSAndriy Gapon SDT_PROBE_DEFINE1(priv, kernel, priv_check, priv__err, "int"); 736efcc2f2SRobert Watson 74800c9408SRobert Watson /* 75800c9408SRobert Watson * Check a credential for privilege. Lots of good reasons to deny privilege; 76800c9408SRobert Watson * only a few to grant it. 77800c9408SRobert Watson */ 78800c9408SRobert Watson int 79cc426dd3SMateusz Guzik priv_check_cred(struct ucred *cred, int priv) 80800c9408SRobert Watson { 81800c9408SRobert Watson int error; 82800c9408SRobert Watson 83800c9408SRobert Watson KASSERT(PRIV_VALID(priv), ("priv_check_cred: invalid privilege %d", 84800c9408SRobert Watson priv)); 85800c9408SRobert Watson 867251b786SRobert Watson /* 877251b786SRobert Watson * We first evaluate policies that may deny the granting of 887251b786SRobert Watson * privilege unilaterally. 897251b786SRobert Watson */ 90800c9408SRobert Watson #ifdef MAC 91800c9408SRobert Watson error = mac_priv_check(cred, priv); 92800c9408SRobert Watson if (error) 936efcc2f2SRobert Watson goto out; 94800c9408SRobert Watson #endif 95800c9408SRobert Watson 96800c9408SRobert Watson /* 97800c9408SRobert Watson * Jail policy will restrict certain privileges that may otherwise be 98800c9408SRobert Watson * be granted. 99800c9408SRobert Watson */ 100800c9408SRobert Watson error = prison_priv_check(cred, priv); 101800c9408SRobert Watson if (error) 1026efcc2f2SRobert Watson goto out; 103800c9408SRobert Watson 1045eb0d283SAndrey Zonov if (unprivileged_mlock) { 1055eb0d283SAndrey Zonov /* 1065eb0d283SAndrey Zonov * Allow unprivileged users to call mlock(2)/munlock(2) and 1075eb0d283SAndrey Zonov * mlockall(2)/munlockall(2). 1085eb0d283SAndrey Zonov */ 1095eb0d283SAndrey Zonov switch (priv) { 1105eb0d283SAndrey Zonov case PRIV_VM_MLOCK: 1115eb0d283SAndrey Zonov case PRIV_VM_MUNLOCK: 1125eb0d283SAndrey Zonov error = 0; 1135eb0d283SAndrey Zonov goto out; 1145eb0d283SAndrey Zonov } 1155eb0d283SAndrey Zonov } 1165eb0d283SAndrey Zonov 117b19d66fdSJamie Gritton if (unprivileged_read_msgbuf) { 118b19d66fdSJamie Gritton /* 119b19d66fdSJamie Gritton * Allow an unprivileged user to read the kernel message 120b19d66fdSJamie Gritton * buffer. 121b19d66fdSJamie Gritton */ 122b19d66fdSJamie Gritton if (priv == PRIV_MSGBUF) { 123b19d66fdSJamie Gritton error = 0; 124b19d66fdSJamie Gritton goto out; 125b19d66fdSJamie Gritton } 126b19d66fdSJamie Gritton } 127b19d66fdSJamie Gritton 128800c9408SRobert Watson /* 129800c9408SRobert Watson * Having determined if privilege is restricted by various policies, 1307251b786SRobert Watson * now determine if privilege is granted. At this point, any policy 1317251b786SRobert Watson * may grant privilege. For now, we allow short-circuit boolean 1327251b786SRobert Watson * evaluation, so may not call all policies. Perhaps we should. 133800c9408SRobert Watson * 134800c9408SRobert Watson * Superuser policy grants privilege based on the effective (or in 1357251b786SRobert Watson * the case of specific privileges, real) uid being 0. We allow the 1367251b786SRobert Watson * superuser policy to be globally disabled, although this is 1377251b786SRobert Watson * currenty of limited utility. 138800c9408SRobert Watson */ 139800c9408SRobert Watson if (suser_enabled) { 1407251b786SRobert Watson switch (priv) { 1417251b786SRobert Watson case PRIV_MAXFILES: 1427251b786SRobert Watson case PRIV_MAXPROC: 1437251b786SRobert Watson case PRIV_PROC_LIMIT: 1446efcc2f2SRobert Watson if (cred->cr_ruid == 0) { 1456efcc2f2SRobert Watson error = 0; 1466efcc2f2SRobert Watson goto out; 1476efcc2f2SRobert Watson } 1487251b786SRobert Watson break; 1497251b786SRobert Watson default: 1506efcc2f2SRobert Watson if (cred->cr_uid == 0) { 1516efcc2f2SRobert Watson error = 0; 1526efcc2f2SRobert Watson goto out; 1536efcc2f2SRobert Watson } 1547251b786SRobert Watson break; 155800c9408SRobert Watson } 156800c9408SRobert Watson } 157800c9408SRobert Watson 158800c9408SRobert Watson /* 1591e7df843SJamie Gritton * Writes to kernel/physical memory are a typical root-only operation, 1601e7df843SJamie Gritton * but non-root users are expected to be able to read it (provided they 1611e7df843SJamie Gritton * have permission to access /dev/[k]mem). 162c71e3362SJamie Gritton */ 163c71e3362SJamie Gritton if (priv == PRIV_KMEM_READ) { 164c71e3362SJamie Gritton error = 0; 165c71e3362SJamie Gritton goto out; 166c71e3362SJamie Gritton } 167c71e3362SJamie Gritton 168c71e3362SJamie Gritton /* 169b3079544SJamie Gritton * Allow unprivileged process debugging on a per-jail basis. 170b3079544SJamie Gritton * Do this here instead of prison_priv_check(), so it can also 171b3079544SJamie Gritton * apply to prison0. 172b3079544SJamie Gritton */ 173b3079544SJamie Gritton if (priv == PRIV_DEBUG_UNPRIV) { 174b3079544SJamie Gritton if (prison_allow(cred, PR_ALLOW_UNPRIV_DEBUG)) { 175b3079544SJamie Gritton error = 0; 176b3079544SJamie Gritton goto out; 177b3079544SJamie Gritton } 178b3079544SJamie Gritton } 179b3079544SJamie Gritton 180b3079544SJamie Gritton /* 181800c9408SRobert Watson * Now check with MAC, if enabled, to see if a policy module grants 182800c9408SRobert Watson * privilege. 183800c9408SRobert Watson */ 184800c9408SRobert Watson #ifdef MAC 1856efcc2f2SRobert Watson if (mac_priv_grant(cred, priv) == 0) { 1866efcc2f2SRobert Watson error = 0; 1876efcc2f2SRobert Watson goto out; 1886efcc2f2SRobert Watson } 189800c9408SRobert Watson #endif 1906efcc2f2SRobert Watson 1916efcc2f2SRobert Watson /* 1926efcc2f2SRobert Watson * The default is deny, so if no policies have granted it, reject 1936efcc2f2SRobert Watson * with a privilege error here. 1946efcc2f2SRobert Watson */ 1956efcc2f2SRobert Watson error = EPERM; 1966efcc2f2SRobert Watson out: 1979b1040a5SPawel Jakub Dawidek if (error) 198d9fae5abSAndriy Gapon SDT_PROBE1(priv, kernel, priv_check, priv__err, priv); 1999b1040a5SPawel Jakub Dawidek else 200d9fae5abSAndriy Gapon SDT_PROBE1(priv, kernel, priv_check, priv__ok, priv); 2016efcc2f2SRobert Watson return (error); 202800c9408SRobert Watson } 203800c9408SRobert Watson 204800c9408SRobert Watson int 205800c9408SRobert Watson priv_check(struct thread *td, int priv) 206800c9408SRobert Watson { 207800c9408SRobert Watson 208800c9408SRobert Watson KASSERT(td == curthread, ("priv_check: td != curthread")); 209800c9408SRobert Watson 210cc426dd3SMateusz Guzik return (priv_check_cred(td->td_ucred, priv)); 211800c9408SRobert Watson } 212