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

target.c (4419B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Helper functions for handling target threads/cpus
      4 *
      5 * Copyright (C) 2012, LG Electronics, Namhyung Kim <namhyung.kim@lge.com>
      6 */
      7
      8#include "target.h"
      9
     10#include <pwd.h>
     11#include <stdio.h>
     12#include <stdlib.h>
     13#include <string.h>
     14#include <linux/kernel.h>
     15#include <linux/string.h>
     16
     17enum target_errno target__validate(struct target *target)
     18{
     19	enum target_errno ret = TARGET_ERRNO__SUCCESS;
     20
     21	if (target->pid)
     22		target->tid = target->pid;
     23
     24	/* CPU and PID are mutually exclusive */
     25	if (target->tid && target->cpu_list) {
     26		target->cpu_list = NULL;
     27		if (ret == TARGET_ERRNO__SUCCESS)
     28			ret = TARGET_ERRNO__PID_OVERRIDE_CPU;
     29	}
     30
     31	/* UID and PID are mutually exclusive */
     32	if (target->tid && target->uid_str) {
     33		target->uid_str = NULL;
     34		if (ret == TARGET_ERRNO__SUCCESS)
     35			ret = TARGET_ERRNO__PID_OVERRIDE_UID;
     36	}
     37
     38	/* UID and CPU are mutually exclusive */
     39	if (target->uid_str && target->cpu_list) {
     40		target->cpu_list = NULL;
     41		if (ret == TARGET_ERRNO__SUCCESS)
     42			ret = TARGET_ERRNO__UID_OVERRIDE_CPU;
     43	}
     44
     45	/* PID and SYSTEM are mutually exclusive */
     46	if (target->tid && target->system_wide) {
     47		target->system_wide = false;
     48		if (ret == TARGET_ERRNO__SUCCESS)
     49			ret = TARGET_ERRNO__PID_OVERRIDE_SYSTEM;
     50	}
     51
     52	/* UID and SYSTEM are mutually exclusive */
     53	if (target->uid_str && target->system_wide) {
     54		target->system_wide = false;
     55		if (ret == TARGET_ERRNO__SUCCESS)
     56			ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM;
     57	}
     58
     59	/* BPF and CPU are mutually exclusive */
     60	if (target->bpf_str && target->cpu_list) {
     61		target->cpu_list = NULL;
     62		if (ret == TARGET_ERRNO__SUCCESS)
     63			ret = TARGET_ERRNO__BPF_OVERRIDE_CPU;
     64	}
     65
     66	/* BPF and PID/TID are mutually exclusive */
     67	if (target->bpf_str && target->tid) {
     68		target->tid = NULL;
     69		if (ret == TARGET_ERRNO__SUCCESS)
     70			ret = TARGET_ERRNO__BPF_OVERRIDE_PID;
     71	}
     72
     73	/* BPF and UID are mutually exclusive */
     74	if (target->bpf_str && target->uid_str) {
     75		target->uid_str = NULL;
     76		if (ret == TARGET_ERRNO__SUCCESS)
     77			ret = TARGET_ERRNO__BPF_OVERRIDE_UID;
     78	}
     79
     80	/* BPF and THREADS are mutually exclusive */
     81	if (target->bpf_str && target->per_thread) {
     82		target->per_thread = false;
     83		if (ret == TARGET_ERRNO__SUCCESS)
     84			ret = TARGET_ERRNO__BPF_OVERRIDE_THREAD;
     85	}
     86
     87	/* THREAD and SYSTEM/CPU are mutually exclusive */
     88	if (target->per_thread && (target->system_wide || target->cpu_list)) {
     89		target->per_thread = false;
     90		if (ret == TARGET_ERRNO__SUCCESS)
     91			ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD;
     92	}
     93
     94	return ret;
     95}
     96
     97enum target_errno target__parse_uid(struct target *target)
     98{
     99	struct passwd pwd, *result;
    100	char buf[1024];
    101	const char *str = target->uid_str;
    102
    103	target->uid = UINT_MAX;
    104	if (str == NULL)
    105		return TARGET_ERRNO__SUCCESS;
    106
    107	/* Try user name first */
    108	getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
    109
    110	if (result == NULL) {
    111		/*
    112		 * The user name not found. Maybe it's a UID number.
    113		 */
    114		char *endptr;
    115		int uid = strtol(str, &endptr, 10);
    116
    117		if (*endptr != '\0')
    118			return TARGET_ERRNO__INVALID_UID;
    119
    120		getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
    121
    122		if (result == NULL)
    123			return TARGET_ERRNO__USER_NOT_FOUND;
    124	}
    125
    126	target->uid = result->pw_uid;
    127	return TARGET_ERRNO__SUCCESS;
    128}
    129
    130/*
    131 * This must have a same ordering as the enum target_errno.
    132 */
    133static const char *target__error_str[] = {
    134	"PID/TID switch overriding CPU",
    135	"PID/TID switch overriding UID",
    136	"UID switch overriding CPU",
    137	"PID/TID switch overriding SYSTEM",
    138	"UID switch overriding SYSTEM",
    139	"SYSTEM/CPU switch overriding PER-THREAD",
    140	"BPF switch overriding CPU",
    141	"BPF switch overriding PID/TID",
    142	"BPF switch overriding UID",
    143	"BPF switch overriding THREAD",
    144	"Invalid User: %s",
    145	"Problems obtaining information for user %s",
    146};
    147
    148int target__strerror(struct target *target, int errnum,
    149			  char *buf, size_t buflen)
    150{
    151	int idx;
    152	const char *msg;
    153
    154	BUG_ON(buflen == 0);
    155
    156	if (errnum >= 0) {
    157		str_error_r(errnum, buf, buflen);
    158		return 0;
    159	}
    160
    161	if (errnum <  __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END)
    162		return -1;
    163
    164	idx = errnum - __TARGET_ERRNO__START;
    165	msg = target__error_str[idx];
    166
    167	switch (errnum) {
    168	case TARGET_ERRNO__PID_OVERRIDE_CPU ...
    169	     TARGET_ERRNO__BPF_OVERRIDE_THREAD:
    170		snprintf(buf, buflen, "%s", msg);
    171		break;
    172
    173	case TARGET_ERRNO__INVALID_UID:
    174	case TARGET_ERRNO__USER_NOT_FOUND:
    175		snprintf(buf, buflen, msg, target->uid_str);
    176		break;
    177
    178	default:
    179		/* cannot reach here */
    180		break;
    181	}
    182
    183	return 0;
    184}