cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

itimer.c (10434B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 1992 Darren Senn
      4 */
      5
      6/* These are all the functions necessary to implement itimers */
      7
      8#include <linux/mm.h>
      9#include <linux/interrupt.h>
     10#include <linux/syscalls.h>
     11#include <linux/time.h>
     12#include <linux/sched/signal.h>
     13#include <linux/sched/cputime.h>
     14#include <linux/posix-timers.h>
     15#include <linux/hrtimer.h>
     16#include <trace/events/timer.h>
     17#include <linux/compat.h>
     18
     19#include <linux/uaccess.h>
     20
     21/**
     22 * itimer_get_remtime - get remaining time for the timer
     23 *
     24 * @timer: the timer to read
     25 *
     26 * Returns the delta between the expiry time and now, which can be
     27 * less than zero or 1usec for an pending expired timer
     28 */
     29static struct timespec64 itimer_get_remtime(struct hrtimer *timer)
     30{
     31	ktime_t rem = __hrtimer_get_remaining(timer, true);
     32
     33	/*
     34	 * Racy but safe: if the itimer expires after the above
     35	 * hrtimer_get_remtime() call but before this condition
     36	 * then we return 0 - which is correct.
     37	 */
     38	if (hrtimer_active(timer)) {
     39		if (rem <= 0)
     40			rem = NSEC_PER_USEC;
     41	} else
     42		rem = 0;
     43
     44	return ktime_to_timespec64(rem);
     45}
     46
     47static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
     48			   struct itimerspec64 *const value)
     49{
     50	u64 val, interval;
     51	struct cpu_itimer *it = &tsk->signal->it[clock_id];
     52
     53	spin_lock_irq(&tsk->sighand->siglock);
     54
     55	val = it->expires;
     56	interval = it->incr;
     57	if (val) {
     58		u64 t, samples[CPUCLOCK_MAX];
     59
     60		thread_group_sample_cputime(tsk, samples);
     61		t = samples[clock_id];
     62
     63		if (val < t)
     64			/* about to fire */
     65			val = TICK_NSEC;
     66		else
     67			val -= t;
     68	}
     69
     70	spin_unlock_irq(&tsk->sighand->siglock);
     71
     72	value->it_value = ns_to_timespec64(val);
     73	value->it_interval = ns_to_timespec64(interval);
     74}
     75
     76static int do_getitimer(int which, struct itimerspec64 *value)
     77{
     78	struct task_struct *tsk = current;
     79
     80	switch (which) {
     81	case ITIMER_REAL:
     82		spin_lock_irq(&tsk->sighand->siglock);
     83		value->it_value = itimer_get_remtime(&tsk->signal->real_timer);
     84		value->it_interval =
     85			ktime_to_timespec64(tsk->signal->it_real_incr);
     86		spin_unlock_irq(&tsk->sighand->siglock);
     87		break;
     88	case ITIMER_VIRTUAL:
     89		get_cpu_itimer(tsk, CPUCLOCK_VIRT, value);
     90		break;
     91	case ITIMER_PROF:
     92		get_cpu_itimer(tsk, CPUCLOCK_PROF, value);
     93		break;
     94	default:
     95		return(-EINVAL);
     96	}
     97	return 0;
     98}
     99
    100static int put_itimerval(struct __kernel_old_itimerval __user *o,
    101			 const struct itimerspec64 *i)
    102{
    103	struct __kernel_old_itimerval v;
    104
    105	v.it_interval.tv_sec = i->it_interval.tv_sec;
    106	v.it_interval.tv_usec = i->it_interval.tv_nsec / NSEC_PER_USEC;
    107	v.it_value.tv_sec = i->it_value.tv_sec;
    108	v.it_value.tv_usec = i->it_value.tv_nsec / NSEC_PER_USEC;
    109	return copy_to_user(o, &v, sizeof(struct __kernel_old_itimerval)) ? -EFAULT : 0;
    110}
    111
    112
    113SYSCALL_DEFINE2(getitimer, int, which, struct __kernel_old_itimerval __user *, value)
    114{
    115	struct itimerspec64 get_buffer;
    116	int error = do_getitimer(which, &get_buffer);
    117
    118	if (!error && put_itimerval(value, &get_buffer))
    119		error = -EFAULT;
    120	return error;
    121}
    122
    123#if defined(CONFIG_COMPAT) || defined(CONFIG_ALPHA)
    124struct old_itimerval32 {
    125	struct old_timeval32	it_interval;
    126	struct old_timeval32	it_value;
    127};
    128
    129static int put_old_itimerval32(struct old_itimerval32 __user *o,
    130			       const struct itimerspec64 *i)
    131{
    132	struct old_itimerval32 v32;
    133
    134	v32.it_interval.tv_sec = i->it_interval.tv_sec;
    135	v32.it_interval.tv_usec = i->it_interval.tv_nsec / NSEC_PER_USEC;
    136	v32.it_value.tv_sec = i->it_value.tv_sec;
    137	v32.it_value.tv_usec = i->it_value.tv_nsec / NSEC_PER_USEC;
    138	return copy_to_user(o, &v32, sizeof(struct old_itimerval32)) ? -EFAULT : 0;
    139}
    140
    141COMPAT_SYSCALL_DEFINE2(getitimer, int, which,
    142		       struct old_itimerval32 __user *, value)
    143{
    144	struct itimerspec64 get_buffer;
    145	int error = do_getitimer(which, &get_buffer);
    146
    147	if (!error && put_old_itimerval32(value, &get_buffer))
    148		error = -EFAULT;
    149	return error;
    150}
    151#endif
    152
    153/*
    154 * The timer is automagically restarted, when interval != 0
    155 */
    156enum hrtimer_restart it_real_fn(struct hrtimer *timer)
    157{
    158	struct signal_struct *sig =
    159		container_of(timer, struct signal_struct, real_timer);
    160	struct pid *leader_pid = sig->pids[PIDTYPE_TGID];
    161
    162	trace_itimer_expire(ITIMER_REAL, leader_pid, 0);
    163	kill_pid_info(SIGALRM, SEND_SIG_PRIV, leader_pid);
    164
    165	return HRTIMER_NORESTART;
    166}
    167
    168static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
    169			   const struct itimerspec64 *const value,
    170			   struct itimerspec64 *const ovalue)
    171{
    172	u64 oval, nval, ointerval, ninterval;
    173	struct cpu_itimer *it = &tsk->signal->it[clock_id];
    174
    175	nval = timespec64_to_ns(&value->it_value);
    176	ninterval = timespec64_to_ns(&value->it_interval);
    177
    178	spin_lock_irq(&tsk->sighand->siglock);
    179
    180	oval = it->expires;
    181	ointerval = it->incr;
    182	if (oval || nval) {
    183		if (nval > 0)
    184			nval += TICK_NSEC;
    185		set_process_cpu_timer(tsk, clock_id, &nval, &oval);
    186	}
    187	it->expires = nval;
    188	it->incr = ninterval;
    189	trace_itimer_state(clock_id == CPUCLOCK_VIRT ?
    190			   ITIMER_VIRTUAL : ITIMER_PROF, value, nval);
    191
    192	spin_unlock_irq(&tsk->sighand->siglock);
    193
    194	if (ovalue) {
    195		ovalue->it_value = ns_to_timespec64(oval);
    196		ovalue->it_interval = ns_to_timespec64(ointerval);
    197	}
    198}
    199
    200/*
    201 * Returns true if the timeval is in canonical form
    202 */
    203#define timeval_valid(t) \
    204	(((t)->tv_sec >= 0) && (((unsigned long) (t)->tv_usec) < USEC_PER_SEC))
    205
    206static int do_setitimer(int which, struct itimerspec64 *value,
    207			struct itimerspec64 *ovalue)
    208{
    209	struct task_struct *tsk = current;
    210	struct hrtimer *timer;
    211	ktime_t expires;
    212
    213	switch (which) {
    214	case ITIMER_REAL:
    215again:
    216		spin_lock_irq(&tsk->sighand->siglock);
    217		timer = &tsk->signal->real_timer;
    218		if (ovalue) {
    219			ovalue->it_value = itimer_get_remtime(timer);
    220			ovalue->it_interval
    221				= ktime_to_timespec64(tsk->signal->it_real_incr);
    222		}
    223		/* We are sharing ->siglock with it_real_fn() */
    224		if (hrtimer_try_to_cancel(timer) < 0) {
    225			spin_unlock_irq(&tsk->sighand->siglock);
    226			hrtimer_cancel_wait_running(timer);
    227			goto again;
    228		}
    229		expires = timespec64_to_ktime(value->it_value);
    230		if (expires != 0) {
    231			tsk->signal->it_real_incr =
    232				timespec64_to_ktime(value->it_interval);
    233			hrtimer_start(timer, expires, HRTIMER_MODE_REL);
    234		} else
    235			tsk->signal->it_real_incr = 0;
    236
    237		trace_itimer_state(ITIMER_REAL, value, 0);
    238		spin_unlock_irq(&tsk->sighand->siglock);
    239		break;
    240	case ITIMER_VIRTUAL:
    241		set_cpu_itimer(tsk, CPUCLOCK_VIRT, value, ovalue);
    242		break;
    243	case ITIMER_PROF:
    244		set_cpu_itimer(tsk, CPUCLOCK_PROF, value, ovalue);
    245		break;
    246	default:
    247		return -EINVAL;
    248	}
    249	return 0;
    250}
    251
    252#ifdef CONFIG_SECURITY_SELINUX
    253void clear_itimer(void)
    254{
    255	struct itimerspec64 v = {};
    256	int i;
    257
    258	for (i = 0; i < 3; i++)
    259		do_setitimer(i, &v, NULL);
    260}
    261#endif
    262
    263#ifdef __ARCH_WANT_SYS_ALARM
    264
    265/**
    266 * alarm_setitimer - set alarm in seconds
    267 *
    268 * @seconds:	number of seconds until alarm
    269 *		0 disables the alarm
    270 *
    271 * Returns the remaining time in seconds of a pending timer or 0 when
    272 * the timer is not active.
    273 *
    274 * On 32 bit machines the seconds value is limited to (INT_MAX/2) to avoid
    275 * negative timeval settings which would cause immediate expiry.
    276 */
    277static unsigned int alarm_setitimer(unsigned int seconds)
    278{
    279	struct itimerspec64 it_new, it_old;
    280
    281#if BITS_PER_LONG < 64
    282	if (seconds > INT_MAX)
    283		seconds = INT_MAX;
    284#endif
    285	it_new.it_value.tv_sec = seconds;
    286	it_new.it_value.tv_nsec = 0;
    287	it_new.it_interval.tv_sec = it_new.it_interval.tv_nsec = 0;
    288
    289	do_setitimer(ITIMER_REAL, &it_new, &it_old);
    290
    291	/*
    292	 * We can't return 0 if we have an alarm pending ...  And we'd
    293	 * better return too much than too little anyway
    294	 */
    295	if ((!it_old.it_value.tv_sec && it_old.it_value.tv_nsec) ||
    296	      it_old.it_value.tv_nsec >= (NSEC_PER_SEC / 2))
    297		it_old.it_value.tv_sec++;
    298
    299	return it_old.it_value.tv_sec;
    300}
    301
    302/*
    303 * For backwards compatibility?  This can be done in libc so Alpha
    304 * and all newer ports shouldn't need it.
    305 */
    306SYSCALL_DEFINE1(alarm, unsigned int, seconds)
    307{
    308	return alarm_setitimer(seconds);
    309}
    310
    311#endif
    312
    313static int get_itimerval(struct itimerspec64 *o, const struct __kernel_old_itimerval __user *i)
    314{
    315	struct __kernel_old_itimerval v;
    316
    317	if (copy_from_user(&v, i, sizeof(struct __kernel_old_itimerval)))
    318		return -EFAULT;
    319
    320	/* Validate the timevals in value. */
    321	if (!timeval_valid(&v.it_value) ||
    322	    !timeval_valid(&v.it_interval))
    323		return -EINVAL;
    324
    325	o->it_interval.tv_sec = v.it_interval.tv_sec;
    326	o->it_interval.tv_nsec = v.it_interval.tv_usec * NSEC_PER_USEC;
    327	o->it_value.tv_sec = v.it_value.tv_sec;
    328	o->it_value.tv_nsec = v.it_value.tv_usec * NSEC_PER_USEC;
    329	return 0;
    330}
    331
    332SYSCALL_DEFINE3(setitimer, int, which, struct __kernel_old_itimerval __user *, value,
    333		struct __kernel_old_itimerval __user *, ovalue)
    334{
    335	struct itimerspec64 set_buffer, get_buffer;
    336	int error;
    337
    338	if (value) {
    339		error = get_itimerval(&set_buffer, value);
    340		if (error)
    341			return error;
    342	} else {
    343		memset(&set_buffer, 0, sizeof(set_buffer));
    344		printk_once(KERN_WARNING "%s calls setitimer() with new_value NULL pointer."
    345			    " Misfeature support will be removed\n",
    346			    current->comm);
    347	}
    348
    349	error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : NULL);
    350	if (error || !ovalue)
    351		return error;
    352
    353	if (put_itimerval(ovalue, &get_buffer))
    354		return -EFAULT;
    355	return 0;
    356}
    357
    358#if defined(CONFIG_COMPAT) || defined(CONFIG_ALPHA)
    359static int get_old_itimerval32(struct itimerspec64 *o, const struct old_itimerval32 __user *i)
    360{
    361	struct old_itimerval32 v32;
    362
    363	if (copy_from_user(&v32, i, sizeof(struct old_itimerval32)))
    364		return -EFAULT;
    365
    366	/* Validate the timevals in value.  */
    367	if (!timeval_valid(&v32.it_value) ||
    368	    !timeval_valid(&v32.it_interval))
    369		return -EINVAL;
    370
    371	o->it_interval.tv_sec = v32.it_interval.tv_sec;
    372	o->it_interval.tv_nsec = v32.it_interval.tv_usec * NSEC_PER_USEC;
    373	o->it_value.tv_sec = v32.it_value.tv_sec;
    374	o->it_value.tv_nsec = v32.it_value.tv_usec * NSEC_PER_USEC;
    375	return 0;
    376}
    377
    378COMPAT_SYSCALL_DEFINE3(setitimer, int, which,
    379		       struct old_itimerval32 __user *, value,
    380		       struct old_itimerval32 __user *, ovalue)
    381{
    382	struct itimerspec64 set_buffer, get_buffer;
    383	int error;
    384
    385	if (value) {
    386		error = get_old_itimerval32(&set_buffer, value);
    387		if (error)
    388			return error;
    389	} else {
    390		memset(&set_buffer, 0, sizeof(set_buffer));
    391		printk_once(KERN_WARNING "%s calls setitimer() with new_value NULL pointer."
    392			    " Misfeature support will be removed\n",
    393			    current->comm);
    394	}
    395
    396	error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : NULL);
    397	if (error || !ovalue)
    398		return error;
    399	if (put_old_itimerval32(ovalue, &get_buffer))
    400		return -EFAULT;
    401	return 0;
    402}
    403#endif