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