]> granicus.if.org Git - procps-ng/commitdiff
EVIL_PROC_HACK
authoralbert <>
Wed, 17 Sep 2003 21:58:32 +0000 (21:58 +0000)
committeralbert <>
Wed, 17 Sep 2003 21:58:32 +0000 (21:58 +0000)
NEWS
proc/library.map
proc/readproc.c
proc/readproc.h
ps/common.h
ps/display.c

diff --git a/NEWS b/NEWS
index 284fcfb3e1f77b5f2ae1f821724f7837f38e852e..c8f729b2e993f8e69e9823749d1e9b0939a6f3f4 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+procps-3.1.12 --> procps-3.1.13
+
+no seLinux for now (new kernel interface)
+
 procps-3.1.11 --> procps-3.1.12
 
 ps: explicit width ("ps -o pid,wchan:42,args")
index 52ebcc28f0d3d666136c17c3775607589324c7df..810440d60d35d442223c9923bcbc171e2724d865 100644 (file)
@@ -1,8 +1,8 @@
-_3_1_5 {
+_3_1_12 {
 global:
   __cyg_profile_func_enter; __cyg_profile_func_exit; main;
 
-  readproc; readproctab; ps_readproc; look_up_our_self; escape_command;
+  readproc; readproctab; look_up_our_self; escape_command;
   escape_str; escape_strlist;
   openproc; closeproc;
   tty_to_dev; dev_to_tty; open_psdb_message; open_psdb; wchan;
index dada3a3bca2279f6e33d9bd19c98d750f33562d5..4f83024e31f551ba39dc68a2e7492ca1bc6f93e6 100644 (file)
@@ -31,6 +31,7 @@
 #include <fs_secure.h>
 #endif
 
+// sometimes it's easier to do this manually, w/o gcc helping
 #ifdef PROF
 extern void __cyg_profile_func_enter(void*,void*);
 #define ENTER(x) __cyg_profile_func_enter((void*)x,(void*)x)
@@ -40,52 +41,6 @@ extern void __cyg_profile_func_enter(void*,void*);
 #define LEAVE(x)
 #endif
 
-/* initiate a process table scan
- */
-PROCTAB* openproc(int flags, ...) {
-    va_list ap;
-    PROCTAB* PT = xmalloc(sizeof(PROCTAB));
-    
-    if (flags & PROC_PID)
-      PT->procfs = NULL;
-    else if (!(PT->procfs = opendir("/proc")))
-      return NULL;
-    PT->flags = flags;
-    va_start(ap, flags);               /*  Init args list */
-    if (flags & PROC_PID)
-       PT->pids = va_arg(ap, pid_t*);
-    else if (flags & PROC_UID) {
-       PT->uids = va_arg(ap, uid_t*);
-       PT->nuid = va_arg(ap, int);
-    }
-    va_end(ap);                                /*  Clean up args list */
-    return PT;
-}
-
-/* terminate a process table scan
- */
-void closeproc(PROCTAB* PT) {
-    if (PT){
-        if (PT->procfs) closedir(PT->procfs);
-        free(PT);
-    }
-}
-
-/* deallocate the space allocated by readproc if the passed rbuf was NULL
- */
-void freeproc(proc_t* p) {
-    if (!p)    /* in case p is NULL */
-       return;
-    /* ptrs are after strings to avoid copying memory when building them. */
-    /* so free is called on the address of the address of strvec[0]. */
-    if (p->cmdline)
-       free((void*)*p->cmdline);
-    if (p->environ)
-       free((void*)*p->environ);
-    free(p);
-}
-
-
 ///////////////////////////////////////////////////////////////////////////
 
 typedef struct status_table_struct {
@@ -505,66 +460,23 @@ int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
            i < n && l[i] == x;                 \
        } )
 
-/* readproc: return a pointer to a proc_t filled with requested info about the
- * next process available matching the restriction set.  If no more such
- * processes are available, return a null pointer (boolean false).  Use the
- * passed buffer instead of allocating space if it is non-NULL.  */
+//////////////////////////////////////////////////////////////////////////////////
+// This reads process info from /proc in the traditional way, for one process.
+// The pid (tgid? tid?) is already in p, and a path to it in path, with some
+// room to spare.
+static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
+    static struct stat sb;             // stat() buffer
+    static char sbuf[1024];    // buffer for stat,statm
+    unsigned flags = PT->flags;
 
-/* This is optimized so that if a PID list is given, only those files are
- * searched for in /proc.  If other lists are given in addition to the PID list,
- * the same logic can follow through as for the no-PID list case.  This is
- * fairly complex, but it does try to not to do any unnecessary work.
- */
-proc_t* readproc(PROCTAB* PT, proc_t* p) {
-    static struct direct *ent;         /* dirent handle */
-    static struct stat sb;             /* stat buffer */
-    static char path[32], sbuf[1024];  /* bufs for stat,statm */
-#ifdef FLASK_LINUX
-    security_id_t secsid;
-#endif
-    pid_t pid;  // saved until we have a proc_t allocated for sure
-
-    /* loop until a proc matching restrictions is found or no more processes */
-    /* I know this could be a while loop -- this way is easier to indent ;-) */
-next_proc:                             /* get next PID for consideration */
-
-/*printf("PT->flags is 0x%08x\n", PT->flags);*/
-#define flags (PT->flags)
-
-    if (flags & PROC_PID) {
-        pid = *(PT->pids)++;
-       if (unlikely(!pid)) return NULL;
-       snprintf(path, sizeof path, "/proc/%d", pid);
-    } else {                                   /* get next numeric /proc ent */
-       for (;;) {
-           ent = readdir(PT->procfs);
-           if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))) return NULL;
-           if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') )) break;
-       }
-       pid = strtoul(ent->d_name, NULL, 10);
-       memcpy(path, "/proc/", 6);
-       strcpy(path+6, ent->d_name);  // trust /proc to not contain evil top-level entries
-//     snprintf(path, sizeof path, "/proc/%s", ent->d_name);
-    }
-#ifdef FLASK_LINUX
-    if ( stat_secure(path, &sb, &secsid) == -1 ) /* no such dirent (anymore) */
-#else
     if (unlikely(stat(path, &sb) == -1))       /* no such dirent (anymore) */
