]> granicus.if.org Git - procps-ng/log
procps-ng
6 years agopmap: Prevent buffer overflow in sscanf().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pmap: Prevent buffer overflow in sscanf().

vmflags[] is a 27*(2+1)=81 char array, but there are 30 flags now (not
27), and even with 27 flags this was an off-by-one overflow (the kernel
always outputs a flag with "%c%c ", so the last +1 is for a space, not
for the terminating null byte). Protect vmflags[] with a maximum field
width, as in the surrounding sscanf() calls.

6 years agopmap: Always check the return value of fgets().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pmap: Always check the return value of fgets().

Otherwise "the contents of the array remain unchanged and a null pointer
is returned" or "the array contents are indeterminate and a null pointer
is returned".

6 years agopmap: Fix parsing error in config_read().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pmap: Fix parsing error in config_read().

$ echo '[' > crash
$ pmap -C crash $$
Segmentation fault (core dumped)

6 years agopmap: Prevent integer overflow in main().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pmap: Prevent integer overflow in main().

Unlikely to ever happen, but just in case.

6 years agopmap: Plug memory leak in range_arguments().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pmap: Plug memory leak in range_arguments().

Also, simplify the code slightly (but functionally equivalent). Check
the return value of xstrdup() only once (yes, it can return NULL).

6 years agoproc/readproc.c: Work around a design flaw in readeither().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Work around a design flaw in readeither().

readeither() caches (in new_p) a pointer to the proc_t of a task-group
leader, but readeither()'s callers can do pretty much anything with the
proc_t structure passed to and/or returned by this function. For
example, they can 1/ free it or 2/ recycle it (by passing it to
readeither() as x).

1/ leads to a use-after-free, and 2/ leads to unexpected behavior when
taskreader()/simple_readtask() is called with new_p equal to x (this is
not a theoretical flaw: 2/ happens in readproctab3() when want_task()
returns false and p is a group leader).

As a workaround, we keep a copy of new_p's first member (tid) in static
storage, and the next times we enter readeither() we check this "canary"
against the tid in new_p: if they differ, we reset new_p to NULL, which
forces the allocation of a new proc_t (the new "leader", or reference).

This always detects 2/ (because free_acquired(x,1) memsets x and hence
new_p); always detects 1/ if freed via free_acquired() and/or freeproc()
(very likely, otherwise memory may be leaked); probably detects 1/ even
if freed directly via free() (because the canary is the first member of
proc_t, likely to be overwritten by free()); but can not detect 1/ if
free() does not write to new_p's chunk at all.

Moreover, accessing new_p->tid to check the canary in case 1/ is itself
a use-after-free, so a better long-term solution should be implemented
at some point (we wanted to avoid intrusive and backward-incompatible
changes in this library function, hence this imperfect workaround).

6 years agoproc/readproc.c: Prevent integer overflows in readproctab*().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Prevent integer overflows in readproctab*().

If an integer overflow is about to be reached, call xalloc_err_handler()
(since it would have been caught by calloc() or reallocarray()) and then
exit(): these integer overflows are far from reachable, with the current
PID_MAX_LIMIT (2^22), so if they are there is something very wrong going
on. Note: we check the n_*alloc variables against INT_MAX even when they
are size_t because they are later stored as int in a struct proc_data_t.

6 years agoproc/readproc.c: Fix double-free()s in readtask().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Fix double-free()s in readtask().

If QUICK_THREADS is not defined (it is not by default, but most
distributions enable it) and task_dir_missing is true (only on very old
kernels), then readtask() forgets to reset some of the struct proc_t t's
members, which later results in double-free()s in free_acquired().

For now, we simply synchronized the list of members to be reset with the
list of members freed in free_acquired().

6 years agoproc/readproc.c: Fix use-after-free in readproctab2().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Fix use-after-free in readproctab2().

The memset() in the PROC_LOOSE_TASKS loop leaves a struct proc_t
uninitialized (the one at data+n_used), which leads to a use-after-free.

ps calls readproctab2(), but only if !TF_loose_tasks, and this U-A-F is
triggered only if PROC_LOOSE_TASKS, so there seems to be no vulnerable
call in the procps package itself (other users of the libprocps may be
vulnerable, though).

6 years agoproc/readproc.c: Harden openproc().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Harden openproc().

Replace xmalloc() with xcalloc().

6 years agoproc/readproc.c: Harden get_proc_stats().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Harden get_proc_stats().

Replace sprintf() with snprintf().

