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

--- 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) {

--- 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;
 

_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to