-#endif
        goto next_proc;
 
     if ((flags & PROC_UID) && !XinLN(uid_t, sb.st_uid, PT->uids, PT->nuid))
        goto next_proc;                 /* not one of the requested uids */
 
-    if (!p)
-       p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
-
     p->euid = sb.st_uid;                       /* need a way to get real uid */
     p->egid = sb.st_gid;                       /* need a way to get real gid */
-#ifdef FLASK_LINUX
-    p->secsid = secsid;
-#endif
-    p->pid  = pid;
 
     if (flags & PROC_FILLSTAT) {         /* read, parse /proc/#/stat */
        if (unlikely( file2str(path, "stat", sbuf, sizeof sbuf) == -1 ))
@@ -572,7 +484,7 @@ next_proc:                          /* get next PID for consideration */
        stat2proc(sbuf, p);                             /* parse /proc/#/stat */
     }
 
-    if (unlikely(flags & PROC_FILLMEM)) {                              /* read, parse /proc/#/statm */
+    if (unlikely(flags & PROC_FILLMEM)) {      /* read, parse /proc/#/statm */
        if (likely( file2str(path, "statm", sbuf, sizeof sbuf) != -1 ))
            statm2proc(sbuf, p);                /* ignore statm errors here */
     }                                          /* statm fields just zero */
@@ -614,10 +526,54 @@ next_proc:                                /* get next PID for consideration */
         p->environ = NULL;
     
     return p;
+next_proc:
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// This finds processes in /proc in the traditional way.
+// Return non-zero on success.
+static int simple_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
+  static struct direct *ent;           /* dirent handle */
+  for (;;) {
+    ent = readdir(PT->procfs);
+    if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))) return 0;
+    if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') )) break;
+  }
+  p->pid = strtoul(ent->d_name, NULL, 10);
+  memcpy(path, "/proc/", 6);
+  strcpy(path+6, ent->d_name);  // trust /proc to not contain evil top-level entries
+  return 1;
 }