6 years agoproc/readproc.c: Harden simple_nextpid().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Harden simple_nextpid().

Replace memcpy+strcpy with snprintf.

6 years agoproc/readproc.c: Harden fill_cgroup_cvt().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Harden fill_cgroup_cvt().

Check the return value of snprintf(), otherwise dst may point
out-of-bounds when it reaches the end of the dst_buffer (the snprintf()
always returns 1 in that case, even if there is not enough space left),
and vMAX becomes negative and is passed to snprintf() as a size_t.

6 years agoproc/readproc.c: Harden vectorize_this_str().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Harden vectorize_this_str().

This detects an integer overflow of "strlen + 1", prevents an integer
overflow of "tot + adj + (2 * pSZ)", and avoids calling snprintf with a
string longer than INT_MAX. Truncate rather than fail, since the callers
do not expect a failure of this function.

6 years agoproc/readproc.c: Harden read_unvectored().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Harden read_unvectored().

1/ Prevent an out-of-bounds write if sz is 0.

2/ Limit sz to INT_MAX, because the return value is an int, not an
unsigned int (and because if INT_MAX is equal to SSIZE_MAX, man 2 read
says "If count is greater than SSIZE_MAX, the result is unspecified.")

3/ Always null-terminate dst (unless sz is 0), because a return value of
0 because of an open() error (for example) is indistinguishable from a
return value of 0 because of an empty file.

4/ Use an unsigned int for i (just like n), not an int.

5/ Check for snprintf() truncation.

6 years agoproc/readproc.c: Fix bugs and overflows in file2strvec().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Fix bugs and overflows in file2strvec().

Note: this is by far the most important and complex patch of the whole
series, please review it carefully; thank you very much!

For this patch, we decided to keep the original function's design and
skeleton, to avoid regressions and behavior changes, while fixing the
various bugs and overflows. And like the "Harden file2str()" patch, this
patch does not fail when about to overflow, but truncates instead: there
is information available about this process, so return it to the caller;
also, we used INT_MAX as a limit, but a lower limit could be used.

The easy changes:

- Replace sprintf() with snprintf() (and check for truncation).

- Replace "if (n == 0 && rbuf == 0)" with "if (n <= 0 && tot <= 0)" and
  do break instead of return: it simplifies the code (only one place to
  handle errors), and also guarantees that in the while loop either n or
  tot is > 0 (or both), even if n is reset to 0 when about to overflow.

- Remove the "if (n < 0)" block in the while loop: it is (and was) dead
  code, since we enter the while loop only if n >= 0.

- Rewrite the missing-null-terminator detection: in the original
  function, if the size of the file is a multiple of 2047, a null-
  terminator is appended even if the file is already null-terminated.

- Replace "if (n <= 0 && !end_of_file)" with "if (n < 0 || tot <= 0)":
  originally, it was equivalent to "if (n < 0)", but we added "tot <= 0"
  to handle the first break of the while loop, and to guarantee that in
  the rest of the function tot is > 0.

- Double-force ("belt and suspenders") the null-termination of rbuf:
  this is (and was) essential to the correctness of the function.

- Replace the final "while" loop with a "for" loop that behaves just
  like the preceding "for" loop: in the original function, this would
  lead to unexpected results (for example, if rbuf is |\0|A|\0|, this
  would return the array {"",NULL} but should return {"","A",NULL}; and
  if rbuf is |A|\0|B| (should never happen because rbuf should be null-
  terminated), this would make room for two pointers in ret, but would
  write three pointers to ret).

The hard changes:

- Prevent the integer overflow of tot in the while loop, but unlike
  file2str(), file2strvec() cannot let tot grow until it almost reaches
  INT_MAX, because it needs more space for the pointers: this is why we
  introduced ARG_LEN, which also guarantees that we can add "align" and
  a few sizeof(char*)s to tot without overflowing.

- Prevent the integer overflow of "tot + c + align": when INT_MAX is
  (almost) reached, we write the maximal safe amount of pointers to ret
  (ARG_LEN guarantees that there is always space for *ret = rbuf and the
  NULL terminator).

6 years agoproc/readproc.c: Harden file2str().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Harden file2str().

1/ Replace sprintf() with snprintf() (and check for truncation).

2/ Prevent an integer overflow of ub->siz. The "tot_read--" is needed to
avoid an off-by-one overflow in "ub->buf[tot_read] = '\0'". It is safe
to decrement tot_read here, because we know that tot_read is equal to
ub->siz (and ub->siz is very large).

