1 // SPDX-License-Identifier: GPL-2.0-only
3 * Helper functions for handling target threads/cpus
5 * Copyright (C) 2012, LG Electronics, Namhyung Kim <namhyung.kim@lge.com>
14 #include <linux/kernel.h>
15 #include <linux/string.h>
17 enum target_errno
target__validate(struct target
*target
)
19 enum target_errno ret
= TARGET_ERRNO__SUCCESS
;
22 target
->tid
= target
->pid
;
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
;
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
;
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
;
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
;
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
;
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
;
66 /* BPF and PID/TID are mutually exclusive */
67 if (target
->bpf_str
&& target
->tid
) {
69 if (ret
== TARGET_ERRNO__SUCCESS
)
70 ret
= TARGET_ERRNO__BPF_OVERRIDE_PID
;
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
;
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
;
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
;
97 enum target_errno
target__parse_uid(struct target
*target
)
99 struct passwd pwd
, *result
;
101 const char *str
= target
->uid_str
;
103 target
->uid
= UINT_MAX
;
105 return TARGET_ERRNO__SUCCESS
;
107 /* Try user name first */
108 getpwnam_r(str
, &pwd
, buf
, sizeof(buf
), &result
);
110 if (result
== NULL
) {
112 * The user name not found. Maybe it's a UID number.
115 int uid
= strtol(str
, &endptr
, 10);
118 return TARGET_ERRNO__INVALID_UID
;
120 getpwuid_r(uid
, &pwd
, buf
, sizeof(buf
), &result
);
123 return TARGET_ERRNO__USER_NOT_FOUND
;
126 target
->uid
= result
->pw_uid
;
127 return TARGET_ERRNO__SUCCESS
;
131 * This must have a same ordering as the enum target_errno.
133 static 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",
145 "Problems obtaining information for user %s",
148 int target__strerror(struct target
*target
, int errnum
,
149 char *buf
, size_t buflen
)
157 str_error_r(errnum
, buf
, buflen
);
161 if (errnum
< __TARGET_ERRNO__START
|| errnum
>= __TARGET_ERRNO__END
)
164 idx
= errnum
- __TARGET_ERRNO__START
;
165 msg
= target__error_str
[idx
];
168 case TARGET_ERRNO__PID_OVERRIDE_CPU
...
169 TARGET_ERRNO__BPF_OVERRIDE_THREAD
:
170 snprintf(buf
, buflen
, "%s", msg
);
173 case TARGET_ERRNO__INVALID_UID
:
174 case TARGET_ERRNO__USER_NOT_FOUND
:
175 snprintf(buf
, buflen
, msg
, target
->uid_str
);
179 /* cannot reach here */