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

timerfd.c (2825B)


      1// SPDX-License-Identifier: GPL-2.0
      2#define _GNU_SOURCE
      3#include <sched.h>
      4
      5#include <sys/timerfd.h>
      6#include <sys/syscall.h>
      7#include <sys/types.h>
      8#include <sys/wait.h>
      9#include <time.h>
     10#include <unistd.h>
     11#include <stdlib.h>
     12#include <stdio.h>
     13#include <stdint.h>
     14
     15#include "log.h"
     16#include "timens.h"
     17
     18static int tclock_gettime(clock_t clockid, struct timespec *now)
     19{
     20	if (clockid == CLOCK_BOOTTIME_ALARM)
     21		clockid = CLOCK_BOOTTIME;
     22	return clock_gettime(clockid, now);
     23}
     24
     25int run_test(int clockid, struct timespec now)
     26{
     27	struct itimerspec new_value;
     28	long long elapsed;
     29	int fd, i;
     30
     31	if (check_skip(clockid))
     32		return 0;
     33
     34	if (tclock_gettime(clockid, &now))
     35		return pr_perror("clock_gettime(%d)", clockid);
     36
     37	for (i = 0; i < 2; i++) {
     38		int flags = 0;
     39
     40		new_value.it_value.tv_sec = 3600;
     41		new_value.it_value.tv_nsec = 0;
     42		new_value.it_interval.tv_sec = 1;
     43		new_value.it_interval.tv_nsec = 0;
     44
     45		if (i == 1) {
     46			new_value.it_value.tv_sec += now.tv_sec;
     47			new_value.it_value.tv_nsec += now.tv_nsec;
     48		}
     49
     50		fd = timerfd_create(clockid, 0);
     51		if (fd == -1)
     52			return pr_perror("timerfd_create(%d)", clockid);
     53
     54		if (i == 1)
     55			flags |= TFD_TIMER_ABSTIME;
     56
     57		if (timerfd_settime(fd, flags, &new_value, NULL))
     58			return pr_perror("timerfd_settime(%d)", clockid);
     59
     60		if (timerfd_gettime(fd, &new_value))
     61			return pr_perror("timerfd_gettime(%d)", clockid);
     62
     63		elapsed = new_value.it_value.tv_sec;
     64		if (abs(elapsed - 3600) > 60) {
     65			ksft_test_result_fail("clockid: %d elapsed: %lld\n",
     66					      clockid, elapsed);
     67			return 1;
     68		}
     69
     70		close(fd);
     71	}
     72
     73	ksft_test_result_pass("clockid=%d\n", clockid);
     74
     75	return 0;
     76}
     77
     78int main(int argc, char *argv[])
     79{
     80	int ret, status, len, fd;
     81	char buf[4096];
     82	pid_t pid;
     83	struct timespec btime_now, mtime_now;
     84
     85	nscheck();
     86
     87	check_supported_timers();
     88
     89	ksft_set_plan(3);
     90
     91	clock_gettime(CLOCK_MONOTONIC, &mtime_now);
     92	clock_gettime(CLOCK_BOOTTIME, &btime_now);
     93
     94	if (unshare_timens())
     95		return 1;
     96
     97	len = snprintf(buf, sizeof(buf), "%d %d 0\n%d %d 0",
     98			CLOCK_MONOTONIC, 70 * 24 * 3600,
     99			CLOCK_BOOTTIME, 9 * 24 * 3600);
    100	fd = open("/proc/self/timens_offsets", O_WRONLY);
    101	if (fd < 0)
    102		return pr_perror("/proc/self/timens_offsets");
    103
    104	if (write(fd, buf, len) != len)
    105		return pr_perror("/proc/self/timens_offsets");
    106
    107	close(fd);
    108	mtime_now.tv_sec += 70 * 24 * 3600;
    109	btime_now.tv_sec += 9 * 24 * 3600;
    110
    111	pid = fork();
    112	if (pid < 0)
    113		return pr_perror("Unable to fork");
    114	if (pid == 0) {
    115		ret = 0;
    116		ret |= run_test(CLOCK_BOOTTIME, btime_now);
    117		ret |= run_test(CLOCK_MONOTONIC, mtime_now);
    118		ret |= run_test(CLOCK_BOOTTIME_ALARM, btime_now);
    119
    120		if (ret)
    121			ksft_exit_fail();
    122		ksft_exit_pass();
    123		return ret;
    124	}
    125
    126	if (waitpid(pid, &status, 0) != pid)
    127		return pr_perror("Unable to wait the child process");
    128
    129	if (WIFEXITED(status))
    130		return WEXITSTATUS(status);
    131
    132	return 1;
    133}