]> granicus.if.org Git - procps-ng/commitdiff
top: adapt for running with proc mounted as subset=pid
authorJim Warner <james.warner@comcast.net>
Thu, 16 Dec 2021 06:00:00 +0000 (00:00 -0600)
committerCraig Small <csmall@dropbear.xyz>
Thu, 16 Dec 2021 20:21:51 +0000 (07:21 +1100)
As the issue cited below illustrates, a pids namespace
with proc mounted as subset=pid denies our library any
access to non-task data. In top's case, the result was
a fatal error message which involved "cpu statistics".

With this patch top will now assume an error involving
global cpu (stat) or memory (meminfo) data means we're
running under a restricted pids namespace. As such, an
attempt will be made to still display task level data.

[ if our assumption is incorrect, it's of no matter. ]
[ instead of a fatal error, we'll still try to offer ]
[ a user some minimally useful bit of functionality. ]

Reference(s):
https://gitlab.com/procps-ng/procps/-/issues/227
https://www.freelists.org/post/procps/three-for-newlib,1
. 1st cut at subset=pid
commit bcb837b8c73f23536a2403b61deeb2b7b3c6be20

Signed-off-by: Jim Warner <james.warner@comcast.net>
top/top.c
top/top_nls.c
top/top_nls.h

index a77aa7dc620a335667bf42b99bb5382ba4eed956..0b3a1d368bdfa78e6020cfe33cbd9086dbb8e4da 100644 (file)
--- a/top/top.c
+++ b/top/top.c
@@ -289,6 +289,10 @@ static sem_t Semaphore_tasks_beg, Semaphore_tasks_end;
 #if defined THREADED_CPU || defined THREADED_MEM || defined THREADED_TSK
 static pthread_t Thread_id_main;
 #endif
+
+        /* Support for a namespace with proc mounted subset=pid,
+           ( we'll limit our display to task information only ). */
+static int Restrict_some = 0;
 \f
 /*######  Tiny useful routine(s)  ########################################*/
 
@@ -3368,20 +3372,22 @@ static void before (char *me) {
 
    // get the total cpus (and, if possible, numa node total)
    if ((rc = procps_stat_new(&Stat_ctx)))
-      error_exit(fmtmk(N_fmt(LIB_errorcpu_fmt),__LINE__, strerror(-rc)));
-   if (!(Stat_reap = procps_stat_reap(Stat_ctx, which, Stat_items, MAXTBL(Stat_items))))
-      error_exit(fmtmk(N_fmt(LIB_errorcpu_fmt),__LINE__, strerror(errno)));
+      Restrict_some = Cpu_cnt = 1;
+   else {
+      if (!(Stat_reap = procps_stat_reap(Stat_ctx, which, Stat_items, MAXTBL(Stat_items))))
+         error_exit(fmtmk(N_fmt(LIB_errorcpu_fmt),__LINE__, strerror(errno)));
 #ifndef PRETEND0NUMA
-   Numa_node_tot = Stat_reap->numa->total;
+      Numa_node_tot = Stat_reap->numa->total;
 #endif
-   Cpu_cnt = Stat_reap->cpus->total;
+      Cpu_cnt = Stat_reap->cpus->total;
 #ifdef PRETEND48CPU
-   Cpu_cnt = 48;
+      Cpu_cnt = 48;
 #endif
+   }
 
    // prepare for memory stats from new library API ...
    if ((rc = procps_meminfo_new(&Mem_ctx)))
-      error_exit(fmtmk(N_fmt(LIB_errormem_fmt),__LINE__, strerror(-rc)));
+      Restrict_some = 1;
 
    // establish max depth for newlib pids stack (# of result structs)
    Pids_itms = alloc_c(sizeof(enum pids_item) * MAXTBL(Fieldstab));
@@ -5047,6 +5053,10 @@ static void keys_global (int ch) {
 static void keys_summary (int ch) {
    WIN_t *w = Curwin;             // avoid gcc bloat with a local copy
 
+   if (Restrict_some && ch != 'C') {
+      show_msg(N_txt(X_RESTRICTED_txt));
+      return;
+   }
    switch (ch) {
       case '!':
          if (CHKw(w, View_CPUSUM) || CHKw(w, View_CPUNOD))
@@ -5734,6 +5744,22 @@ static void summary_show (void) {
    char tmp[MEDBUFSIZ];
    int i;
 
+   if (Restrict_some) {
+#ifdef THREADED_TSK
+      sem_wait(&Semaphore_tasks_end);
+#endif
+      // Display Task States only
+      if (isROOM(View_STATES, 1)) {
+         show_special(0, fmtmk(N_unq(STATE_line_1_fmt)
+            , Thread_mode ? N_txt(WORD_threads_txt) : N_txt(WORD_process_txt)
+            , PIDSmaxt, Pids_reap->counts->running
+            , Pids_reap->counts->sleeping + Pids_reap->counts->other
+            , Pids_reap->counts->stopped, Pids_reap->counts->zombied));
+         Msg_row += 1;
+      }
+      goto restrict_end;
+   }
+
    // Display Uptime and Loadavg
    if (isROOM(View_LOADAV, 1)) {
       if (!Rc.mode_altscr)
@@ -5951,6 +5977,7 @@ numa_oops:
     #undef memPARM
    } // end: View_MEMORY
 
+restrict_end:
  #undef isROOM
  #undef anyFLG
 } // end: summary_show
@@ -6061,6 +6088,10 @@ static const char *task_show (const WIN_t *q, int idx) {
             break;
    /* s_int, scale_pcnt with special handling */
          case EU_CPU:        // PIDS_TICS_ALL_DELTA
+            if (Restrict_some) {
+               cp = justify_pad("?", W, Jn);
+               break;
+            }
          {  float u = (float)rSv(EU_CPU, u_int);
             int n = rSv(EU_THD, s_int);
 #ifndef TREE_VCPUOFF
@@ -6130,6 +6161,10 @@ static const char *task_show (const WIN_t *q, int idx) {
             break;
    /* ul_int, scale_pcnt */
          case EU_MEM:        // derive from PIDS_MEM_RES
+            if (Restrict_some) {
+               cp = justify_pad("?", W, Jn);
+               break;
+            }
             cp = scale_pcnt((float)rSv(EU_MEM, ul_int) * 100 / MEM_VAL(mem_TOT), W, Jn);
             break;
    /* ul_int, make_str with special handling */
@@ -6399,16 +6434,19 @@ static void frame_make (void) {
 #else
    tasks_refresh(NULL);
 #endif
+
+   if (!Restrict_some) {
 #ifdef THREADED_CPU
-   sem_post(&Semaphore_cpus_beg);
+      sem_post(&Semaphore_cpus_beg);
 #else
-   cpus_refresh(NULL);
+      cpus_refresh(NULL);
 #endif
 #ifdef THREADED_MEM
-   sem_post(&Semaphore_memory_beg);
+      sem_post(&Semaphore_memory_beg);
 #else
-   memory_refresh(NULL);
+      memory_refresh(NULL);
 #endif
+   }
 
    // whoa either first time or thread/task mode change, (re)prime the pump...
    if (Pseudo_row == PROC_XTRA) {
index c2db9b9342dafecda9503a5dfeb9fd8fa237cfd4..4a91a1dac197ee7da7f609ad6d7a2d3472ce5b3d 100644 (file)
@@ -571,6 +571,7 @@ static void build_norm_nlstab (void) {
    Norm_nlstab[XTRA_warnold_txt] = _("saving prevents older top from reading, save anyway?");
    Norm_nlstab[X_SEMAPHORES_fmt] = _("failed sem_init() at %d: %s");
    Norm_nlstab[X_THREADINGS_fmt] = _("failed pthread_create() at %d: %s");
+   Norm_nlstab[X_RESTRICTED_txt] = _("sorry, restricted namespace with reduced functionality");
 }
 
 
index 4995f17771abac170515684ae28697bd81dad51b..e70a0ef49dcbae948b77c4f60ad8a257c1a790ce 100644 (file)
@@ -84,7 +84,7 @@ enum norm_nls {
    WORD_process_txt, WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt,
    XTRA_badflds_fmt, XTRA_fixwide_fmt, XTRA_modebad_txt, XTRA_size2up_txt,
    XTRA_vforest_fmt, XTRA_warncfg_txt, XTRA_warnold_txt, XTRA_winsize_txt,
-   X_SEMAPHORES_fmt, X_THREADINGS_fmt,
+   X_RESTRICTED_txt, X_SEMAPHORES_fmt, X_THREADINGS_fmt,
 #ifndef INSP_OFFDEMO
    YINSP_demo01_txt, YINSP_demo02_txt, YINSP_demo03_txt, YINSP_deqfmt_txt,
    YINSP_deqtyp_txt, YINSP_dstory_txt,