diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 92511fbcc1c..574464aecef 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1224,6 +1224,7 @@ options MAC_NONE options MAC_NTPD options MAC_PARTITION options MAC_PORTACL +options MAC_READ_DIR options MAC_SEEOTHERUIDS options MAC_STUB options MAC_TEST diff --git a/sys/conf/files b/sys/conf/files index 9d6642bf952..780eeba71a7 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -4909,6 +4909,7 @@ security/mac_none/mac_none.c optional mac_none security/mac_ntpd/mac_ntpd.c optional mac_ntpd security/mac_partition/mac_partition.c optional mac_partition security/mac_portacl/mac_portacl.c optional mac_portacl +security/mac_read_dir/mac_read_dir.c optional mac_read_dir security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids security/mac_stub/mac_stub.c optional mac_stub security/mac_test/mac_test.c optional mac_test diff --git a/sys/conf/options b/sys/conf/options index b458a3828c2..cd8f28704c3 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -159,6 +159,7 @@ MAC_NONE opt_dontuse.h MAC_NTPD opt_dontuse.h MAC_PARTITION opt_dontuse.h MAC_PORTACL opt_dontuse.h +MAC_READ_DIR opt_dontuse.h MAC_SEEOTHERUIDS opt_dontuse.h MAC_STATIC opt_mac.h MAC_STUB opt_dontuse.h diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index b71bcd7dd1b..e09a2b66c64 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -3323,6 +3323,14 @@ prison_priv_check(struct ucred *cred, int priv) else return (EPERM); + /* + * Jails should hold no disposition on the PRIV_VFS_READ_DIR + * policy. priv_check_cred will not specifically allow it, and + * we may want a MAC policy to allow it. + */ + case PRIV_VFS_READ_DIR: + return (0); + /* * Conditionnaly allow locking (unlocking) physical pages * in memory. diff --git a/sys/kern/kern_priv.c b/sys/kern/kern_priv.c index 58ce6cf342a..266dcae8747 100644 --- a/sys/kern/kern_priv.c +++ b/sys/kern/kern_priv.c @@ -194,6 +194,13 @@ priv_check_cred(struct ucred *cred, int priv) goto out; } break; + case PRIV_VFS_READ_DIR: + /* + * Allow PRIV_VFS_READ_DIR for root if we're not in a + * jail, otherwise deny unless a MAC policy grants it. + */ + if (jailed(cred)) + break; default: if (cred->cr_uid == 0) { error = 0; diff --git a/sys/modules/mac_read_dir/Makefile b/sys/modules/mac_read_dir/Makefile new file mode 100644 index 00000000000..df082d9fa67 --- /dev/null +++ b/sys/modules/mac_read_dir/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/security/mac_read_dir + +KMOD= mac_read_dir +SRCS= mac_read_dir.c + +.include diff --git a/sys/security/mac_read_dir/mac_read_dir.c b/sys/security/mac_read_dir/mac_read_dir.c new file mode 100644 index 00000000000..884bd2b022f --- /dev/null +++ b/sys/security/mac_read_dir/mac_read_dir.c @@ -0,0 +1,78 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Kyle Evans + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +SYSCTL_DECL(_security_mac); + +static SYSCTL_NODE(_security_mac, OID_AUTO, read_dir, + CTLFLAG_RW | CTLFLAG_MPSAFE, 0, + "mac_read_dir policy controls"); + +static int read_dir_enabled = 1; +SYSCTL_INT(_security_mac_read_dir, OID_AUTO, enabled, CTLFLAG_RWTUN, + &read_dir_enabled, 0, "Enable mac_read_dir policy"); + +static int read_dir_jail_root; +SYSCTL_INT(_security_mac_read_dir, OID_AUTO, jail_root, CTLFLAG_RWTUN, + &read_dir_jail_root, 0, "Allow jailed root to read directories"); + +static int read_dir_all_users; +SYSCTL_INT(_security_mac_read_dir, OID_AUTO, all_users, CTLFLAG_RWTUN, + &read_dir_all_users, 0, "Allow all users to read directories"); + +static int +read_dir_priv_grant(struct ucred *cred, int priv) +{ + + if (!read_dir_enabled || priv != PRIV_VFS_READ_DIR) + return (EPERM); + + if (read_dir_all_users) + return (0); + if (read_dir_jail_root && jailed(cred) && cred->cr_uid == 0) + return (0); + return (EPERM); +} + +static struct mac_policy_ops read_dir_ops = +{ + .mpo_priv_grant = read_dir_priv_grant, +}; + +MAC_POLICY_SET(&read_dir_ops, mac_read_dir, "MAC/read_dir", + MPC_LOADTIME_FLAG_UNLOADOK, NULL);