]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_time.c
xnu-4903.221.2.tar.gz
[apple/xnu.git] / bsd / kern / kern_time.c
index 7f94f9b50428559c12a454308556ad7433619745..ba2e6c9901c9e3cc42d81c5792593da62c55b693 100644 (file)
@@ -88,6 +88,8 @@
 #if CONFIG_MACF
 #include <security/mac_framework.h>
 #endif
+#include <IOKit/IOBSD.h>
+#include <sys/time.h>
 
 #define HZ     100     /* XXX */
 
@@ -101,6 +103,7 @@ static void         setthetime(
                                        struct timeval  *tv);
 
 void time_zone_slock_init(void);
+static boolean_t timeval_fixusec(struct timeval *t1);
 
 /*
  * Time of day and interval timer support.
@@ -174,13 +177,20 @@ settimeofday(__unused struct proc *p, struct settimeofday_args  *uap, __unused i
 
        bzero(&atv, sizeof(atv));
 
+       /* Check that this task is entitled to set the time or it is root */
+       if (!IOTaskHasEntitlement(current_task(), SETTIME_ENTITLEMENT)) {
+
 #if CONFIG_MACF
-       error = mac_system_check_settime(kauth_cred_get());
-       if (error)
-               return (error);
+               error = mac_system_check_settime(kauth_cred_get());
+               if (error)
+                       return (error);
 #endif
-       if ((error = suser(kauth_cred_get(), &p->p_acflag)))
-               return (error);
+#ifndef CONFIG_EMBEDDED
+               if ((error = suser(kauth_cred_get(), &p->p_acflag)))
+                       return (error);
+#endif
+       }
+
        /* Verify all parameters before changing time */
        if (uap->tv) {
                if (IS_64BIT_PROCESS(p)) {
@@ -200,8 +210,10 @@ settimeofday(__unused struct proc *p, struct settimeofday_args  *uap, __unused i
        if (uap->tzp && (error = copyin(uap->tzp, (caddr_t)&atz, sizeof(atz))))
                return (error);
        if (uap->tv) {
-               timevalfix(&atv);
-               if (atv.tv_sec < 0 || (atv.tv_sec == 0 && atv.tv_usec < 0))
+               /* only positive values of sec/usec are accepted */
+               if (atv.tv_sec < 0 || atv.tv_usec < 0)
+                       return (EPERM);
+               if (!timeval_fixusec(&atv))
                        return (EPERM);
                setthetime(&atv);
        }
@@ -220,59 +232,6 @@ setthetime(
        clock_set_calendar_microtime(tv->tv_sec, tv->tv_usec);
 }
 
-/*
- * XXX Y2038 bug because of clock_adjtime() first argument
- */
-/* ARGSUSED */
-int
-adjtime(struct proc *p, struct adjtime_args *uap, __unused int32_t *retval)
-{
-       struct timeval atv;
-       int error;
-
-#if CONFIG_MACF
-       error = mac_system_check_settime(kauth_cred_get());
-       if (error)
-               return (error);
-#endif
-       if ((error = priv_check_cred(kauth_cred_get(), PRIV_ADJTIME, 0)))
-               return (error);
-       if (IS_64BIT_PROCESS(p)) {
-               struct user64_timeval user_atv;
-               error = copyin(uap->delta, &user_atv, sizeof(user_atv));
-               atv.tv_sec = user_atv.tv_sec;
-               atv.tv_usec = user_atv.tv_usec;
-       } else {
-               struct user32_timeval user_atv;
-               error = copyin(uap->delta, &user_atv, sizeof(user_atv));
-               atv.tv_sec = user_atv.tv_sec;
-               atv.tv_usec = user_atv.tv_usec;
-       }
-       if (error)
-               return (error);
-               
-       /*
-        * Compute the total correction and the rate at which to apply it.
-        */
-       clock_adjtime(&atv.tv_sec, &atv.tv_usec);
-
-       if (uap->olddelta) {
-               if (IS_64BIT_PROCESS(p)) {
-                       struct user64_timeval user_atv;
-                       user_atv.tv_sec = atv.tv_sec;
-                       user_atv.tv_usec = atv.tv_usec;
-                       error = copyout(&user_atv, uap->olddelta, sizeof(user_atv));
-               } else {
-                       struct user32_timeval user_atv;
-                       user_atv.tv_sec = atv.tv_sec;
-                       user_atv.tv_usec = atv.tv_usec;
-                       error = copyout(&user_atv, uap->olddelta, sizeof(user_atv));
-               }
-       }
-
-       return (0);
-}
-
 /*
  *     Verify the calendar value.  If negative,
  *     reset to zero (the epoch).
@@ -755,6 +714,22 @@ timevalfix(
        }
 }
 
+static boolean_t
+timeval_fixusec(
+       struct timeval *t1)
+{
+       assert(t1->tv_usec >= 0);
+       assert(t1->tv_sec >= 0);
+
+       if (t1->tv_usec >= 1000000) {
+               if (os_add_overflow(t1->tv_sec, t1->tv_usec / 1000000, &t1->tv_sec))
+                       return FALSE;
+               t1->tv_usec = t1->tv_usec % 1000000;
+       }
+
+       return TRUE;
+}
+
 /*
  * Return the best possible estimate of the time in the timeval
  * to which tvp points.
@@ -943,3 +918,4 @@ time_zone_slock_init(void)
        /* Allocate the spin lock */
        tz_slock = lck_spin_alloc_init(tz_slock_grp, tz_slock_attr);
 }
+