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

futex.c (2235B)


      1// SPDX-License-Identifier: GPL-2.0
      2#define _GNU_SOURCE
      3#include <sched.h>
      4
      5#include <linux/unistd.h>
      6#include <linux/futex.h>
      7#include <stdio.h>
      8#include <string.h>
      9#include <sys/syscall.h>
     10#include <sys/types.h>
     11#include <sys/wait.h>
     12#include <time.h>
     13#include <unistd.h>
     14
     15#include "log.h"
     16#include "timens.h"
     17
     18#define NSEC_PER_SEC 1000000000ULL
     19
     20static int run_test(int clockid)
     21{
     22	int futex_op = FUTEX_WAIT_BITSET;
     23	struct timespec timeout, end;
     24	int val = 0;
     25
     26	if (clockid == CLOCK_REALTIME)
     27		futex_op |= FUTEX_CLOCK_REALTIME;
     28
     29	clock_gettime(clockid, &timeout);
     30	timeout.tv_nsec += NSEC_PER_SEC / 10; // 100ms
     31	if (timeout.tv_nsec > NSEC_PER_SEC) {
     32		timeout.tv_sec++;
     33		timeout.tv_nsec -= NSEC_PER_SEC;
     34	}
     35
     36	if (syscall(__NR_futex, &val, futex_op, 0,
     37		    &timeout, 0, FUTEX_BITSET_MATCH_ANY) >= 0) {
     38		ksft_test_result_fail("futex didn't return ETIMEDOUT\n");
     39		return 1;
     40	}
     41
     42	if (errno != ETIMEDOUT) {
     43		ksft_test_result_fail("futex didn't return ETIMEDOUT: %s\n",
     44							strerror(errno));
     45		return 1;
     46	}
     47
     48	clock_gettime(clockid, &end);
     49
     50	if (end.tv_sec < timeout.tv_sec ||
     51	    (end.tv_sec == timeout.tv_sec && end.tv_nsec < timeout.tv_nsec)) {
     52		ksft_test_result_fail("futex slept less than 100ms\n");
     53		return 1;
     54	}
     55
     56
     57	ksft_test_result_pass("futex with the %d clockid\n", clockid);
     58
     59	return 0;
     60}
     61
     62int main(int argc, char *argv[])
     63{
     64	int status, len, fd;
     65	char buf[4096];
     66	pid_t pid;
     67	struct timespec mtime_now;
     68
     69	nscheck();
     70
     71	ksft_set_plan(2);
     72
     73	clock_gettime(CLOCK_MONOTONIC, &mtime_now);
     74
     75	if (unshare_timens())
     76		return 1;
     77
     78	len = snprintf(buf, sizeof(buf), "%d %d 0",
     79			CLOCK_MONOTONIC, 70 * 24 * 3600);
     80	fd = open("/proc/self/timens_offsets", O_WRONLY);
     81	if (fd < 0)
     82		return pr_perror("/proc/self/timens_offsets");
     83
     84	if (write(fd, buf, len) != len)
     85		return pr_perror("/proc/self/timens_offsets");
     86
     87	close(fd);
     88
     89	pid = fork();
     90	if (pid < 0)
     91		return pr_perror("Unable to fork");
     92	if (pid == 0) {
     93		int ret = 0;
     94
     95		ret |= run_test(CLOCK_REALTIME);
     96		ret |= run_test(CLOCK_MONOTONIC);
     97		if (ret)
     98			ksft_exit_fail();
     99		ksft_exit_pass();
    100		return 0;
    101	}
    102
    103	if (waitpid(pid, &status, 0) != pid)
    104		return pr_perror("Unable to wait the child process");
    105
    106	if (WIFEXITED(status))
    107		return WEXITSTATUS(status);
    108
    109	return 1;
    110}