ps/display.c: Harden show_tree().

1/ Do not go deeper than the size of forest_prefix[], to prevent a
buffer overflow (sizeof(forest_prefix) is roughly 128K, but the maximum
/proc/sys/kernel/pid_max is 4M). (actually, we go deeper, but we stop
adding bytes to forest_prefix[])

2/ Always null-terminate forest_prefix[] at the current level.
This commit is contained in:
Qualys Security Advisory 1970-01-01 00:00:00 +00:00 committed by Craig Small
parent 136e372495
commit bb9c217f29

View File

@ -468,14 +468,22 @@ static void show_proc_array(PROCTAB *restrict ptp, int n){
/***** show tree */ /***** show tree */
/* this needs some optimization work */ /* this needs some optimization work */
#define ADOPTED(x) 1 #define ADOPTED(x) 1
#define IS_LEVEL_SAFE(level) \
((level) >= 0 && (size_t)(level) < sizeof(forest_prefix))
static void show_tree(const int self, const int n, const int level, const int have_sibling){ static void show_tree(const int self, const int n, const int level, const int have_sibling){
int i = 0; int i = 0;
if(!IS_LEVEL_SAFE(level))
catastrophic_failure(__FILE__, __LINE__, _("please report this bug"));
if(level){ if(level){
/* add prefix of "+" or "L" */ /* add prefix of "+" or "L" */
if(have_sibling) forest_prefix[level-1] = '+'; if(have_sibling) forest_prefix[level-1] = '+';
else forest_prefix[level-1] = 'L'; else forest_prefix[level-1] = 'L';
forest_prefix[level] = '\0';
} }
forest_prefix[level] = '\0';
show_one_proc(processes[self],format_list); /* first show self */ show_one_proc(processes[self],format_list); /* first show self */
for(;;){ /* look for children */ for(;;){ /* look for children */
if(i >= n) return; /* no children */ if(i >= n) return; /* no children */
@ -486,8 +494,8 @@ static void show_tree(const int self, const int n, const int level, const int ha
/* change our prefix to "|" or " " for the children */ /* change our prefix to "|" or " " for the children */
if(have_sibling) forest_prefix[level-1] = '|'; if(have_sibling) forest_prefix[level-1] = '|';
else forest_prefix[level-1] = ' '; else forest_prefix[level-1] = ' ';
forest_prefix[level] = '\0';
} }
forest_prefix[level] = '\0';
for(;;){ for(;;){
int self_pid; int self_pid;
int more_children = 1; int more_children = 1;
@ -498,16 +506,18 @@ static void show_tree(const int self, const int n, const int level, const int ha
else else
if(processes[i+1]->ppid != self_pid) more_children = 0; if(processes[i+1]->ppid != self_pid) more_children = 0;
if(self_pid==1 && ADOPTED(processes[i]) && forest_type!='u') if(self_pid==1 && ADOPTED(processes[i]) && forest_type!='u')
show_tree(i++, n, level, more_children); show_tree(i++, n, level, more_children);
else else
show_tree(i++, n, level+1, more_children); show_tree(i++, n, IS_LEVEL_SAFE(level+1) ? level+1 : level, more_children);
if(!more_children) break; if(!more_children) break;
} }
/* chop prefix that children added -- do we need this? */ /* chop prefix that children added */
forest_prefix[level] = '\0'; forest_prefix[level] = '\0';
// memset(processes[self], '$', sizeof(proc_t)); /* debug */ // memset(processes[self], '$', sizeof(proc_t)); /* debug */
} }
#undef IS_LEVEL_SAFE
/***** show forest */ /***** show forest */
static void show_forest(const int n){ static void show_forest(const int n){
int i = n; int i = n;