We believe that truncation is a better option than failure (implementing
failure instead should be as easy as replacing the "tot_read--" with
"tot_read = 0").

6 years agoproc/readproc.c: Harden stat2proc().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Harden stat2proc().

1/ Use a "size_t num" instead of an "unsigned num" (also, do not store
the return value of sscanf() into num, it was unused anyway).

2/ Check the return value of strchr() and strrchr().

3/ Never jump over the terminating null byte with "S = tmp + 2".

6 years agoproc/readproc.c: Harden supgrps_from_supgids().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Harden supgrps_from_supgids().

1/ Prevent an integer overflow of t.

2/ Avoid an infinite loop if s contains characters other than comma,
spaces, +, -, and digits.

3/ Handle all possible return values of snprintf().

6 years agoproc/readproc.c: Harden status2proc().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Harden status2proc().

1/ Do not read past the terminating null byte when hashing the name.

2/ S[x] is used as an index, but S is "char *S" (signed) and hence may
index the array out-of-bounds. Bit-mask S[x] with 127 (the array has 128
entries).

3/ Use a size_t for j, not an int (strlen() returns a size_t).

Notes:

- These are (mostly) theoretical problems, because the contents of
  /proc/PID/status are (mostly) trusted.

- The "name" member of the status_table_struct has 8 bytes, and
  "RssShmem" occupies exactly 8 bytes, which means that "name" is not
  null-terminated. This is fine right now, because status2proc() uses
  memcmp(), not strcmp(), but it is worth mentioning.

6 years agoproc/readproc.c: Fix the unhex() function.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Fix the unhex() function.

This function is unused (SIGNAL_STRING is defined by default, and if it
is not, procps does not compile -- for example, there is no "outbuf" in
help_pr_sig()) but fix it anyway. There are two bugs:

- it accepts non-hexadecimal characters (anything >= 0x30);

- "(c - (c>0x57) ? 0x57 : 0x30)" is always equal to 0x57.

6 years agoproc/sysinfo.c: Ensure null-termination in getstat().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/sysinfo.c: Ensure null-termination in getstat().

There was a "buff[BUFFSIZE-1] = 0;" but there may be garbage between
what is read() (less than BUFFSIZE-1 bytes) and this null byte. Reuse
the construct from the preceding getrunners().

6 years agops/sortformat.c: Avoid "sep_loc + 1" when sep_loc is NULL.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/sortformat.c: Avoid "sep_loc + 1" when sep_loc is NULL.

6 years agops/sortformat.c: Handle large width in aix_format_parse().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/sortformat.c: Handle large width in aix_format_parse().

Unlikely to ever happen, since it would imply a very large string, but
better safe than sorry.

6 years agops/sortformat.c: Catch negative width in format_parse().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/sortformat.c: Catch negative width in format_parse().

The existing strspn() check guarantees that the string contains no '-'
but atoi() does not catch errors, especially not integer overflows.

6 years agops/sortformat.c: Double-check chars in verify_short_sort().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/sortformat.c: Double-check chars in verify_short_sort().

To avoid an out-of-bounds access at checkoff[tmp]. The strspn() at the
beginning of the function protects against it already, but double-check
this in case of some future change.

6 years agops/display.c: Fix "move process-only flags to the process".
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/display.c: Fix "move process-only flags to the process".

Use "proc |= (task & PROC_ONLY)" not "proc |= (task &~ PROC_ONLY)".

6 years agops/display.c: Always exit from signal_handler().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/display.c: Always exit from signal_handler().

Right now, "we _exit() anyway" is not always true: for example, the
default action for SIGURG is to ignore the signal, which means that
"kill(getpid(), signo);" does not terminate the process. Call _exit()
explicitly, in this case (rather than exit(), because the terminating
kill() calls do not call the functions registered with atexit() either).

6 years agops/output.c: Always null-terminate outbuf in show_one_proc().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/output.c: Always null-terminate outbuf in show_one_proc().

Before "strlen(outbuf)", if one of the pr_*() functions forgot to do it.
This prevents an out-of-bounds read in strlen(), and an out-of-bounds
write in "outbuf[sz] = '\n'". Another solution would be to replace
strlen() with strnlen(), but this is not used anywhere else in the
code-base and may not exist in all libc's.

6 years agops/output.c: Protect outbuf in various pr_*() functions.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/output.c: Protect outbuf in various pr_*() functions.

