brintos

brintos / linux-shallow public Read only

0
0
Text · 4.3 KiB · 0f38341 Raw
185 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Helper functions for handling target threads/cpus4 *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}185