+/*
+ * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
+ * support for mandatory and extensible security protections. This notice
+ * is included in support of clause 2.2 (b) of the Apple Public License,
+ * Version 2.0.
+ */
#include <sys/mount_internal.h>
#include <sys/sysproto.h>
#include <sys/signalvar.h>
#include <kern/clock.h>
#include <sys/mount_internal.h>
#include <sys/sysproto.h>
#include <sys/signalvar.h>
#include <kern/clock.h>
- struct user_timeval user_atv;
- error = copyin(uap->tv, &user_atv, sizeof(struct user_timeval));
+ struct user64_timeval user_atv;
+ error = copyin(uap->tv, &user_atv, sizeof(user_atv));
- error = copyin(uap->tv, &atv, sizeof(struct timeval));
+ struct user32_timeval user_atv;
+ error = copyin(uap->tv, &user_atv, sizeof(user_atv));
+ atv.tv_sec = user_atv.tv_sec;
+ atv.tv_usec = user_atv.tv_usec;
- if ((error = suser(kauth_cred_get(), &p->p_acflag)))
+#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)))
- struct user_timeval user_atv;
- error = copyin(uap->delta, &user_atv, sizeof(struct user_timeval));
+ struct user64_timeval user_atv;
+ error = copyin(uap->delta, &user_atv, sizeof(user_atv));
- error = copyin(uap->delta, &atv, sizeof(struct timeval));
+ 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;
- error = copyout(&atv, uap->olddelta, sizeof(struct timeval));
+ 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));
* is kept as an absolute time rather than as a delta, so that
* it is easy to keep periodic real-time signals from drifting.
*
* is kept as an absolute time rather than as a delta, so that
* it is easy to keep periodic real-time signals from drifting.
*
- * Virtual time timers are processed in the hardclock() routine of
- * kern_clock.c. The real time timer is processed by a callout
- * routine. Since a callout may be delayed in real time due to
+ * The real time timer is processed by a callout routine.
+ * Since a callout may be delayed in real time due to
* other processing in the system, it is possible for the real
* time callout routine (realitexpire, given below), to be delayed
* in real time past when it is supposed to occur. It does not
* suffice, therefore, to reload the real time .it_value from the
* real time .it_interval. Rather, we compute the next time in
* absolute time when the timer should go off.
* other processing in the system, it is possible for the real
* time callout routine (realitexpire, given below), to be delayed
* in real time past when it is supposed to occur. It does not
* suffice, therefore, to reload the real time .it_value from the
* real time .it_interval. Rather, we compute the next time in
* absolute time when the timer should go off.
/*
* If time for real time timer has passed return 0,
* else return difference between current time and
/*
* If time for real time timer has passed return 0,
* else return difference between current time and
user_itv.it_interval.tv_sec = aitv.it_interval.tv_sec;
user_itv.it_interval.tv_usec = aitv.it_interval.tv_usec;
user_itv.it_value.tv_sec = aitv.it_value.tv_sec;
user_itv.it_value.tv_usec = aitv.it_value.tv_usec;
user_itv.it_interval.tv_sec = aitv.it_interval.tv_sec;
user_itv.it_interval.tv_usec = aitv.it_interval.tv_usec;
user_itv.it_value.tv_sec = aitv.it_value.tv_sec;
user_itv.it_value.tv_usec = aitv.it_value.tv_usec;
- return (copyout((caddr_t)&aitv, uap->itv, sizeof (struct itimerval)));
+ struct user32_itimerval user_itv;
+ user_itv.it_interval.tv_sec = aitv.it_interval.tv_sec;
+ user_itv.it_interval.tv_usec = aitv.it_interval.tv_usec;
+ user_itv.it_value.tv_sec = aitv.it_value.tv_sec;
+ user_itv.it_value.tv_usec = aitv.it_value.tv_usec;
+ return (copyout((caddr_t)&user_itv, uap->itv, sizeof (user_itv)));
-setitimer(p, uap, retval)
- struct proc *p;
- register struct setitimer_args *uap;
- register_t *retval;
+setitimer(struct proc *p, struct setitimer_args *uap, int32_t *retval)
- struct user_itimerval user_itv;
- if ((error = copyin(itvp, (caddr_t)&user_itv, sizeof (struct user_itimerval))))
+ struct user64_itimerval user_itv;
+ if ((error = copyin(itvp, (caddr_t)&user_itv, sizeof (user_itv))))
return (error);
aitv.it_interval.tv_sec = user_itv.it_interval.tv_sec;
aitv.it_interval.tv_usec = user_itv.it_interval.tv_usec;
aitv.it_value.tv_sec = user_itv.it_value.tv_sec;
aitv.it_value.tv_usec = user_itv.it_value.tv_usec;
} else {
return (error);
aitv.it_interval.tv_sec = user_itv.it_interval.tv_sec;
aitv.it_interval.tv_usec = user_itv.it_interval.tv_usec;
aitv.it_value.tv_sec = user_itv.it_value.tv_sec;
aitv.it_value.tv_usec = user_itv.it_value.tv_usec;
} else {
- if ((error = copyin(itvp, (caddr_t)&aitv, sizeof (struct itimerval))))
+ struct user32_itimerval user_itv;
+ if ((error = copyin(itvp, (caddr_t)&user_itv, sizeof (user_itv))))
+ aitv.it_interval.tv_sec = user_itv.it_interval.tv_sec;
+ aitv.it_interval.tv_usec = user_itv.it_interval.tv_usec;
+ aitv.it_value.tv_sec = user_itv.it_value.tv_sec;
+ aitv.it_value.tv_usec = user_itv.it_value.tv_usec;
if (timerisset(&aitv.it_value)) {
microuptime(&p->p_rtime);
timevaladd(&p->p_rtime, &aitv.it_value);
if (timerisset(&aitv.it_value)) {
microuptime(&p->p_rtime);
timevaladd(&p->p_rtime, &aitv.it_value);
- thread_call_func_delayed(
- (thread_call_func_t)realitexpire, (void *)p->p_pid,
- tvtoabstime(&p->p_rtime));
+ p->p_realtimer = aitv;
+ if (!thread_call_enter_delayed(p->p_rcall, tvtoabstime(&p->p_rtime)))
+ p->p_ractive++;
+ } else {
+ timerclear(&p->p_rtime);
+ p->p_realtimer = aitv;
+ if (thread_call_cancel(p->p_rcall))
+ p->p_ractive--;
+ proc_spinunlock(p);
+
+ break;
+
+
+ case ITIMER_VIRTUAL:
+ if (timerisset(&aitv.it_value))
+ task_vtimer_set(p->task, TASK_VTIMER_USER);
+ else
+ task_vtimer_clear(p->task, TASK_VTIMER_USER);
+
+ proc_spinlock(p);
+ p->p_vtimer_user = aitv;
+ proc_spinunlock(p);
+ break;
+
+ case ITIMER_PROF:
+ if (timerisset(&aitv.it_value))
+ task_vtimer_set(p->task, TASK_VTIMER_PROF);
- register struct proc *p;
- struct timeval now;
- boolean_t funnel_state;
-
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- p = pfind((pid_t)pid);
- if (p == NULL) {
- (void) thread_funnel_set(kernel_flock, FALSE);
+ struct proc *r;
+ struct timeval t;
+
+ r = proc_find(p->p_pid);
+
+ proc_spinlock(p);
+
+ if (--p->p_ractive > 0 || r != p) {
+ proc_spinunlock(p);
+
+ if (r != NULL)
+ proc_rele(r);
- if (timercmp(&p->p_rtime, &now, <=)) {
- if ((p->p_rtime.tv_sec + 2) >= now.tv_sec) {
+ if (timercmp(&p->p_rtime, &t, <=)) {
+ if ((p->p_rtime.tv_sec + 2) >= t.tv_sec) {
- * .it_interval part of an interval timer is acceptable, and
- * fix it to have at least minimal value (i.e. if it is less
- * than the resolution of the clock, round it up.)
+ * .it_interval part of an interval timer is acceptable.
* of microseconds, which must be less than a second,
* i.e. < 1000000. If the timer expires, then reload
* it. In this case, carry over (usec - old value) to
* of microseconds, which must be less than a second,
* i.e. < 1000000. If the timer expires, then reload
* it. In this case, carry over (usec - old value) to
* the timer does not drift. This routine assumes
* that it is called in a context where the timers
* on which it is operating cannot change in value.
*/
int
* the timer does not drift. This routine assumes
* that it is called in a context where the timers
* on which it is operating cannot change in value.
*/
int
if (itp->it_value.tv_usec < usec) {
if (itp->it_value.tv_sec == 0) {
/* expired, and already in next interval */
if (itp->it_value.tv_usec < usec) {
if (itp->it_value.tv_sec == 0) {
/* expired, and already in next interval */
/* expired, exactly at end of interval */
expire:
if (timerisset(&itp->it_interval)) {
itp->it_value = itp->it_interval;
/* expired, exactly at end of interval */
expire:
if (timerisset(&itp->it_interval)) {
itp->it_value = itp->it_interval;
itp->it_value.tv_usec -= usec;
if (itp->it_value.tv_usec < 0) {
itp->it_value.tv_usec += 1000000;
itp->it_value.tv_sec--;
itp->it_value.tv_usec -= usec;
if (itp->it_value.tv_usec < 0) {
itp->it_value.tv_usec += 1000000;
itp->it_value.tv_sec--;
/* Allocate the spin lock */
tz_slock = lck_spin_alloc_init(tz_slock_grp, tz_slock_attr);
}
/* Allocate the spin lock */
tz_slock = lck_spin_alloc_init(tz_slock_grp, tz_slock_attr);
}