pr_bsdstart(): Replace "strcpy(outbuf," with "snprintf(outbuf, COLWID,"
(which is used in all surrounding functions). (side note: the fact that
many pr_*() functions simply return "snprintf(outbuf, COLWID," justifies
the "amount" checks added to show_one_proc() by the "ps/output.c:
Replace strcpy() with snprintf() in show_one_proc()." patch)

pr_stime(): Check the return value of strftime() (in case of an error,
"the contents of the array are undefined").

help_pr_sig(): Handle the "len < 8" case, otherwise "sig+len-8" may
point outside the sig string.

pr_context(): Handle the empty string case, or else "outbuf[len-1]"
points outside outbuf.

6 years agops/output.c: Enforce a safe range for max_rightward.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/output.c: Enforce a safe range for max_rightward.

Enforce a maximum max_rightward of OUTBUF_SIZE-1, because it is used in
constructs such as "snprintf(outbuf, max_rightward+1," (we could remove
the extra check at the beginning of forest_helper() now, but we decided
to leave it, as a precaution and reminder).

The minimum max_rightward check is not strictly needed, because it is
unsigned. However, we decided to add it anyway:

- most of the other variables are signed;

- make it visually clear that this case is properly handled;

- ideally, the minimum max_rightward should be 1, not 0 (to prevent
  integer overflows such as "max_rightward-1"), but this might change
  the behavior/output of ps, so we decided against it, for now.

Instead, we fixed the only function that overflows if max_rightward is
0. Also, enforce the same safe range for max_leftward, although it is
never used throughout the code-base.

6 years agops/output.c: Replace strcpy() with snprintf() in show_one_proc().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/output.c: Replace strcpy() with snprintf() in show_one_proc().

This strcpy() should normally not overflow outbuf, but names can be
overridden (via -o). Also, check "amount" in all cases.

6 years agops/output.c: Remove the page_shift variable.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/output.c: Remove the page_shift variable.

It is static and not used anywhere.

6 years agops/output.c: Check return value of mmap() in init_output().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/output.c: Check return value of mmap() in init_output().

We decided not to check the return value of the mprotect() calls,
because they are not vital to the operation of ps.

6 years agops/display.c: Harden show_tree().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
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.

6 years agops/output.c: Fix outbuf overflows in pr_args() etc.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/output.c: Fix outbuf overflows in pr_args() etc.

Because there is usually less than OUTBUF_SIZE available at endp.

6 years agops/output.c: Harden forest_helper().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
ps/output.c: Harden forest_helper().

This patch solves several problems:

1/ Limit the number of characters written (to outbuf) to OUTBUF_SIZE-1
(-1 for the null-terminator).

2/ Always null-terminate outbuf at q.

3/ Move the "rightward" checks *before* the strcpy() calls.

4/ Avoid an integer overflow in these checks (e.g., rightward-4).

6 years agoproc/escape.c: Handle negative snprintf() return value.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/escape.c: Handle negative snprintf() return value.

May happen if strlen(src) > INT_MAX for example. This patch prevents
escaped_copy() from increasing maxroom and returning -1 (= number of
bytes consumed in dst).

6 years agoproc/escape.c: Prevent buffer overflows in escape_command().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/escape.c: Prevent buffer overflows in escape_command().

This solves several problems:

1/ outbuf[1] was written to, but not outbuf[0], which was left
uninitialized (well, SECURE_ESCAPE_ARGS() already fixes this, but do it
explicitly as well); we know it is safe to write one byte to outbuf,
because SECURE_ESCAPE_ARGS() guarantees it.

2/ If bytes was 1, the write to outbuf[1] was an off-by-one overflow.

3/ Do not call escape_str() with a 0 bufsize if bytes == overhead.

4/ Prevent various buffer overflows if bytes <= overhead.

6 years agoproc/escape.c: Prevent integer overflows in escape_str_utf8().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/escape.c: Prevent integer overflows in escape_str_utf8().

Simply rearrange the old comparisons. The new comparisons are safe,
because we know from previous checks that:

1/ wlen > 0

2/ my_cells < *maxcells (also: my_cells >= 0 and *maxcells > 0)

3/ len > 1

4/ my_bytes+1 < bufsize (also: my_bytes >= 0 and bufsize > 0)

6 years agoproc/escape.c: Handle negative wcwidth() return value.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/escape.c: Handle negative wcwidth() return value.

This should never happen, because wcwidth() is called only if iswprint()
returns nonzero. But belt-and-suspenders, and make it visually clear
(very important for the next patch).

6 years agoproc/escape.c: Make sure all escape*() arguments are safe.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/escape.c: Make sure all escape*() arguments are safe.

The SECURE_ESCAPE_ARGS() macro solves several potential problems
(although we found no problematic calls to the escape*() functions in
procps's code-base, but had to thoroughly review every call; and this is
library code):

1/ off-by-one overflows if the size of the destination buffer is 0;

2/ buffer overflows if this size (or "maxroom") is negative;

3/ integer overflows (for example, "*maxcells+1");

4/ always null-terminate the destination buffer (unless its size is 0).

6 years agoproc/whattime.c: Always initialize buf.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/whattime.c: Always initialize buf.

In the human_readable case; otherwise the strcat() that follows may
append bytes to the previous contents of buf.

Also, slightly enlarge buf, as it was a bit too tight.

Could also replace all sprintf()s with snprintf()s, but all the calls
here output a limited number of characters, so they should be safe.

6 years agoproc/slab.c: Initialize struct slab_info in get_slabnode().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/slab.c: Initialize struct slab_info in get_slabnode().

Especially its "next" member: this is what caused the crash in "slabtop:
Reset slab_list if get_slabinfo() fails." (if parse_slabinfo*() fails in
sscanf(), for example, then curr is set to NULL but it is already linked
into the "list" and its "next" member was never initialized).

