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.
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).
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.
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.
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.
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.
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).
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.
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).
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).
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).
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."
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?
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).
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.
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:
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.
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).
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)").
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."
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().
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."
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:
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:
(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")
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.
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).
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.
Craig Small [Sat, 3 Mar 2018 07:36:44 +0000 (18:36 +1100)]
watch: use sysconf() for hostname length
Hurd doesn't have HOST_NAME_MAX, neither does Solaris.
An early fix just checked for this value and used 64 instead.
This change uses sysconf which is the correct method, possibly until
this compiles on some mis-behaving OS which doesn't have this value.
By default pgrep/pkill should not kill processes in a namespace it is not
part of. If this is allowed, it allows callers to break namespaces they did
not expect to affect, requiring rewrite of all callers to fix.
So by default, we should work in the current namespace. If --ns 0 is
specified, they we look at all namespaces, and if any other pid is specified
we continue to look in only that namespace.
Jim Warner [Wed, 28 Feb 2018 06:00:00 +0000 (00:00 -0600)]
top: show that truncation indicator ('+') consistently
With a little luck, this should be the final tweak for
our support of extra wide characters. Currently, those
characters don't always display the '+' indicator when
they've been truncated. Now, it should always be seen.
[ plus it's done a tad more efficiently via snprintf ]
Signed-off-by: Jim Warner <james.warner@comcast.net>
Masatake YAMATO [Sat, 24 Feb 2018 09:03:11 +0000 (18:03 +0900)]
pidof: allow to change a separator put between pids
I frequency use pidof command with strace system call tracer.
strace can trace MULTIPLE processes specified with "-p $PID"
arguments like:
strace -p 1 -p 1030 -p 3043
Sometimes I want to do as following
strace -p $(pidof httpd)
However, above command line doesn't work because -p option
is needed for specifying a pid. pidof uses a whitespace as
a separator. For passing the output to strace, the separator
should be replaced with ' -p '.
This maybe not a special to my use case.
This commit introduces -S option that allows a user to specify a
separator the one wants.
Craig Small [Thu, 1 Mar 2018 10:25:04 +0000 (21:25 +1100)]
sysctl: Bring procio functions out of library
The procio functions that were in the library have been
moved into sysctl. sysctl is not linked to libprocps in
newlib and none of the other procps binaries would need
to read/write large data to the procfs.
Werner Fink [Thu, 18 Jan 2018 10:26:37 +0000 (11:26 +0100)]
Add flexible buffered I/O based on fopencookie(3)
to be able to read and write large buffers below /proc.
The buffers and file offsets are handled dynamically
on the required buffer size at read, that is lseek(2)
is used to determine this size. Large buffers at
write are split at a delimeter into pieces and also
lseek(2) is used to write each of them.