[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.senozhat...@gmail.com>

---

 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);
 

_______________________________________________
Discuss mailing list
Discuss@lesswatts.org
http://lists.lesswatts.org/listinfo/discuss

Reply via email to