6 years agoproc/sysinfo.c: Fix off-by-one in get_pid_digits().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/sysinfo.c: Fix off-by-one in get_pid_digits().

At "pidbuf[rc] = '\0';" if "rc = read()" returns "sizeof pidbuf"
(unlikely to ever happen, but still).

6 years agoproc/sysinfo.c: Prevent integer overflow of realloc() size.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/sysinfo.c: Prevent integer overflow of realloc() size.

6 years agoproc/slab.c: Check correct number of items after sscanf().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/slab.c: Check correct number of items after sscanf().

6 years agoproc/slab.h: Fix off-by-one overflow in sscanf().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/slab.h: Fix off-by-one overflow in sscanf().

In proc/slab.c, functions parse_slabinfo20() and parse_slabinfo11(),
sscanf() might overflow curr->name, because "String input conversions
store a terminating null byte ('\0') to mark the end of the input; the
maximum field width does not include this terminator."

Add one byte to name[] for this terminator.

6 years agoproc/sig.c: Harden print_given_signals().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/sig.c: Harden print_given_signals().

And signal_name_to_number().

6 years agoproc/devname.c: Never write more than "chop" (part 2).
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/devname.c: Never write more than "chop" (part 2).

"chop" is the maximum offset where the null-byte should be written;
respect this even if about to write just one (non-null) character.

6 years agoproc/devname.c: Never write more than "chop" characters.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/devname.c: Never write more than "chop" characters.

This should be guaranteed by "tmp[chop] = '\0';" and "if(!c) break;" but
this patch adds a very easy belt-and-suspenders check.

6 years agoproc/devname.c: Prevent off-by-one overflow in dev_to_tty().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/devname.c: Prevent off-by-one overflow in dev_to_tty().

6 years agoproc/devname.c: Use snprintf() in link_name().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/devname.c: Use snprintf() in link_name().

Found no problematic use case at the moment, but better safe than sorry.
Also, return an error on snprintf() or readlink() truncation.

6 years agoproc/version.h: Protect parameter in LINUX_VERSION() macro.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/version.h: Protect parameter in LINUX_VERSION() macro.

Just in case (no problematic use case at the moment).

6 years agoproc/alloc.*: Use size_t, not unsigned int.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/alloc.*: Use size_t, not unsigned int.

Otherwise this can truncate sizes on 64-bit platforms, and is one of the
reasons the integer overflows in file2strvec() are exploitable at all.
Also: catch potential integer overflow in xstrdup() (should never
happen, but better safe than sorry), and use memcpy() instead of
strcpy() (faster).

Warnings:

- in glibc, realloc(ptr, 0) is equivalent to free(ptr), but not here,
  because of the ++size;

- here, xstrdup() can return NULL (if str is NULL), which goes against
  the idea of the xalloc wrappers.

We were tempted to call exit() or xerrx() in those cases, but decided
against it, because it might break things in unexpected places; TODO?

6 years agoproc/alloc.c: Use vfprintf(), not fprintf().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/alloc.c: Use vfprintf(), not fprintf().

This can disclose information from the stack, but is unlikely to have a
security impact in the context of the procps utilities:

