Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 07 Nov 2005 22:17:07 +0100
From:      Anatoli Klassen <anatoli@aksoft.net>
To:        freebsd-hackers@freebsd.org
Subject:   Run ntpd as non-root user
Message-ID:  <436FC453.1080801@aksoft.net>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------030509020808000204010009
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Hi All,

I have written patches to allow to run ntpd as ordinal user and/or from
jail.

The idea is to disable build-in kernel security checks by setting some
sysctl's and then plug in a MAC module (actually it is the same approach
as in mac_portacl to bind to low ports).

There are four new sysctl MIBs:
kern.usersettime - non-root is allowed to change system time,
kern.jailsettime - system time is allowed to be changed from jail,
kern.useradjtime - non-root is allowed to adjust system time,
kern.jailadjtime - system time is allowed to be adjusted from jail;

and a new MAC module mac_settime, where admin can define rules via
sysctl MIB:
	security.mac.settime.rules=
		"allow uid 2000 nojail; allow gid 123 jail 10"

There is also a one-line patch for ntpd itself to disable root-check at
startup.

I'm waiting for your comments :)

Regards,
Anatoli


--------------030509020808000204010009
Content-Type: text/plain;
 name="kern_settime.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="kern_settime.patch"

--- sys/kern/kern_time.c.orig	Mon Nov  7 11:56:57 2005
+++ sys/kern/kern_time.c	Mon Nov  7 12:14:45 2005
@@ -41,9 +41,11 @@
 #include <sys/sysproto.h>
 #include <sys/resourcevar.h>
 #include <sys/signalvar.h>
+#include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/mac.h>
 #include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
 #include <sys/sysent.h>
 #include <sys/proc.h>
 #include <sys/time.h>
@@ -104,6 +106,12 @@
 
 SYSINIT(posix_timer, SI_SUB_P1003_1B, SI_ORDER_FIRST+4, itimer_start, NULL);
 
+static int cf_usersettime;
+static int cf_jailsettime;
+SYSCTL_INT(_kern, OID_AUTO, usersettime, CTLFLAG_RW, &cf_usersettime, 0,
+    "Non-root is allowed to change system time");
+SYSCTL_INT(_kern, OID_AUTO, jailsettime, CTLFLAG_RW, &cf_jailsettime, 0,
+    "System time is allowed to be changed from jail");
 
 static void 
 no_lease_updatetime(deltat)
@@ -265,8 +273,10 @@
 	if (error)
 		return (error);
 #endif
-	if ((error = suser(td)) != 0)
-		return (error);
+	if (!cf_jailsettime && jailed(td->td_ucred))
+		return (EPERM);
+	if (!cf_usersettime && (error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL)) != 0)
+		return (error);				/* jail is already checked */
 	if (clock_id != CLOCK_REALTIME)
 		return (EINVAL);
 	if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000)
@@ -472,9 +482,12 @@
 	if (error)
 		return (error);
 #endif
-	error = suser(td);
-	if (error)
-		return (error);
+	if (!cf_jailsettime && jailed(td->td_ucred))
+		return (EPERM);
+	if (!cf_usersettime && (error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL)) != 0)
+		return (error);				/* jail is already checked */
+	else
+		error = 0;
 	/* Verify all parameters before changing time. */
 	if (tv) {
 		if (tv->tv_usec < 0 || tv->tv_usec >= 1000000)
--- sys/kern/kern_ntptime.c.orig	Mon Nov  7 11:57:07 2005
+++ sys/kern/kern_ntptime.c	Mon Nov  7 12:14:45 2005
@@ -38,6 +38,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/sysproto.h>
+#include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/proc.h>
 #include <sys/lock.h>
@@ -198,6 +199,13 @@
 static void hardupdate(long offset);
 static void ntp_gettime1(struct ntptimeval *ntvp);
 
+static int cf_useradjtime;
+static int cf_jailadjtime;
+SYSCTL_INT(_kern, OID_AUTO, useradjtime, CTLFLAG_RW, &cf_useradjtime, 0,
+    "Non-root is allowed to adjust system time");
+SYSCTL_INT(_kern, OID_AUTO, jailadjtime, CTLFLAG_RW, &cf_jailadjtime, 0,
+    "System time is allowed to be adjusted from jail");
+
 static void
 ntp_gettime1(struct ntptimeval *ntvp)
 {
@@ -330,12 +338,20 @@
 	 * the STA_PLL bit in the status word is cleared, the state and
 	 * status words are reset to the initial values at boot.
 	 */
-	mtx_lock(&Giant);
 	modes = ntv.modes;
-	if (modes)
-		error = suser(td);
-	if (error)
-		goto done2;
+	if (modes) {
+#ifdef MAC
+		error = mac_check_system_settime(td->td_ucred);
+		if (error)
+			return (error);
+#endif
+		if (!cf_jailadjtime && jailed(td->td_ucred))
+			return (EPERM);
+		if (!cf_useradjtime && 
+		    (error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL)) != 0)
+			return (error);         /* jail is already checked at this point */
+	}
+	mtx_lock(&Giant);
 	s = splclock();
 	if (modes & MOD_MAXERROR)
 		time_maxerror = ntv.maxerror;
@@ -954,8 +970,17 @@
 	struct timeval atv;
 	int error;
 
-	if ((error = suser(td)))
+#ifdef MAC
+	error = mac_check_system_settime(td->td_ucred);
+	if (error)
 		return (error);
+#endif
+	if (!cf_jailadjtime && jailed(td->td_ucred))
+		return (EPERM);
+	if (!cf_useradjtime && (error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL)) != 0)
+		return (error);                          /* jail is already checked */
+	else
+		error = 0;
 
 	mtx_lock(&Giant);
 	if (olddelta) {


--------------030509020808000204010009
Content-Type: text/plain;
 name="ntp.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ntp.patch"

--- contrib/ntp/ntpd/ntpd.c.orig	Mon Nov  7 11:57:28 2005
+++ contrib/ntp/ntpd/ntpd.c	Mon Nov  7 12:14:45 2005
@@ -394,7 +394,7 @@
 	}
 #endif
 
-#if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
+#if 0 && defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
 	{
 		uid_t uid;
 


--------------030509020808000204010009--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?436FC453.1080801>