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

process.c (5763B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
      4 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
      5 */
      6
      7#include <stdio.h>
      8#include <stdlib.h>
      9#include <unistd.h>
     10#include <errno.h>
     11#include <signal.h>
     12#include <fcntl.h>
     13#include <sys/mman.h>
     14#include <sys/ptrace.h>
     15#include <sys/wait.h>
     16#include <asm/unistd.h>
     17#include <init.h>
     18#include <longjmp.h>
     19#include <os.h>
     20
     21#define ARBITRARY_ADDR -1
     22#define FAILURE_PID    -1
     23
     24#define STAT_PATH_LEN sizeof("/proc/#######/stat\0")
     25#define COMM_SCANF "%*[^)])"
     26
     27unsigned long os_process_pc(int pid)
     28{
     29	char proc_stat[STAT_PATH_LEN], buf[256];
     30	unsigned long pc = ARBITRARY_ADDR;
     31	int fd, err;
     32
     33	sprintf(proc_stat, "/proc/%d/stat", pid);
     34	fd = open(proc_stat, O_RDONLY, 0);
     35	if (fd < 0) {
     36		printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', "
     37		       "errno = %d\n", proc_stat, errno);
     38		goto out;
     39	}
     40	CATCH_EINTR(err = read(fd, buf, sizeof(buf)));
     41	if (err < 0) {
     42		printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', "
     43		       "err = %d\n", proc_stat, errno);
     44		goto out_close;
     45	}
     46	os_close_file(fd);
     47	pc = ARBITRARY_ADDR;
     48	if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d "
     49		   "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
     50		   "%*d %*d %*d %*d %*d %lu", &pc) != 1)
     51		printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n",
     52		       buf);
     53 out_close:
     54	close(fd);
     55 out:
     56	return pc;
     57}
     58
     59int os_process_parent(int pid)
     60{
     61	char stat[STAT_PATH_LEN];
     62	char data[256];
     63	int parent = FAILURE_PID, n, fd;
     64
     65	if (pid == -1)
     66		return parent;
     67
     68	snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
     69	fd = open(stat, O_RDONLY, 0);
     70	if (fd < 0) {
     71		printk(UM_KERN_ERR "Couldn't open '%s', errno = %d\n", stat,
     72		       errno);
     73		return parent;
     74	}
     75
     76	CATCH_EINTR(n = read(fd, data, sizeof(data)));
     77	close(fd);
     78
     79	if (n < 0) {
     80		printk(UM_KERN_ERR "Couldn't read '%s', errno = %d\n", stat,
     81		       errno);
     82		return parent;
     83	}
     84
     85	parent = FAILURE_PID;
     86	n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
     87	if (n != 1)
     88		printk(UM_KERN_ERR "Failed to scan '%s'\n", data);
     89
     90	return parent;
     91}
     92
     93void os_alarm_process(int pid)
     94{
     95	kill(pid, SIGALRM);
     96}
     97
     98void os_stop_process(int pid)
     99{
    100	kill(pid, SIGSTOP);
    101}
    102
    103void os_kill_process(int pid, int reap_child)
    104{
    105	kill(pid, SIGKILL);
    106	if (reap_child)
    107		CATCH_EINTR(waitpid(pid, NULL, __WALL));
    108}
    109
    110/* Kill off a ptraced child by all means available.  kill it normally first,
    111 * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from
    112 * which it can't exit directly.
    113 */
    114
    115void os_kill_ptraced_process(int pid, int reap_child)
    116{
    117	kill(pid, SIGKILL);
    118	ptrace(PTRACE_KILL, pid);
    119	ptrace(PTRACE_CONT, pid);
    120	if (reap_child)
    121		CATCH_EINTR(waitpid(pid, NULL, __WALL));
    122}
    123
    124/* Don't use the glibc version, which caches the result in TLS. It misses some
    125 * syscalls, and also breaks with clone(), which does not unshare the TLS.
    126 */
    127
    128int os_getpid(void)
    129{
    130	return syscall(__NR_getpid);
    131}
    132
    133int os_getpgrp(void)
    134{
    135	return getpgrp();
    136}
    137
    138int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
    139		  int r, int w, int x)
    140{
    141	void *loc;
    142	int prot;
    143
    144	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
    145		(x ? PROT_EXEC : 0);
    146
    147	loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
    148		     fd, off);
    149	if (loc == MAP_FAILED)
    150		return -errno;
    151	return 0;
    152}
    153
    154int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
    155{
    156	int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
    157		    (x ? PROT_EXEC : 0));
    158
    159	if (mprotect(addr, len, prot) < 0)
    160		return -errno;
    161
    162	return 0;
    163}
    164
    165int os_unmap_memory(void *addr, int len)
    166{
    167	int err;
    168
    169	err = munmap(addr, len);
    170	if (err < 0)
    171		return -errno;
    172	return 0;
    173}
    174
    175#ifndef MADV_REMOVE
    176#define MADV_REMOVE KERNEL_MADV_REMOVE
    177#endif
    178
    179int os_drop_memory(void *addr, int length)
    180{
    181	int err;
    182
    183	err = madvise(addr, length, MADV_REMOVE);
    184	if (err < 0)
    185		err = -errno;
    186	return err;
    187}
    188
    189int __init can_drop_memory(void)
    190{
    191	void *addr;
    192	int fd, ok = 0;
    193
    194	printk(UM_KERN_INFO "Checking host MADV_REMOVE support...");
    195	fd = create_mem_file(UM_KERN_PAGE_SIZE);
    196	if (fd < 0) {
    197		printk(UM_KERN_ERR "Creating test memory file failed, "
    198		       "err = %d\n", -fd);
    199		goto out;
    200	}
    201
    202	addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
    203		      MAP_SHARED, fd, 0);
    204	if (addr == MAP_FAILED) {
    205		printk(UM_KERN_ERR "Mapping test memory file failed, "
    206		       "err = %d\n", -errno);
    207		goto out_close;
    208	}
    209
    210	if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) {
    211		printk(UM_KERN_ERR "MADV_REMOVE failed, err = %d\n", -errno);
    212		goto out_unmap;
    213	}
    214
    215	printk(UM_KERN_CONT "OK\n");
    216	ok = 1;
    217
    218out_unmap:
    219	munmap(addr, UM_KERN_PAGE_SIZE);
    220out_close:
    221	close(fd);
    222out:
    223	return ok;
    224}
    225
    226static int os_page_mincore(void *addr)
    227{
    228	char vec[2];
    229	int ret;
    230
    231	ret = mincore(addr, UM_KERN_PAGE_SIZE, vec);
    232	if (ret < 0) {
    233		if (errno == ENOMEM || errno == EINVAL)
    234			return 0;
    235		else
    236			return -errno;
    237	}
    238
    239	return vec[0] & 1;
    240}
    241
    242int os_mincore(void *addr, unsigned long len)
    243{
    244	char *vec;
    245	int ret, i;
    246
    247	if (len <= UM_KERN_PAGE_SIZE)
    248		return os_page_mincore(addr);
    249
    250	vec = calloc(1, (len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE);
    251	if (!vec)
    252		return -ENOMEM;
    253
    254	ret = mincore(addr, UM_KERN_PAGE_SIZE, vec);
    255	if (ret < 0) {
    256		if (errno == ENOMEM || errno == EINVAL)
    257			ret = 0;
    258		else
    259			ret = -errno;
    260
    261		goto out;
    262	}
    263
    264	for (i = 0; i < ((len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); i++) {
    265		if (!(vec[i] & 1)) {
    266			ret = 0;
    267			goto out;
    268		}
    269	}
    270
    271	ret = 1;
    272out:
    273	free(vec);
    274	return ret;
    275}
    276
    277void init_new_thread_signals(void)
    278{
    279	set_handler(SIGSEGV);
    280	set_handler(SIGTRAP);
    281	set_handler(SIGFPE);
    282	set_handler(SIGILL);
    283	set_handler(SIGBUS);
    284	signal(SIGHUP, SIG_IGN);
    285	set_handler(SIGIO);
    286	signal(SIGWINCH, SIG_IGN);
    287}