The function is obsolete. It is recommended to use getrlimit(2) instead
(see the manual page for ulimit(3) or the POSIX manual for it). Since
getrlimit(2) is required by POSIX.1-2001, we can rely on it.
Cc: Christian Göttsche <cgzones@googlemail.com> Signed-off-by: Alejandro Colomar <alx@kernel.org>
Replace the deprecated getpass(3) by our agetpass()
getpass(3) is broken in all implementations; in some, more than
others, but somewhat broken in all of them. Check the immediate
previous commit, which added the functions, for more details.
Check also the Linux man-pages commit that marked it as
deprecated, for more details: 7ca189099d73bde954eed2d7fc21732bcc8ddc6b.
Link: <https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit?id=7ca189099d73bde954eed2d7fc21732bcc8ddc6b> Reported-by: Christian Göttsche <cgzones@googlemail.com> Signed-off-by: Alejandro Colomar <alx@kernel.org>
Alex Colomar [Mon, 26 Sep 2022 20:22:24 +0000 (22:22 +0200)]
libmisc: agetpass(), erase_pass(): Add functions for getting passwords safely
There are several issues with getpass(3).
Many implementations of it share the same issues that the infamous
gets(3). In glibc it's not so terrible, since it's a wrapper
around getline(3). But it still has an important bug:
If the password is long enough, getline(3) will realloc(3) memory,
and prefixes of the password will be laying around in some
deallocated memory.
See the getpass(3) manual page for more details, and especially
the commit that marked it as deprecated, which links to a long
discussion in the linux-man@ mailing list.
So, readpassphrase(3bsd) is preferrable, which is provided by
libbsd on GNU systems. However, using readpassphrase(3) directly
is a bit verbose, so we can write our own wrapper with a simpler
interface similar to that of getpass(3).
One of the benefits of writing our own interface around
readpassphrase(3) is that we can hide there any checks that should
be done always and which would be error-prone to repeat every
time. For example, check that there was no truncation in the
password.
Also, use malloc(3) to get the buffer, instead of using a global
buffer. We're not using a multithreaded program (and it wouldn't
make sense to do so), but it's nice to know that the visibility of
our passwords is as limited as possible.
erase_pass() is a clean-up function that handles all clean-up
correctly, including zeroing the entire buffer, and then
free(3)ing the memory. By using [[gnu::malloc(erase_pass)]], we
make sure that we don't leak the buffers in any case, since the
compiler will be able to enforce clean up.
Link: <https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit?id=7ca189099d73bde954eed2d7fc21732bcc8ddc6b> Reported-by: Christian Göttsche <cgzones@googlemail.com> Signed-off-by: Alejandro Colomar <alx@kernel.org>
Florian Weimer [Mon, 21 Nov 2022 10:52:45 +0000 (11:52 +0100)]
Fix HAVE_SHADOWGRP configure check
The missing #include <gshadow.h> causes the configure check to fail
spuriously, resulting in HAVE_SHADOWGRP not being defined even
on systems that actually have sgetsgent (such as current glibc).
Andy Zaugg [Tue, 18 Oct 2022 23:30:14 +0000 (16:30 -0700)]
Allow supplementary groups to be added via config file
Allow supplementary groups to be set via the /etc/default/useradd config
file. Allowing an administrator to set additonal groups via the GROUPS
configurable and control the default behaviour of useradd.
This program has 10 calls to gets(3) according to grep(1). That
makes it a very unsafe program which should not be used at all.
Let's kill the program already.
See what gets(3) has to say:
SYNOPSIS
#include <stdio.h>
[[deprecated]] char *gets(char *s);
DESCRIPTION
Never use this function.
...
BUGS
Never use gets(). Because it is impossible to tell with‐
out knowing the data in advance how many characters
gets() will read, and because gets() will continue to
store characters past the end of the buffer, it is ex‐
tremely dangerous to use. It has been used to break com‐
puter security. Use fgets() instead.
For more information, see CWE‐242 (aka "Use of Inherently
Dangerous Function") at http://cwe.mitre.org/data/defini‐
tions/242.html
Acked-by: "Serge E. Hallyn" <serge@hallyn.com> Signed-off-by: Alejandro Colomar <alx@kernel.org>
glibc, musl, FreeBSD, and OpenBSD define the MAX() and MIN()
macros in <sys/param.h> with the same definition that we use.
Let's not redefine it here and use the system one, as it's
effectively the same as we define (modulo whitespace).
Alex Colomar [Wed, 28 Sep 2022 20:03:52 +0000 (22:03 +0200)]
Don't test for NULL before calling free(3)
free(3) accepts NULL, since the oldest ISO C. I guess the
paranoid code was taking care of prehistoric implementations of
free(3). I've never known of an implementation that doesn't
conform to this, so let's simplify this.
Remove xfree(3), which was effectively an equivalent of free(3).
Luca BRUNO [Mon, 29 Aug 2022 12:35:07 +0000 (12:35 +0000)]
lib/commonio: make lock failures more detailed
This tweaks the database locking logic so that failures in the
link-checking paths are more detailed.
The rationale for this is that I've experienced a non-deterministic
bug which seems to be coming from this logic, and I'd like to get
more details about the actual failing condition.
The setuid, setgid, and sticky bits are not copied during copy_tree.
Also start with very restrictive permissions before setting ownerships.
This prevents situations in which users in a group with less permissions
than others could win a race in opening the file before permissions are
removed again.
This means that between openat and chownat_if_needed a user of group
fandom could open /tmp/uwu/owo and read the content when it is finally
written into the file.
The groupadd from shadow does not allow upper case group names, the
same is true for the upstream shadow. But distributions like
Debian/Ubuntu/CentOS has their own way to cope with this problem,
this patch is picked up from Fedora [1] to relax the usernames
restrictions to allow the upper case group names, and the relaxation is
POSIX compliant because POSIX indicate that usernames are composed of
characters from the portable filename character set [A-Za-z0-9._-].
useradd: Do not reset non-existent data in {last,fail}log
useradd does not create the files if they don't exist, but if they exist
it will reset user data even if the data did not exist before creating
a hole and an explicitly zero'd data point resulting (especially for
high UIDs) in a lot of zeros ending up in containers and tarballs.
Use *at() functions to pin the directory operating in to avoid being
redirected by unprivileged users replacing parts of paths by symlinks to
privileged files.
Introduce a path_info struct with the full path and dirfd and name
information for *at() functions, since the full path is needed for link
resolution, SELinux label lookup and ACL attributes.
copydir.c:666:44: warning: unsigned conversion from 'int' to '__mode_t' {aka 'unsigned int'} changes value from '-4096' to '4294963200' [-Wsign-conversion]
666 | if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0)
| ^
copydir.c:116:1: warning: missing initializer for field 'quote' of 'struct error_context' [-Wmissing-field-initializers]
116 | };
| ^
In file included from copydir.c:27:
/usr/include/attr/error_context.h:30:23: note: 'quote' declared here
30 | const char *(*quote) (struct error_context *, const char *);
| ^~~~~
Use *at() functions to pin the directory operating in to avoid being
redirected by unprivileged users replacing parts of paths by symlinks to
privileged files.
Use *at() functions to pin the directory operating in to avoid being
redirected by unprivileged users replacing parts of paths by symlinks to
privileged files.
Allow the compiler to verify the format string against the supplied
arguments.
chage.c:239:51: warning: format not a string literal, format string not checked [-Wformat-nonliteral]
239 | (void) strftime (buf, sizeof buf, format, tp);
| ^~~~~~
salt.c:102:22: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
102 | static /*@observer@*/const unsigned long SHA_get_salt_rounds (/*@null@*/int *prefered_rounds);
| ^~~~~
salt.c:110:22: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
110 | static /*@observer@*/const unsigned long YESCRYPT_get_salt_cost (/*@null@*/int *prefered_cost);
| ^~~~~
subordinateio.c:160:8: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
160 | static const bool range_exists(struct commonio_db *db, const char *owner)
| ^~~~~