summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2023-05-05 20:23:15 +0200
committercgzones <cgzones@googlemail.com>2024-04-06 19:42:28 +0200
commitb4d5b5cea98f557a856c89500dc169f511a2b817 (patch)
treeaa57a74027c0e3b9b91dc7d5ecd14bcab04d315b
parenteb27a94ba411793aa1a25c331b3e1bb328739583 (diff)
Linux: gather permitted capabilities via capget(2)
#1211 has shown reading /proc/<pid>/status might have a significant performance impact. It was started to be read by default to gather the permitted capabilities of the process. Gather permitted capabilities via the syscall capget(2) instead. cap_get_proc(3) is not used to avoid linking with -lcap.
-rw-r--r--Process.c2
-rw-r--r--Process.h9
-rw-r--r--linux/LinuxProcessTable.c23
3 files changed, 24 insertions, 10 deletions
diff --git a/Process.c b/Process.c
index c343e77d..527fc201 100644
--- a/Process.c
+++ b/Process.c
@@ -736,7 +736,7 @@ void Process_writeField(const Process* this, RichString* str, RowField field) {
}
break;
case USER:
- if (this->elevated_priv)
+ if (this->elevated_priv == TRI_ON)
attr = CRT_colors[PROCESS_PRIV];
else if (host->htopUserId != this->st_uid)
attr = CRT_colors[PROCESS_SHADOW];
diff --git a/Process.h b/Process.h
index 6a80bc51..066c1402 100644
--- a/Process.h
+++ b/Process.h
@@ -24,6 +24,13 @@ in the source distribution for its full text.
#define DEFAULT_HIGHLIGHT_SECS 5
+typedef enum Tristate_ {
+ TRI_INITIAL = 0,
+ TRI_OFF = -1,
+ TRI_ON = 1,
+} Tristate;
+
+
/* Core process states (shared by platforms)
* NOTE: The enum has an ordering that is important!
* See processStateChar in process.c for ProcessSate -> letter mapping */
@@ -106,7 +113,7 @@ typedef struct Process_ {
* - from file capabilities
* - inherited from the ambient set
*/
- bool elevated_priv;
+ Tristate elevated_priv;
/* Process runtime (in hundredth of a second) */
unsigned long long int time;
diff --git a/linux/LinuxProcessTable.c b/linux/LinuxProcessTable.c
index 9a5ffdb4..57f93227 100644
--- a/linux/LinuxProcessTable.c
+++ b/linux/LinuxProcessTable.c
@@ -20,7 +20,9 @@ in the source distribution for its full text.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <syscall.h>
#include <unistd.h>
+#include <linux/capability.h> // raw syscall, no libcap // IWYU pragma: keep // IWYU pragma: no_include <sys/capability.h>
#include <sys/stat.h>
#include "Compat.h"
@@ -391,14 +393,6 @@ static bool LinuxProcessTable_readStatusFile(Process* process, openat_arg_t proc
if (pid_ns_count > 1)
process->isRunningInContainer = true;
- } else if (String_startsWith(buffer, "CapPrm:")) {
- char* ptr = buffer + strlen("CapPrm:");
- while (*ptr == ' ' || *ptr == '\t')
- ptr++;
-
- uint64_t cap_permitted = fast_strtoull_hex(&ptr, 16);
- process->elevated_priv = cap_permitted != 0 && process->st_uid != 0;
-
} else if (String_startsWith(buffer, "voluntary_ctxt_switches:")) {
unsigned long vctxt;
int ok = sscanf(buffer, "voluntary_ctxt_switches:\t%lu", &vctxt);
@@ -1481,6 +1475,19 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
}
}
+ /* Gather permitted capabilities (thread-specific data) for non-root process. */
+ if (proc->st_uid != 0 && proc->elevated_priv != TRI_OFF) {
+ struct __user_cap_header_struct header = { .version = _LINUX_CAPABILITY_VERSION_3, .pid = Process_getPid(proc) };
+ struct __user_cap_data_struct data;
+
+ long res = syscall(SYS_capget, &header, &data);
+ if (res == 0) {
+ proc->elevated_priv = (data.permitted != 0) ? TRI_ON : TRI_OFF;
+ } else {
+ proc->elevated_priv = TRI_OFF;
+ }
+ }
+
if (ss->flags & PROCESS_FLAG_LINUX_CGROUP)
LinuxProcessTable_readCGroupFile(lp, procFd);

© 2014-2024 Faster IT GmbH | imprint | privacy policy