18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Helper functions for handling target threads/cpus 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2012, LG Electronics, Namhyung Kim <namhyung.kim@lge.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "target.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <pwd.h> 118c2ecf20Sopenharmony_ci#include <stdio.h> 128c2ecf20Sopenharmony_ci#include <stdlib.h> 138c2ecf20Sopenharmony_ci#include <string.h> 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/string.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cienum target_errno target__validate(struct target *target) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci enum target_errno ret = TARGET_ERRNO__SUCCESS; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci if (target->pid) 228c2ecf20Sopenharmony_ci target->tid = target->pid; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci /* CPU and PID are mutually exclusive */ 258c2ecf20Sopenharmony_ci if (target->tid && target->cpu_list) { 268c2ecf20Sopenharmony_ci target->cpu_list = NULL; 278c2ecf20Sopenharmony_ci if (ret == TARGET_ERRNO__SUCCESS) 288c2ecf20Sopenharmony_ci ret = TARGET_ERRNO__PID_OVERRIDE_CPU; 298c2ecf20Sopenharmony_ci } 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci /* UID and PID are mutually exclusive */ 328c2ecf20Sopenharmony_ci if (target->tid && target->uid_str) { 338c2ecf20Sopenharmony_ci target->uid_str = NULL; 348c2ecf20Sopenharmony_ci if (ret == TARGET_ERRNO__SUCCESS) 358c2ecf20Sopenharmony_ci ret = TARGET_ERRNO__PID_OVERRIDE_UID; 368c2ecf20Sopenharmony_ci } 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci /* UID and CPU are mutually exclusive */ 398c2ecf20Sopenharmony_ci if (target->uid_str && target->cpu_list) { 408c2ecf20Sopenharmony_ci target->cpu_list = NULL; 418c2ecf20Sopenharmony_ci if (ret == TARGET_ERRNO__SUCCESS) 428c2ecf20Sopenharmony_ci ret = TARGET_ERRNO__UID_OVERRIDE_CPU; 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* PID and SYSTEM are mutually exclusive */ 468c2ecf20Sopenharmony_ci if (target->tid && target->system_wide) { 478c2ecf20Sopenharmony_ci target->system_wide = false; 488c2ecf20Sopenharmony_ci if (ret == TARGET_ERRNO__SUCCESS) 498c2ecf20Sopenharmony_ci ret = TARGET_ERRNO__PID_OVERRIDE_SYSTEM; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* UID and SYSTEM are mutually exclusive */ 538c2ecf20Sopenharmony_ci if (target->uid_str && target->system_wide) { 548c2ecf20Sopenharmony_ci target->system_wide = false; 558c2ecf20Sopenharmony_ci if (ret == TARGET_ERRNO__SUCCESS) 568c2ecf20Sopenharmony_ci ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM; 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* THREAD and SYSTEM/CPU are mutually exclusive */ 608c2ecf20Sopenharmony_ci if (target->per_thread && (target->system_wide || target->cpu_list)) { 618c2ecf20Sopenharmony_ci target->per_thread = false; 628c2ecf20Sopenharmony_ci if (ret == TARGET_ERRNO__SUCCESS) 638c2ecf20Sopenharmony_ci ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci return ret; 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cienum target_errno target__parse_uid(struct target *target) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci struct passwd pwd, *result; 728c2ecf20Sopenharmony_ci char buf[1024]; 738c2ecf20Sopenharmony_ci const char *str = target->uid_str; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci target->uid = UINT_MAX; 768c2ecf20Sopenharmony_ci if (str == NULL) 778c2ecf20Sopenharmony_ci return TARGET_ERRNO__SUCCESS; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* Try user name first */ 808c2ecf20Sopenharmony_ci getpwnam_r(str, &pwd, buf, sizeof(buf), &result); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci if (result == NULL) { 838c2ecf20Sopenharmony_ci /* 848c2ecf20Sopenharmony_ci * The user name not found. Maybe it's a UID number. 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ci char *endptr; 878c2ecf20Sopenharmony_ci int uid = strtol(str, &endptr, 10); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci if (*endptr != '\0') 908c2ecf20Sopenharmony_ci return TARGET_ERRNO__INVALID_UID; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci getpwuid_r(uid, &pwd, buf, sizeof(buf), &result); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (result == NULL) 958c2ecf20Sopenharmony_ci return TARGET_ERRNO__USER_NOT_FOUND; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci target->uid = result->pw_uid; 998c2ecf20Sopenharmony_ci return TARGET_ERRNO__SUCCESS; 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci/* 1038c2ecf20Sopenharmony_ci * This must have a same ordering as the enum target_errno. 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_cistatic const char *target__error_str[] = { 1068c2ecf20Sopenharmony_ci "PID/TID switch overriding CPU", 1078c2ecf20Sopenharmony_ci "PID/TID switch overriding UID", 1088c2ecf20Sopenharmony_ci "UID switch overriding CPU", 1098c2ecf20Sopenharmony_ci "PID/TID switch overriding SYSTEM", 1108c2ecf20Sopenharmony_ci "UID switch overriding SYSTEM", 1118c2ecf20Sopenharmony_ci "SYSTEM/CPU switch overriding PER-THREAD", 1128c2ecf20Sopenharmony_ci "Invalid User: %s", 1138c2ecf20Sopenharmony_ci "Problems obtaining information for user %s", 1148c2ecf20Sopenharmony_ci}; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ciint target__strerror(struct target *target, int errnum, 1178c2ecf20Sopenharmony_ci char *buf, size_t buflen) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci int idx; 1208c2ecf20Sopenharmony_ci const char *msg; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci BUG_ON(buflen == 0); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (errnum >= 0) { 1258c2ecf20Sopenharmony_ci str_error_r(errnum, buf, buflen); 1268c2ecf20Sopenharmony_ci return 0; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci if (errnum < __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END) 1308c2ecf20Sopenharmony_ci return -1; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci idx = errnum - __TARGET_ERRNO__START; 1338c2ecf20Sopenharmony_ci msg = target__error_str[idx]; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci switch (errnum) { 1368c2ecf20Sopenharmony_ci case TARGET_ERRNO__PID_OVERRIDE_CPU ... 1378c2ecf20Sopenharmony_ci TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD: 1388c2ecf20Sopenharmony_ci snprintf(buf, buflen, "%s", msg); 1398c2ecf20Sopenharmony_ci break; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci case TARGET_ERRNO__INVALID_UID: 1428c2ecf20Sopenharmony_ci case TARGET_ERRNO__USER_NOT_FOUND: 1438c2ecf20Sopenharmony_ci snprintf(buf, buflen, msg, target->uid_str); 1448c2ecf20Sopenharmony_ci break; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci default: 1478c2ecf20Sopenharmony_ci /* cannot reach here */ 1488c2ecf20Sopenharmony_ci break; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci return 0; 1528c2ecf20Sopenharmony_ci} 153