user@debian:~$ w 2>&1 | xxd
00000000: a03c 79b7 1420 6661 696c 6564 2074 6f20  .<y.. failed to
00000010: 616c 6c6f 6361 7465 2033 3232 3137 3439  allocate 3221749
00000020: 3738 3020 6279 7465 7320 6f66 206d 656d  780 bytes of mem
00000030: 6f72 79                                  ory

6 years agoproc/readproc.c: Add checks to get_ns_name() and get_ns_id().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/readproc.c: Add checks to get_ns_name() and get_ns_id().

6 years agoproc/sig.c: Fix the strtosig() function.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
proc/sig.c: Fix the strtosig() function.

Do not memleak "copy" in case of an error.

Do not use "sizeof(converted)" in snprintf(), since "converted" is a
"char *" (luckily, 8 >= sizeof(char *)). Also, remove "sizeof(char)"
which is guaranteed to be 1 by the C standard, and replace 8 with 12,
which is enough to hold any stringified int and does not consume more
memory (in both cases, the glibc malloc()ates a minimum-sized chunk).

6 years agoskill: Do not scan past the null-terminator in check_proc().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
skill: Do not scan past the null-terminator in check_proc().

6 years agoskill: Check return value of str*chr() in check_proc().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
skill: Check return value of str*chr() in check_proc().

6 years agoskill: Properly null-terminate buf in check_proc().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
skill: Properly null-terminate buf in check_proc().

Right now, if read() returns less than 127 bytes (the most likely case),
the end of the "string" buf will contain garbage from the stack, because
buf is always null-terminated at a fixed offset 127. This is especially
bad because the next operation is a strrchr().

Also, make sure that the whole /proc/PID/stat file is read, otherwise
its parsing may be unsafe (the strrchr() may point into user-controlled
data, comm). This should never happen with the current file format (comm
is very short), but be safe, just in case.

6 years agoskill: Check the return value of fstat().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
skill: Check the return value of fstat().

6 years agoskill: Prevent multiple overflows in ENLIST().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
skill: Prevent multiple overflows in ENLIST().

First problem: saved_argc was used to calculate the size of the array,
but saved_argc was never initialized. This triggers an immediate heap-
based buffer overflow:

$ skill -c0 -c0 -c0 -c0
Segmentation fault (core dumped)

Second problem: saved_argc was not the upper bound anyway, because one
argument can ENLIST() several times (for example, in parse_namespaces())
and overflow the array as well.

Third problem: integer overflow of the size of the array.

6 years agoskill: Fix double-increment of pid_count.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
skill: Fix double-increment of pid_count.

No need to "pid_count++;" because "ENLIST(pid," does it already. Right
now this can trigger a heap-based buffer overflow.

Also, remove the unneeded "pid_count = 0;" (it is static, and
skillsnice_parse() is called only once; and the other *_count variables
are not initialized explicitly either).

6 years agoskill: Remove unused NEXTARG macro.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
skill: Remove unused NEXTARG macro.

6 years agoskill: Always NULL-terminate argv.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
skill: Always NULL-terminate argv.

The memmove() itself does not move the NULL-terminator, because nargs is
decremented first. Copy how skill_sig_option() does it: decrement nargs
last, and remove the "if (nargs - i)" (we are in "while (i < nargs)").

6 years agoskill: Fix getline() usage.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
skill: Fix getline() usage.

man getline: "If *lineptr is set to NULL and *n is set 0 before the
call, then getline() will allocate a buffer for storing the line. This
buffer should be freed by the user program even if getline() failed."

6 years agoskill: Simplify the kill_main() loop.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
skill: Simplify the kill_main() loop.

Right now the "loop=0; break;" is never reached.

6 years agopwdx: Fix a misleading comment.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pwdx: Fix a misleading comment.

It sounds like an off-by-one, but the code itself is correct.

6 years agopidof: Prevent integer overflows with grow_size().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pidof: Prevent integer overflows with grow_size().

Note: unlike "size" and "omit_size", "path_alloc_size" is not multiplied
by "sizeof(struct el)" but the checks in grow_size() allow for a roughly
100MB path_alloc_size, which should be more than enough for readlink().

6 years agopidof: Do not memleak pidof_root if multiple -c options.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pidof: Do not memleak pidof_root if multiple -c options.

6 years agopidof: Do not skip the NULL terminator in cmdline.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pidof: Do not skip the NULL terminator in cmdline.

This should never happen (cmdline[0] should always be non-NULL), but
just in case.

6 years agopidof: Get the arg1 base name with get_basename().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pidof: Get the arg1 base name with get_basename().

