Index: head/contrib/ntp/ntpd/ntpd.c =================================================================== --- head/contrib/ntp/ntpd/ntpd.c +++ head/contrib/ntp/ntpd/ntpd.c @@ -123,6 +123,9 @@ #if defined(HAVE_PRIV_H) && defined(HAVE_SOLARIS_PRIVS) # include #endif /* HAVE_PRIV_H */ +#if defined(HAVE_TRUSTEDBSD_MAC) +# include +#endif /* HAVE_TRUSTEDBSD_MAC */ #endif /* HAVE_DROPROOT */ #if defined (LIBSECCOMP) && (KERN_SECCOMP) @@ -634,7 +637,12 @@ /* MPE lacks the concept of root */ # if defined(HAVE_GETUID) && !defined(MPE) uid = getuid(); - if (uid && !HAVE_OPT( SAVECONFIGQUIT )) { + if (uid && !HAVE_OPT( SAVECONFIGQUIT ) +# if defined(HAVE_TRUSTEDBSD_MAC) + /* We can run as non-root if the mac_ntpd policy is enabled. */ + && mac_is_present("ntpd") != 1 +# endif + ) { msyslog_term = TRUE; msyslog(LOG_ERR, "must be run as root, not uid %ld", (long)uid); @@ -1082,7 +1090,17 @@ exit (-1); } -# if !defined(HAVE_LINUX_CAPABILITIES) && !defined(HAVE_SOLARIS_PRIVS) +# if defined(HAVE_TRUSTEDBSD_MAC) + /* + * To manipulate system time and (re-)bind to NTP_PORT as needed + * following interface changes, we must either run as uid 0 or + * the mac_ntpd policy module must be enabled. + */ + if (sw_uid != 0 && mac_is_present("ntpd") != 1) { + msyslog(LOG_ERR, "Need MAC 'ntpd' policy enabled to drop root privileges"); + exit (-1); + } +# elif !defined(HAVE_LINUX_CAPABILITIES) && !defined(HAVE_SOLARIS_PRIVS) /* * for now assume that the privilege to bind to privileged ports * is associated with running with uid 0 - should be refined on Index: head/etc/group =================================================================== --- head/etc/group +++ head/etc/group @@ -29,6 +29,7 @@ network:*:69: audit:*:77: www:*:80: +ntpd:*:123: _ypldap:*:160: hast:*:845: nogroup:*:65533: Index: head/etc/master.passwd =================================================================== --- head/etc/master.passwd +++ head/etc/master.passwd @@ -22,6 +22,7 @@ pop:*:68:6::0:0:Post Office Owner:/nonexistent:/usr/sbin/nologin auditdistd:*:78:77::0:0:Auditdistd unprivileged user:/var/empty:/usr/sbin/nologin www:*:80:80::0:0:World Wide Web Owner:/nonexistent:/usr/sbin/nologin +ntpd:*:123:123::0:0:NTP Daemon:/var/db/ntp:/usr/sbin/nologin _ypldap:*:160:160::0:0:YP LDAP unprivileged user:/var/empty:/usr/sbin/nologin hast:*:845:845::0:0:HAST unprivileged user:/var/empty:/usr/sbin/nologin nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/usr/sbin/nologin Index: head/etc/mtree/BSD.var.dist =================================================================== --- head/etc/mtree/BSD.var.dist +++ head/etc/mtree/BSD.var.dist @@ -46,7 +46,7 @@ .. ipf mode=0700 .. - ntp mode=0700 + ntp uname=ntpd gname=ntpd .. pkg .. Index: head/share/man/man4/mac_ntpd.4 =================================================================== --- head/share/man/man4/mac_ntpd.4 +++ head/share/man/man4/mac_ntpd.4 @@ -0,0 +1,116 @@ +.\" Copyright (c) 2018 Ian Lepore +.\" +.\" 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 AUTHORS 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 AUTHORS 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$ +.\" +.Dd June 28, 2018 +.Dt MAC_NTPD 4 +.Os +.Sh NAME +.Nm mac_ntpd +.Nd "policy allowing ntpd to run as non-root user" +.Sh SYNOPSIS +To compile the ntpd policy into your kernel, place the following lines +in your kernel configuration file: +.Bd -ragged -offset indent +.Cd "options MAC" +.Cd "options MAC_NTPD" +.Ed +.Pp +Alternately, to load the ntpd policy module at boot time, +place the following line in your kernel configuration file: +.Bd -ragged -offset indent +.Cd "options MAC" +.Ed +.Pp +and in +.Xr loader.conf 5 : +.Pp +.Dl "mac_ntpd_load=""YES""" +.Sh DESCRIPTION +The +.Nm +policy grants any process running as user +.Sq ntpd +(uid 123) the privileges needed to manipulate +system time, and to (re-)bind to the privileged NTP port. +.Pp +When +.Xr ntpd 8 +is started with +.Sq -u\ +on the command line, it performs all initializations requiring root +privileges, then drops root privileges by switching to the given user id. +From that point on, the only privileges it requires are the ability +to manipulate system time, and the ability to re-bind a UDP socket +to the NTP port (port 123) after a network interface change. +By default, +.Fx +starts +.Xr ntpd 8 +with +.Sq -u\ ntpd:ntpd +on the command line, if the mac_ntpd policy is available to grant +the required privileges. +.Pp +.Ss Privileges Granted +The exact set of kernel privileges granted to any process running +with the configured uid is: +.Bl -inset -compact -offset indent +.It PRIV_ADJTIME +.It PRIV_CLOCK_SETTIME +.It PRIV_NTP_ADJTIME +.It PRIV_NETINET_RESERVEDPORT +.It PRIV_NETINET_REUSEPORT +.El +.Pp +.Ss Runtime Configuration +The following +.Xr sysctl 8 +MIBs are available for fine-tuning this MAC policy. +All +.Xr sysctl 8 +variables can also be set as +.Xr loader 8 +tunables in +.Xr loader.conf 5 . +.Bl -tag -width indent +.It Va security.mac.ntpd.enabled +Enable the +.Nm +policy. +(Default: 1). +.It Va security.mac.ntpd.uid +The numeric uid of the ntpd user. +(Default: 123). +.El +.Sh SEE ALSO +.Xr mac 4 , +.Xr ntpd 8 +.Sh HISTORY +MAC first appeared in +.Fx 5.0 +and +.Nm +first appeared in +.Fx 12.0 . Index: head/sys/conf/NOTES =================================================================== --- head/sys/conf/NOTES +++ head/sys/conf/NOTES @@ -1193,6 +1193,7 @@ options MAC_LOMAC options MAC_MLS options MAC_NONE +options MAC_NTPD options MAC_PARTITION options MAC_PORTACL options MAC_SEEOTHERUIDS Index: head/sys/conf/files =================================================================== --- head/sys/conf/files +++ head/sys/conf/files @@ -4887,6 +4887,7 @@ security/mac_lomac/mac_lomac.c optional mac_lomac security/mac_mls/mac_mls.c optional mac_mls 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_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids Index: head/sys/conf/options =================================================================== --- head/sys/conf/options +++ head/sys/conf/options @@ -158,6 +158,7 @@ MAC_LOMAC opt_dontuse.h MAC_MLS opt_dontuse.h MAC_NONE opt_dontuse.h +MAC_NTPD opt_dontuse.h MAC_PARTITION opt_dontuse.h MAC_PORTACL opt_dontuse.h MAC_SEEOTHERUIDS opt_dontuse.h Index: head/sys/modules/Makefile =================================================================== --- head/sys/modules/Makefile +++ head/sys/modules/Makefile @@ -230,6 +230,7 @@ mac_lomac \ mac_mls \ mac_none \ + mac_ntpd \ mac_partition \ mac_portacl \ mac_seeotheruids \ Index: head/sys/modules/mac_ntpd/Makefile =================================================================== --- head/sys/modules/mac_ntpd/Makefile +++ head/sys/modules/mac_ntpd/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/security/mac_ntpd + +KMOD= mac_ntpd +SRCS= mac_ntpd.c + +.include Index: head/sys/security/mac_ntpd/mac_ntpd.c =================================================================== --- head/sys/security/mac_ntpd/mac_ntpd.c +++ head/sys/security/mac_ntpd/mac_ntpd.c @@ -0,0 +1,77 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2018 Ian Lepore + * + * 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 + +SYSCTL_DECL(_security_mac); + +static SYSCTL_NODE(_security_mac, OID_AUTO, ntpd, CTLFLAG_RW, 0, + "mac_ntpd policy controls"); + +static int ntpd_enabled = 1; +SYSCTL_INT(_security_mac_ntpd, OID_AUTO, enabled, CTLFLAG_RWTUN, + &ntpd_enabled, 0, "Enable mac_ntpd policy"); + +static int ntpd_uid = 123; +SYSCTL_INT(_security_mac_ntpd, OID_AUTO, uid, CTLFLAG_RWTUN, + &ntpd_uid, 0, "User id for ntpd user"); + +static int +ntpd_priv_grant(struct ucred *cred, int priv) +{ + + if (ntpd_enabled && cred->cr_uid == ntpd_uid) { + switch (priv) { + case PRIV_ADJTIME: + case PRIV_CLOCK_SETTIME: + case PRIV_NTP_ADJTIME: + case PRIV_NETINET_RESERVEDPORT: + case PRIV_NETINET_REUSEPORT: + return (0); + default: + break; + } + } + return (EPERM); +} + +static struct mac_policy_ops ntpd_ops = +{ + .mpo_priv_grant = ntpd_priv_grant, +}; + +MAC_POLICY_SET(&ntpd_ops, mac_ntpd, "MAC/ntpd", + MPC_LOADTIME_FLAG_UNLOADOK, NULL); Index: head/usr.sbin/ntp/config.h =================================================================== --- head/usr.sbin/ntp/config.h +++ head/usr.sbin/ntp/config.h @@ -392,7 +392,7 @@ /* #undef HAVE_DOPRNT */ /* Can we drop root privileges? */ -/* #undef HAVE_DROPROOT */ +#define HAVE_DROPROOT /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 @@ -1118,6 +1118,9 @@ /* Do we have the TIO serial stuff? */ /* #undef HAVE_TIO_SERIAL_STUFF */ + +/* Are TrustedBSD MAC policy privileges available? */ +#define HAVE_TRUSTEDBSD_MAC 1 /* Define to 1 if the system has the type `uint16_t'. */ #define HAVE_UINT16_T 1