Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Helper functions for handling target threads/cpus
0004  *
0005  * Copyright (C) 2012, LG Electronics, Namhyung Kim <namhyung.kim@lge.com>
0006  */
0007 
0008 #include "target.h"
0009 
0010 #include <pwd.h>
0011 #include <stdio.h>
0012 #include <stdlib.h>
0013 #include <string.h>
0014 #include <linux/kernel.h>
0015 #include <linux/string.h>
0016 
0017 enum target_errno target__validate(struct target *target)
0018 {
0019     enum target_errno ret = TARGET_ERRNO__SUCCESS;
0020 
0021     if (target->pid)
0022         target->tid = target->pid;
0023 
0024     /* CPU and PID are mutually exclusive */
0025     if (target->tid && target->cpu_list) {
0026         target->cpu_list = NULL;
0027         if (ret == TARGET_ERRNO__SUCCESS)
0028             ret = TARGET_ERRNO__PID_OVERRIDE_CPU;
0029     }
0030 
0031     /* UID and PID are mutually exclusive */
0032     if (target->tid && target->uid_str) {
0033         target->uid_str = NULL;
0034         if (ret == TARGET_ERRNO__SUCCESS)
0035             ret = TARGET_ERRNO__PID_OVERRIDE_UID;
0036     }
0037 
0038     /* UID and CPU are mutually exclusive */
0039     if (target->uid_str && target->cpu_list) {
0040         target->cpu_list = NULL;
0041         if (ret == TARGET_ERRNO__SUCCESS)
0042             ret = TARGET_ERRNO__UID_OVERRIDE_CPU;
0043     }
0044 
0045     /* PID and SYSTEM are mutually exclusive */
0046     if (target->tid && target->system_wide) {
0047         target->system_wide = false;
0048         if (ret == TARGET_ERRNO__SUCCESS)
0049             ret = TARGET_ERRNO__PID_OVERRIDE_SYSTEM;
0050     }
0051 
0052     /* UID and SYSTEM are mutually exclusive */
0053     if (target->uid_str && target->system_wide) {
0054         target->system_wide = false;
0055         if (ret == TARGET_ERRNO__SUCCESS)
0056             ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM;
0057     }
0058 
0059     /* BPF and CPU are mutually exclusive */
0060     if (target->bpf_str && target->cpu_list) {
0061         target->cpu_list = NULL;
0062         if (ret == TARGET_ERRNO__SUCCESS)
0063             ret = TARGET_ERRNO__BPF_OVERRIDE_CPU;
0064     }
0065 
0066     /* BPF and PID/TID are mutually exclusive */
0067     if (target->bpf_str && target->tid) {
0068         target->tid = NULL;
0069         if (ret == TARGET_ERRNO__SUCCESS)
0070             ret = TARGET_ERRNO__BPF_OVERRIDE_PID;
0071     }
0072 
0073     /* BPF and UID are mutually exclusive */
0074     if (target->bpf_str && target->uid_str) {
0075         target->uid_str = NULL;
0076         if (ret == TARGET_ERRNO__SUCCESS)
0077             ret = TARGET_ERRNO__BPF_OVERRIDE_UID;
0078     }
0079 
0080     /* BPF and THREADS are mutually exclusive */
0081     if (target->bpf_str && target->per_thread) {
0082         target->per_thread = false;
0083         if (ret == TARGET_ERRNO__SUCCESS)
0084             ret = TARGET_ERRNO__BPF_OVERRIDE_THREAD;
0085     }
0086 
0087     /* THREAD and SYSTEM/CPU are mutually exclusive */
0088     if (target->per_thread && (target->system_wide || target->cpu_list)) {
0089         target->per_thread = false;
0090         if (ret == TARGET_ERRNO__SUCCESS)
0091             ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD;
0092     }
0093 
0094     return ret;
0095 }
0096 
0097 enum target_errno target__parse_uid(struct target *target)
0098 {
0099     struct passwd pwd, *result;
0100     char buf[1024];
0101     const char *str = target->uid_str;
0102 
0103     target->uid = UINT_MAX;
0104     if (str == NULL)
0105         return TARGET_ERRNO__SUCCESS;
0106 
0107     /* Try user name first */
0108     getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
0109 
0110     if (result == NULL) {
0111         /*
0112          * The user name not found. Maybe it's a UID number.
0113          */
0114         char *endptr;
0115         int uid = strtol(str, &endptr, 10);
0116 
0117         if (*endptr != '\0')
0118             return TARGET_ERRNO__INVALID_UID;
0119 
0120         getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
0121 
0122         if (result == NULL)
0123             return TARGET_ERRNO__USER_NOT_FOUND;
0124     }
0125 
0126     target->uid = result->pw_uid;
0127     return TARGET_ERRNO__SUCCESS;
0128 }
0129 
0130 /*
0131  * This must have a same ordering as the enum target_errno.
0132  */
0133 static const char *target__error_str[] = {
0134     "PID/TID switch overriding CPU",
0135     "PID/TID switch overriding UID",
0136     "UID switch overriding CPU",
0137     "PID/TID switch overriding SYSTEM",
0138     "UID switch overriding SYSTEM",
0139     "SYSTEM/CPU switch overriding PER-THREAD",
0140     "BPF switch overriding CPU",
0141     "BPF switch overriding PID/TID",
0142     "BPF switch overriding UID",
0143     "BPF switch overriding THREAD",
0144     "Invalid User: %s",
0145     "Problems obtaining information for user %s",
0146 };
0147 
0148 int target__strerror(struct target *target, int errnum,
0149               char *buf, size_t buflen)
0150 {
0151     int idx;
0152     const char *msg;
0153 
0154     BUG_ON(buflen == 0);
0155 
0156     if (errnum >= 0) {
0157         str_error_r(errnum, buf, buflen);
0158         return 0;
0159     }
0160 
0161     if (errnum <  __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END)
0162         return -1;
0163 
0164     idx = errnum - __TARGET_ERRNO__START;
0165     msg = target__error_str[idx];
0166 
0167     switch (errnum) {
0168     case TARGET_ERRNO__PID_OVERRIDE_CPU ...
0169          TARGET_ERRNO__BPF_OVERRIDE_THREAD:
0170         snprintf(buf, buflen, "%s", msg);
0171         break;
0172 
0173     case TARGET_ERRNO__INVALID_UID:
0174     case TARGET_ERRNO__USER_NOT_FOUND:
0175         snprintf(buf, buflen, msg, target->uid_str);
0176         break;
0177 
0178     default:
0179         /* cannot reach here */
0180         break;
0181     }
0182 
0183     return 0;
0184 }