Same as program_base, cmd_arg0base, and exe_link_base.

6 years agopidof: Do not memleak the contents of proc_t.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pidof: Do not memleak the contents of proc_t.

Just like "pgrep: Do not memleak the contents of proc_t."

6 years agotload: Prevent integer overflows of ncols, nrows, and scr_size.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
tload: Prevent integer overflows of ncols, nrows, and scr_size.

Also, use xerrx() instead of xerr() since errno is not set.

6 years agotload: Prevent a buffer overflow when row equals nrows.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
tload: Prevent a buffer overflow when row equals nrows.

When max_scale is very small, scale_fact is very small, row is equal to
nrows, p points outside screen, and the write to *p is out-of-bounds.

6 years agotload: Use snprintf() instead of sprintf().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
tload: Use snprintf() instead of sprintf().

6 years agotload: Call longjmp() 1 instead of 0.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
tload: Call longjmp() 1 instead of 0.

Do it explicitly instead of the implicit "longjmp() cannot cause 0 to be
returned. If longjmp() is invoked with a second argument of 0, 1 will be
returned instead."

6 years agotload: Use standard names instead of numbers.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
tload: Use standard names instead of numbers.

6 years agoslabtop: Reset slab_list if get_slabinfo() fails.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
slabtop: Reset slab_list if get_slabinfo() fails.

Otherwise "the state of 'list' and 'stats' are undefined" (as per
get_slabinfo()'s documentation) and free_slabinfo() crashes (a
use-after-free).

6 years agouptime: Check the return value of various functions.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
uptime: Check the return value of various functions.

6 years agopgrep: Prevent a potential stack-based buffer overflow.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pgrep: Prevent a potential stack-based buffer overflow.

This is one of the worst issues that we found: if the strlen() of one of
the cmdline arguments is greater than INT_MAX (it is possible), then the
"int bytes" could wrap around completely, back to a very large positive
int, and the next strncat() would be called with a huge number of
destination bytes (a stack-based buffer overflow).

Fortunately, every distribution that we checked compiles its procps
utilities with FORTIFY, and the fortified strncat() detects and aborts
the buffer overflow before it occurs.

This patch also fixes a secondary issue: the old "--bytes;" meant that
cmdline[sizeof (cmdline) - 2] was never written to if the while loop was
never entered; in the example below, "ff" is the uninitialized byte:

((exec -ca `python3 -c 'print("A" * 131000)'` /usr/bin/cat < /dev/zero) | sleep 60) &
pgrep -a -P "$!" 2>/dev/null | hexdump -C
00000000  31 32 34 36 30 20 41 41  41 41 41 41 41 41 41 41  |12460 AAAAAAAAAA|
00000010  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  |AAAAAAAAAAAAAAAA|
*
00001000  41 41 41 41 ff 0a 31 32  34 36 32 20 73 6c 65 65  |AAAA..12462 slee|
00001010  70 20 36 30 0a                                    |p 60.|

6 years agopgrep: Always null-terminate the cmd*[] buffers.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pgrep: Always null-terminate the cmd*[] buffers.

Otherwise, man strncpy: "If there is no null byte among the first n
bytes of src, the string placed in dest will not be null-terminated."

6 years agopgrep: Initialize the cmd*[] stack buffers.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pgrep: Initialize the cmd*[] stack buffers.

Otherwise (for example), if the (undocumented) opt_echo is set, but not
opt_long, and not opt_longlong, and not opt_pattern, there is a call to
xstrdup(cmdoutput) but cmdoutput was never initialized:

sleep 60 & echo "$!" > pidfile
env -i LD_DEBUG=`perl -e 'print "A" x 131000'` pkill -e -c -F pidfile | xxd
...
000001c0: 4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
000001d0: 4141 4141 4141 4141 fcd4 e6bd e47f 206b  AAAAAAAA...... k
000001e0: 696c 6c65 6420 2870 6964 2031 3230 3931  illed (pid 12091
000001f0: 290a 310a                                ).1.
[1]+  Terminated              sleep 60

(the LD_DEBUG is just a trick to fill the initial stack with non-null
bytes, to show that there is uninitialized data from the stack in the
output; here, an address "fcd4 e6bd e47f")

6 years agopgrep: Simplify the match_*() functions.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pgrep: Simplify the match_*() functions.

6 years agopgrep: Replace buf+1 with buf in read_pidfile().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pgrep: Replace buf+1 with buf in read_pidfile().

Unless we missed something, this makes it unnecessarily difficult to
read/audit.

