[2.1 SUP]
Introduce uid_t ruid member variable -- owner's real uid.
By default ruid should have (uid_t)-1 value.
Move /proc/PID/* parsing logic out from constructor to separate
init_process() function, returning parsed ruid value. Due to events
processing delay (in measurement) process (and corresponding /proc/PID/*
files) may went away by the time we start processing. In this case we can't
find process owner's ruid, so (uid_t)-1 guarantees that such process will
not get into all_processes/all_power.
Change find_create_process() so it can return NULL if process owner's
ruid is not matched to user supplied uid. This also implies that
sched:sched_switch and sched:sched_wakeup events will be processed only
for user's processes.
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky-***@public.gmane.org>
---
process/process.cpp | 92 ++++++++++++++++++++++++++++++++++----------------
process/process.h | 5 ++-
2 files changed, 65 insertions(+), 32 deletions(-)
diff --git a/process/process.cpp b/process/process.cpp
index 0b0f788..45e79a4 100644
--- a/process/process.cpp
+++ b/process/process.cpp
@@ -82,45 +82,47 @@ static void cmdline_to_string(char *str)
}
}
-
-process::process(const char *_comm, int _pid, int _tid) : power_consumer()
+/* return processes uid or (uid_t)-1 if not parsed.
+ */
+uid_t process::init_process()
{
char line[4096];
ifstream file;
- strcpy(comm, _comm);
- pid = _pid;
- is_idle = 0;
- running = 0;
- last_waker = NULL;
- waker = NULL;
- is_kernel = 0;
- tgid = _tid;
-
- if (_tid == 0) {
- sprintf(line, "/proc/%i/status", _pid);
- file.open(line);
- while (file) {
- file.getline(line, 4096);
- if (strstr(line, "Tgid")) {
- char *c;
- c = strchr(line, ':');
- if (!c)
- continue;
- c++;
- tgid = strtoull(c, NULL, 10);
- break;
- }
+ /* Process may be gone by the time we reach this path due
+ * to sleep in measurement. The following two reads may fail as
+ * a result.
+ */
+ char to_read = 2;
+ sprintf(line, "/proc/%i/status", pid);
+ file.open(line);
+ while (file) {
+ if (to_read < 1) break;
+ file.getline(line, 4096);
+ if (tgid == 0 && strstr(line, "Tgid")) {
+ char *c;
+ c = strchr(line, ':');
+ if (!c)
+ continue;
+ c++;
+ tgid = strtoull(c, NULL, 10);
+ --to_read;
+ continue;
+ }
+ if (strstr(line, "Uid")) {
+ /* get real UID */
+ /* sscanf(line, "Uid: %d %d %d %d", &ruid, &euid, &suid, &fuid); */
+ sscanf(line, "Uid: %d", &ruid);
+ --to_read;
+ continue;
}
- file.close();
}
+ file.close();
- if (strncmp(_comm, "kondemand/", 10) == 0)
+ if (strncmp(comm, "kondemand/", 10) == 0)
is_idle = 1;
- strcpy(desc, comm);
-
- sprintf(line, "/proc/%i/cmdline", _pid);
+ sprintf(line, "/proc/%i/cmdline", pid);
file.open(line, ios::binary);
if (file) {
memset(line, 0, sizeof(line));
@@ -136,6 +138,26 @@ process::process(const char *_comm, int _pid, int _tid) : power_consumer()
desc[sz] = 0x00;
}
}
+
+ return ruid;
+}
+
+process::process(const char *_comm, int _pid, int _tid) : power_consumer()
+{
+ strcpy(comm, _comm);
+ strcpy(desc, comm);
+ pid = _pid;
+ is_idle = 0;
+ running = 0;
+ last_waker = NULL;
+ waker = NULL;
+ is_kernel = 0;
+ tgid = _tid;
+ /* Since process may already went away, setting ruid to -1
+ * will guarantee that 'orphan' event will not get into
+ * user's statistics.
+ */
+ ruid = -1;
}
const char * process::description(void)
@@ -169,6 +191,16 @@ class process * find_create_process(char *comm, int pid)
return it->second;
new_proc = new class process(comm, pid);
+ /* init_process will return uid (if parsed). If uid has
+ * been set by user, only processes with matched uid will
+ * get into all_processes. This also implies that sched:sched_switch
+ * and sched:sched_wakeup events will be processed only for user's
+ * processes.
+ */
+ if ( !match_uid(new_proc->init_process()) ) {
+ delete new_proc;
+ return NULL;
+ }
/* The trick is to use process->comm as the key. comm has the same
* life-time as the corresponding process does, so we can avoid
diff --git a/process/process.h b/process/process.h
index 777e90d..181be5c 100644
--- a/process/process.h
+++ b/process/process.h
@@ -29,6 +29,7 @@
#include <map>
#include <string.h>
#include "powerconsumer.h"
+#include "../lib.h"
#ifdef __x86_64__
#define BIT64 1
@@ -47,14 +48,14 @@ public:
int tgid;
char comm[16];
int pid;
-
+ uid_t ruid;
int is_idle; /* count this as if the cpu was idle */
int running;
int is_kernel; /* kernel thread */
process(const char *_comm, int _pid, int _tid = 0);
-
+ uid_t init_process();
virtual void schedule_thread(uint64_t time, int thread_id);
virtual uint64_t deschedule_thread(uint64_t time, int thread_id = 0);