Run ntpd as non-root user
Anatoli Klassen
anatoli at aksoft.net
Mon Nov 7 21:17:28 GMT 2005
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
-------------- next part --------------
--- 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) {
-------------- next part --------------
--- 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;
More information about the freebsd-hackers
mailing list