6 years agopgrep: Replace ints with longs in strict_atol().
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pgrep: Replace ints with longs in strict_atol().

atol() means long, and value points to a long.

6 years agopgrep: Prevent integer overflow of list size.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pgrep: Prevent integer overflow of list size.

Not exploitable (not under an attacker's control), but still a potential
non-security problem. Copied, fixed, and used the grow_size() macro from
pidof.c.

6 years agopgrep: Do not memleak the contents of proc_t.
Qualys Security Advisory [Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)]
pgrep: Do not memleak the contents of proc_t.

memset()ing task and subtask inside their loops prevents free_acquired()
(in readproc() and readtask()) from free()ing their contents (especially
cmdline and environ).

Our solution is not perfect, because we still memleak the very last
cmdline/environ, but select_procs() is called only once, so this is not
as bad as it sounds.

It would be better to leave subtask in its block and call
free_acquired() after the loop, but this function is static (not
exported).

The only other solution is to use freeproc(), but this means replacing
the stack task/subtask with xcalloc()s, thus changing a lot of code in
pgrep.c (to pointer accesses).

Hence this imperfect solution for now.

6 years agolibrary: check not undef SIGLOST
Craig Small [Thu, 3 May 2018 11:06:05 +0000 (21:06 +1000)]
library: check not undef SIGLOST

sig.c had this odd logic where on non-Hurd systems it would undefine
SIGLOST. Fine for Hurd or amd64 Linux systems. Bad for a sparc which
has SIGLOST defined *and* is not Hurd.

Just check its defined, its much simpler.

6 years agomisc: fix ps etime tests
Craig Small [Tue, 10 Apr 2018 12:09:40 +0000 (22:09 +1000)]
misc: fix ps etime tests

The test assumes only one process appears which, depending on the
speed of things, may not be true. It now matches one to many process
lines.

6 years agoupdate translations v3.3.14
Craig Small [Tue, 10 Apr 2018 11:37:39 +0000 (21:37 +1000)]
update translations

6 years agolibrary: build on non-glibc systems
Craig Small [Tue, 10 Apr 2018 11:28:11 +0000 (21:28 +1000)]
library: build on non-glibc systems

Some non-glibc systems didn't have libio.h or __BEGIN_DECLS
Changes to make it more standard.

References:
 issue #88

6 years agofree: fix scaling on 32-bit systems
Craig Small [Tue, 10 Apr 2018 11:20:25 +0000 (21:20 +1000)]
free: fix scaling on 32-bit systems

Systems that have a 32-bit long would give incorrect results in free.

References:
 Issue #89
 https://www.freelists.org/post/procps/frees-scale-size-broken-with-32bit-long

6 years agomisc: Update news about #91
Craig Small [Tue, 10 Apr 2018 11:16:10 +0000 (21:16 +1000)]
misc: Update news about #91

6 years agoRevert "Support running with child namespaces"
Craig Small [Tue, 10 Apr 2018 11:14:01 +0000 (21:14 +1000)]
Revert "Support running with child namespaces"

This reverts commit dcb6914f11406a13972636b08b7e26fdafe9efc9.

This commit broke a lot of scripts that were expecting to see all
programs. See #91

6 years agopgrep: Don't segfault with no match
Craig Small [Fri, 6 Apr 2018 13:00:29 +0000 (23:00 +1000)]
pgrep: Don't segfault with no match

If pgrep is run with a non-program name match and there are
no matches, it segfaults.

The testsuite thinks zero bytes sent, and zero bytes sent
because the program crashed is the same :/

References:
 commit 1aacf4af7f199d77fc9386e249eee654f59880db
 https://bugs.debian.org/894917

Signed-off-by: Craig Small <csmall@enc.com.au>
6 years agomisc: Update translations from Translation project v3.3.13
Craig Small [Sun, 1 Apr 2018 07:37:10 +0000 (17:37 +1000)]
misc: Update translations from Translation project

6 years ago3.3.13 release candidate 1 v3.3.13rc1
Craig Small [Mon, 12 Mar 2018 05:30:58 +0000 (16:30 +1100)]
3.3.13 release candidate 1

Update NEWS with the version
Add library API change into NEWS
Update c:r:a for library to 7:0:1

This means the current and age are incremented, so old programs can
use new library but not vice-versa as they won't have the numa*
functions.

6 years agomisc: Update translations
Craig Small [Mon, 12 Mar 2018 03:24:49 +0000 (14:24 +1100)]
misc: Update translations

po4a is awful, basically.