-#undef flags
 
-/* ps_readproc: return a pointer to a proc_t filled with requested info about the
+#define PROCPATHLEN 64   // must hold /proc/2000222000/task/2000222000/cmdline
+
+//////////////////////////////////////////////////////////////////////////////////
+// This "finds" processes in a list that was given to openproc().
+// Return non-zero on success. (pid was handy)
+static int listed_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
+  pid_t pid = *(PT->pids)++;
+  if(likely( pid )){
+    snprintf(path, PROCPATHLEN, "/proc/%d", pid);
+    p->pid = pid;
+  }
+  return pid;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// This "finds" processes by guessing every possible one of them.
+// Return non-zero on success. (pid was handy)
+static int stupid_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
+  pid_t pid = --PT->u;
+  if(likely( pid )){
+    snprintf(path, PROCPATHLEN, "/proc/%d", pid);
+    p->pid = pid;
+  }
+  return pid;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+/* readproc: return a pointer to a proc_t filled with requested info about the
  * next process available matching the restriction set.  If no more such
  * processes are available, return a null pointer (boolean false).  Use the
  * passed buffer instead of allocating space if it is non-NULL.  */
@@ -627,99 +583,86 @@ next_proc:                                /* get next PID for consideration */
  * the same logic can follow through as for the no-PID list case.  This is
  * fairly complex, but it does try to not to do any unnecessary work.
  */
-proc_t* ps_readproc(PROCTAB* PT, proc_t* p) {
-    static struct direct *ent;         /* dirent handle */
-    static struct stat sb;             /* stat buffer */
-    static char path[32], sbuf[1024];  /* bufs for stat,statm */
-#ifdef FLASK_LINUX
-    security_id_t secsid;
-#endif
-    pid_t pid;  // saved until we have a proc_t allocated for sure
-
-    /* loop until a proc matching restrictions is found or no more processes */
-    /* I know this could be a while loop -- this way is easier to indent ;-) */
-next_proc:                             /* get next PID for consideration */
+proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict p) {
+  static char path[PROCPATHLEN];       // must hold /proc/2000222000/task/2000222000/cmdline
+  proc_t *ret;
+  proc_t *saved_p;
+
+  saved_p = p;
+  if(!p) p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
+
+  for(;;){
+    // fills in the path and the p->pid
+    if (unlikely(! PT->finder(PT,p,path) )) goto out;
+
+    // go read the process data
+    ret = PT->reader(PT,p,path);
+    if(ret) return ret;
+  }
+
+out:
+  if(!saved_p) free(p);
+  return NULL;
+}
 
-/*printf("PT->flags is 0x%08x\n", PT->flags);*/
-#define flags (PT->flags)
+//////////////////////////////////////////////////////////////////////////////////
 
