This is a stability fix, not a security fix, because the affected -o
option can only be used by root and it takes a modified passwd file.
If a gecos field for a user has BUFSIZ characters without commas and an
equals sign (i.e. a huge slop/extra field) and chfn is called with -o,
then a buffer overflow occurs.
It is not possible to trigger this with shadow tools. Therefore, the
passwd file must be modified manually.
I have fixed this unlikely case the easiest and cleanest way possible.
Since chfn bails out if more than 80 characters excluding commas are
supposed to be written into gecos field, we can stop processing early on
if -o argument is too long.
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
This is merely a stability fix, not a security fix.
As the root user, it is possible to set time values which later on
result in signed integer overflows.
For this to work, an sgetspent implementation must be used which
supports long values (glibc on amd64 only parses 32 bit, not 64).
Either use musl or simply call configure with following environment
variable:
$ ac_cv_func_sgetspent=no ./configure
Also it is recommended to compile with -fsanitize=undefined or
-ftrapv to see these issues easily.
Examples to trigger issues when calling "chage -l user":
$ chage -d 9223372036854775807 user
$ chage -d 106751991167300 user
$ chage -M 9999 user
$ chage -d 90000000000000 user
$ chage -I 90000000000000 user
$ chage -M 9999 user
$ chage -E 9223372036854775807 user
While at it, I fixed casting issues which could lead to signed integer
overflows on systems which still have a 32 bit time_t.
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Do not reset the pid_child to 0 if the child process is still
running. This else-condition can be reached with pid being -1,
therefore explicitly test this condition.
This is a regression fix for CVE-2017-2616. If su receives a
signal like SIGTERM, it is not propagated to the child.
Reported-by: Radu Duta <raduduta@gmail.com>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
If su is compiled with PAM support, it is possible for any local user
to send SIGKILL to other processes with root privileges. There are
only two conditions. First, the user must be able to perform su with
a successful login. This does NOT have to be the root user, even using
su with the same id is enough, e.g. "su $(whoami)". Second, SIGKILL
can only be sent to processes which were executed after the su process.
It is not possible to send SIGKILL to processes which were already
running. I consider this as a security vulnerability, because I was
able to write a proof of concept which unlocked a screen saver of
another user this way.
Some of the supplied tools use functions which are not signal-safe.
Most of the times it's exit() vs. _exit().
In other times it's how the standard output or standard error is
handled. FILE-related functions shall be avoided, therefore I replaced
them with write().
Also there is no need to call closelog(). At worst, it allows to
trigger a deadlock by issuing different signal types at bad timings.
But as these fixes are about race conditions, expect bad timings in
general for these bugs to be triggered. :)
The functions __gr_dup and __pw_dup do not explicitly zero the
memory which hold the passwords after free. The gr_free and pw_free
functions do this explicitly.
To guarantee same behaviour, it's possible to call these *_free
functions directly from __*_dup, because the memory is initialized
with zeros at the beginning. Calling free(NULL) has no negative
effect and can be considered safe these days.