-    for (;;) {
-       ent = readdir(PT->procfs);
-       if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))) return NULL;
-       if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') )) break;
+// initiate a process table scan
+PROCTAB* openproc(int flags, ...) {
+    va_list ap;
+    PROCTAB* PT = xmalloc(sizeof(PROCTAB));
+    
+    PT->reader = simple_readproc;
+    if (flags & PROC_PID){
+      PT->procfs = NULL;
+      PT->finder = listed_nextpid;
+    }else{
+      PT->procfs = opendir("/proc");
+      if(!PT->procfs) return NULL;
+      PT->finder = simple_nextpid;
     }
-    pid = strtoul(ent->d_name, NULL, 10);
-    memcpy(path, "/proc/", 6);
-    strcpy(path+6, ent->d_name);  // trust /proc to not contain evil top-level entries
-//  snprintf(path, sizeof path, "/proc/%s", ent->d_name);
-
-#ifdef FLASK_LINUX
-    if (stat_secure(path, &sb, &secsid) == -1) /* no such dirent (anymore) */
-#else
-    if (stat(path, &sb) == -1)         /* no such dirent (anymore) */
-#endif
-       goto next_proc;
-
-    if (!p)
-       p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
-
-    p->euid = sb.st_uid;                       /* need a way to get real uid */
-    p->egid = sb.st_gid;                       /* need a way to get real gid */
-#ifdef FLASK_LINUX
-    p->secsid = secsid;
-#endif
-    p->pid  = pid;
-
-    if ((file2str(path, "stat", sbuf, sizeof sbuf)) == -1)
-       goto next_proc;                 /* error reading /proc/#/stat */
-    stat2proc(sbuf, p);                                /* parse /proc/#/stat */
-
-    if (flags & PROC_FILLMEM) {                                /* read, parse /proc/#/statm */
-       if ((file2str(path, "statm", sbuf, sizeof sbuf)) != -1 )
-           statm2proc(sbuf, p);                /* ignore statm errors here */
-    }                                          /* statm fields just zero */
-
-  /*  if (flags & PROC_FILLSTATUS) { */        /* read, parse /proc/#/status */
-       if ((file2str(path, "status", sbuf, sizeof sbuf)) != -1 ){
-           status2proc(sbuf, p);
-       }
-/*    }*/
+    PT->flags = flags;
 
-    /* some number->text resolving which is time consuming */
-    if (flags & PROC_FILLUSR){
-       strncpy(p->euser,   user_from_uid(p->euid), sizeof p->euser);
-/*        if(flags & PROC_FILLSTATUS) { */
-            strncpy(p->ruser,   user_from_uid(p->ruid), sizeof p->ruser);
-            strncpy(p->suser,   user_from_uid(p->suid), sizeof p->suser);
-            strncpy(p->fuser,   user_from_uid(p->fuid), sizeof p->fuser);
-/*        }*/
+    if(getenv("EVIL_PROC_HACK")){
+      PT->finder = stupid_nextpid;
+      PT->u = 10000;
     }
 
-    /* some number->text resolving which is time consuming */
-    if (flags & PROC_FILLGRP){
-        strncpy(p->egroup, group_from_gid(p->egid), sizeof p->egroup);
-/*        if(flags & PROC_FILLSTATUS) { */
-            strncpy(p->rgroup, group_from_gid(p->rgid), sizeof p->rgroup);
-            strncpy(p->sgroup, group_from_gid(p->sgid), sizeof p->sgroup);
-            strncpy(p->fgroup, group_from_gid(p->fgid), sizeof p->fgroup);
-/*        }*/
+    va_start(ap, flags);               /*  Init args list */
+    if (flags & PROC_PID)
+       PT->pids = va_arg(ap, pid_t*);
+    else if (flags & PROC_UID) {
+       PT->uids = va_arg(ap, uid_t*);
+       PT->nuid = va_arg(ap, int);
     }
+    va_end(ap);                                /*  Clean up args list */
 
-    if ((flags & PROC_FILLCOM) || (flags & PROC_FILLARG))      /* read+parse /proc/#/cmdline */
-       p->cmdline = file2strvec(path, "cmdline");
-    else
-        p->cmdline = NULL;
+    return PT;
+}
 
-    if (flags & PROC_FILLENV)                  /* read+parse /proc/#/environ */
-       p->environ = file2strvec(path, "environ");
-    else
-        p->environ = NULL;
-    
-    return p;
+// terminate a process table scan
+void closeproc(PROCTAB* PT) {
+    if (PT){
+        if (PT->procfs) closedir(PT->procfs);
+        free(PT);
+    }
+}
+
+// deallocate the space allocated by readproc if the passed rbuf was NULL
+void freeproc(proc_t* p) {
+    if (!p)    /* in case p is NULL */
+       return;
+    /* ptrs are after strings to avoid copying memory when building them. */
+    /* so free is called on the address of the address of strvec[0]. */
+    if (p->cmdline)
+       free((void*)*p->cmdline);
+    if (p->environ)
+       free((void*)*p->environ);
+    free(p);
 }
-#undef flags
 
 
+//////////////////////////////////////////////////////////////////////////////////
 void look_up_our_self(proc_t *p) {
     char sbuf[1024];
 
index 5529d467cf4306c1a4915d62f7ffa6361033b295..6fbcd851ef8d4043e4d98996a8a3383d09c90338 100644 (file)
@@ -150,17 +150,18 @@ typedef struct proc_t {
 #include <unistd.h>
 typedef struct PROCTAB {
     DIR*       procfs;
-    int                flags;
+    int(*finder)(struct PROCTAB *restrict const, proc_t *restrict const, char *restrict const);
+    proc_t*(*reader)(struct PROCTAB *restrict const, proc_t *restrict const, char *restrict const);
+    unsigned   flags;
     pid_t*     pids;   /* pids of the procs */
     uid_t*     uids;   /* uids of procs */
     int                nuid;   /* cannot really sentinel-terminate unsigned short[] */
-#ifdef FLASK_LINUX
-    security_id_t* sids; /* SIDs of the procs */
-#endif
+    int         i;  // generic
+    unsigned    u;  // generic
+    void *      vp; // generic
 } PROCTAB;
 
-/* initialize a PROCTAB structure holding needed call-to-call persistent data
- */
+// initialize a PROCTAB structure holding needed call-to-call persistent data
 extern PROCTAB* openproc(int flags, ... /* pid_t*|uid_t*|dev_t*|char* [, int n] */ );
 
 
@@ -171,14 +172,11 @@ extern PROCTAB* openproc(int flags, ... /* pid_t*|uid_t*|dev_t*|char* [, int n]
  */
 extern proc_t** readproctab(int flags, ... /* same as openproc */ );
 
-/* clean-up open files, etc from the openproc()
- */
+// clean-up open files, etc from the openproc()
 extern void closeproc(PROCTAB* PT);
 
-/* retrieve the next process matching the criteria set by the openproc()
- */
-extern proc_t* readproc(PROCTAB* PT, proc_t* return_buf);
-extern proc_t* ps_readproc(PROCTAB* PT, proc_t* return_buf);
+// retrieve the next process matching the criteria set by the openproc()
+extern proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict const return_buf);
 
 // warning: interface may change
 extern int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid);
index 48d4cff50978c18d8dcef32c0d65576bd0ecdff6..e9ba85beef701017ec5e2cb188088e568cfc4f6e 100644 (file)
@@ -71,6 +71,8 @@
 
 /******************* PS DEFINE *******************/
 
+#define needs_for_select (PROC_FILLSTAT | PROC_FILLSTATUS)
+
 /* personality control flags */
 #define PER_BROKEN_o      0x0001
 #define PER_BSD_h         0x0002
index d9a39a7fa7404185acdcd5bcfa346c8a4184a5d0..2d5222b514acddf06fd898bc5550f4931d9d6e83 100644 (file)
@@ -242,13 +242,13 @@ static void compute_needs(void){
 static void simple_spew(void){
   proc_t buf;
   PROCTAB* ptp;
-  ptp = openproc(needs_for_format | needs_for_sort);
+  ptp = openproc(needs_for_format | needs_for_sort | needs_for_select);
   if(!ptp) {
     fprintf(stderr, "Error: can not access /proc.\n");
     exit(1);
   }
   memset(&buf, '#', sizeof(proc_t));
-  while(ps_readproc(ptp,&buf)){
+  while(readproc(ptp,&buf)){
     if(want_this_proc(&buf)) show_one_proc(&buf);
     if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
     if(buf.environ) free((void*)*buf.environ); // ought to reuse
@@ -381,16 +381,16 @@ static void fancy_spew(void){
   proc_t *retbuf = NULL;
   PROCTAB *restrict ptp;
   int n = 0;  /* number of processes & index into array */
-  ptp = openproc(needs_for_format | needs_for_sort);
+  ptp = openproc(needs_for_format | needs_for_sort | needs_for_select);
   if(!ptp) {
     fprintf(stderr, "Error: can not access /proc.\n");
     exit(1);
   }
-  while((retbuf = ps_readproc(ptp,retbuf))){
+  while((retbuf = readproc(ptp,retbuf))){
     if(want_this_proc(retbuf)){
       fill_pcpu(retbuf); // in case we might sort by %cpu
       processes[n++] = retbuf;
-      retbuf = NULL;  /* NULL asks ps_readproc to allocate */
+      retbuf = NULL;     // NULL asks readproc to allocate
     }
   }
   if(retbuf) free(retbuf);