]> git.ipfire.org Git - thirdparty/shadow.git/log
thirdparty/shadow.git
2 weeks ago*/: Remove support for DES
Alejandro Colomar [Sat, 27 Dec 2025 11:25:41 +0000 (12:25 +0100)] 
*/: Remove support for DES

Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agouseradd: fix subuid allocation
Serge Hallyn [Fri, 17 Jul 2026 16:03:45 +0000 (11:03 -0500)] 
useradd: fix subuid allocation

closes #1683

The decision on whether to allocate a subuid is dependent
on user_id != 0, but user_id is not filled in until after
the call to this.  I spent a few minutes trying to track
down where this ordering changed, and haven't found it yet.
We can add a fixes tag if we track it down.

Move the decision on whether to calculate it to after we
calculate user_id.  Then, because that decision is used to
decide whether to open the subuid_db, and pull the subuid
db opening out of open_files and run it later.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/: Use SYSLOGE() instead of SYSLOG() with %m
Alejandro Colomar [Sat, 11 Jul 2026 22:16:59 +0000 (00:16 +0200)] 
lib/: Use SYSLOGE() instead of SYSLOG() with %m

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/, src/: Use fprinte() instead of fprintf(3) with %m
Alejandro Colomar [Sat, 11 Jul 2026 22:17:41 +0000 (00:17 +0200)] 
lib/, src/: Use fprinte() instead of fprintf(3) with %m

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/string/: strerrno(): Remove unused macro
Alejandro Colomar [Fri, 6 Mar 2026 23:50:35 +0000 (00:50 +0100)] 
lib/string/: strerrno(): Remove unused macro

We don't use this anymore.

It was helpful temporarily, but now we use higher-level APIs.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/, src/: Use SYSLOGE() instead of its pattern
Alejandro Colomar [Wed, 23 Jul 2025 16:14:32 +0000 (18:14 +0200)] 
lib/, src/: Use SYSLOGE() instead of its pattern

Having such long and complex format strings and variadic arguments is
error-prone, as can be seen in the previous commit, which fixes a bug of
this kind.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/io/syslog.h: SYSLOGE[C](): Add macros
Alejandro Colomar [Wed, 23 Jul 2025 12:23:11 +0000 (14:23 +0200)] 
lib/io/syslog.h: SYSLOGE[C](): Add macros

like the fprintf(3) wrappers, these print an error message.  SYSLOGE()
uses errno, and SYSLOGEC() uses an errno-like error code.

This time we need to be careful to name the local copy of errno
differently than within SYSLOG() --which we call--.  Let's use a double
underscore.  In the future, C might have function literals (similar to
lambdas), which will solve this issue.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/, tests/: Use fprinte() instead of its pattern
Alejandro Colomar [Wed, 23 Jul 2025 15:39:19 +0000 (17:39 +0200)] 
lib/, tests/: Use fprinte() instead of its pattern

While we don't use it directly in tests/, exit_if_null_() uses it, so we
need to link to it in its test.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/io/fprintf.h: fprinte(): Add macro
Alejandro Colomar [Wed, 23 Jul 2025 12:19:52 +0000 (14:19 +0200)] 
lib/io/fprintf.h: fprinte(): Add macro

fprinte() is like fprintec(), but uses errno instead of an error code.

It is implemented as a macro so that it can read the value in errno
before evaluating any of its arguments, thus not corrupting it.

It also preserves errno so that the error can be printed more than once.
This is useful because we often print to stderr or log_get_logfd(), and
immediately after print to the system log with syslog(3).

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/copydir.c: error_acl(): Use vfprintec() instead of its pattern
Alejandro Colomar [Wed, 24 Dec 2025 10:20:53 +0000 (11:20 +0100)] 
lib/copydir.c: error_acl(): Use vfprintec() instead of its pattern

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/io/fprintf.h: [v]fprintec(): Add functions
Alejandro Colomar [Wed, 23 Jul 2025 12:19:52 +0000 (14:19 +0200)] 
lib/io/fprintf.h: [v]fprintec(): Add functions

These functions print a formatted string, followed by a colon and
a space, followed by an error string produced by strerror($2).  That is,
the output is as follows:

fmt: error message string

For example,
fprintec(stderr, ENOMEM, "foo(%d)", 42);
prints
foo(42): Cannot allocate memory

These functions return the number of characters printed, or a negative
value on error, like fprintf(3).

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/copydir.c: error_acl(): Preserve errno
Alejandro Colomar [Wed, 24 Dec 2025 10:19:37 +0000 (11:19 +0100)] 
lib/copydir.c: error_acl(): Preserve errno

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/io/: SYSLOG(): Preserve errno
Alejandro Colomar [Mon, 3 Nov 2025 17:08:11 +0000 (18:08 +0100)] 
lib/io/: SYSLOG(): Preserve errno

In some cases, we print strerrno() with this macro.  Because this is
a macro, and internal calls such as strdup(3) may set errno, that value
could be corrupted when we arrive at syslog(3).  While we could solve
this here, it's not robust.  Instead, we'll use a dedicated wrapper for
that, which will be added in the following commits: SYSLOGE().

What we'll do here is preserve errno when we exit from this macro, as we
often follow SYSLOG() calls with fprintf(stderr,) calls, which also use
the errno value, and we don't want to pollute that.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/, src/: is_valid_group_name(): Remove 'badnames' parameter
Alejandro Colomar [Sun, 12 Jul 2026 15:31:01 +0000 (17:31 +0200)] 
lib/, src/: is_valid_group_name(): Remove 'badnames' parameter

We don't allow badnames in group names.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agosrc/newusers.c: Don't allow bad names in group names
Alejandro Colomar [Sun, 12 Jul 2026 15:26:41 +0000 (17:26 +0200)] 
src/newusers.c: Don't allow bad names in group names

Other programs handling groups don't allow this.
I believe this was only accidentally allowed.

Fixes: a2cd3e9ef03a (2019-10-04; "chkname.c, pwck.c, useradd.c, usermod.c, newusers.c: Allow names that do not conform to standards")
Cc: ed <ed@s5h.net>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agosrc/{chfn,chsh,passwd}.c: Allow bad names
Alejandro Colomar [Sun, 12 Jul 2026 14:40:07 +0000 (16:40 +0200)] 
src/{chfn,chsh,passwd}.c: Allow bad names

These programs don't add new users.  Because they handle existing users,
they should handle them with whatever names they already have, including
bad names.

A recent commit that added some username syntax validation blindly
removed support for bad names in these programs.  Fix that regression.

Fixes: 326889ca81bb (2024-10-22; "Fix coverity unbound buffer issues")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/, src/, tests/: Pass the badname flag as a function parameter
Alejandro Colomar [Sun, 12 Jul 2026 14:22:17 +0000 (16:22 +0200)] 
lib/, src/, tests/: Pass the badname flag as a function parameter

... instead of an extern variable.  This makes it easier to analyze
which programs allow badnames and which don't.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agopo/kk.po: Update from the Translation Project 'shadow-4.20.0-rc2.kk.po'
Baurzhan Muftakhidinov [Sun, 5 Jul 2026 11:32:03 +0000 (13:32 +0200)] 
po/kk.po: Update from the Translation Project 'shadow-4.20.0-rc2.kk.po'

From: Translation Project Robot <robot@translationproject.org>
Message-ID: <E1wgL4t-004Azb-26@duik.vrijschrift.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agotests/unit/test_strncpy.c: Remove strncpy_a() tests
Alejandro Colomar [Fri, 21 Feb 2025 09:22:36 +0000 (10:22 +0100)] 
tests/unit/test_strncpy.c: Remove strncpy_a() tests

It's just the obvious thin wrapper around strncpy(3); let's trust it's
ok.

The reason for removing this test is that GCC has bogus diagnostics
for strncpy(3).  Its diagnostics are geared towards helping people
that abuse strncpy(3) as a poor-man's strlcpy(3) not write exploitable
code as easily.  Using strncpy(3) for that purpose is brain damaged, and
those programs should be audited to stop using this API for that.  And
most importantly, GCC should stop encouraging writing bad code that
calls strncpy(3) as that results in diagnostics that are actively
harmful for us, legitimate users of strncpy(3).  Those false positives
should certainly be out of -Wall.

We could fill the tests with pragmas, but let's just remove the tests.
I don't feel like maintaining code for ignoring GCC's brain bamage.

If people want to write a function for truncating strings (because they
can't rely on strlcpy(3) being available, or because they don't like
it), they certainly should write such an API.  strncpy(3) isn't that
API.  strncpy(3) is a function that takes a string and writes it into a
utmpx(5) member, which is NOT a string.  (And I heard it might also be
useful for implementing tar(1), which also uses non-terminated character
arrays, but I never looked at that code.)

Link: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122963>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agoautogen.sh: Enable -Werror=stringop-* diagnostics
Alejandro Colomar [Fri, 5 Dec 2025 17:12:02 +0000 (18:12 +0100)] 
autogen.sh: Enable -Werror=stringop-* diagnostics

We can't enable -Wstringop-overread because it has bogus diagnostics
with legitimate strncat(3) calls.

We can't enable -Wstringop-truncation because it has bogus diagnostics
with legitimate strncpy(3) calls.

Link: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123024>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agolib/, man/: Default to SHA512 instead of DES
Alejandro Colomar [Fri, 26 Dec 2025 23:59:04 +0000 (00:59 +0100)] 
lib/, man/: Default to SHA512 instead of DES

DES is insecure; use it only if explicitly requested.

Closes: <https://github.com/shadow-maint/shadow/issues/1278>
Reported-by: Andre Boscatto <andreboscatto@gmail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agoetc/login.defs: Group password strength controls
Alejandro Colomar [Tue, 16 Dec 2025 12:33:17 +0000 (13:33 +0100)] 
etc/login.defs: Group password strength controls

Reported-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 weeks agoetc/login.defs: Remove defaults for password expiration
Alejandro Colomar [Mon, 15 Dec 2025 13:03:49 +0000 (14:03 +0100)] 
etc/login.defs: Remove defaults for password expiration

Expiring passwords has been determined to decrease safety.
Let's default to not expiring passwords.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
3 weeks agotests/system/tests/: sp_min: Ignore field
Alejandro Colomar [Sun, 5 Jul 2026 19:20:27 +0000 (21:20 +0200)] 
tests/system/tests/: sp_min: Ignore field

Link: <https://github.com/shadow-maint/shadow/pull/1482>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
3 weeks ago*/: shadow(5): sp_min: Ignore field, and clear it
Alejandro Colomar [Wed, 17 Dec 2025 17:52:07 +0000 (18:52 +0100)] 
*/: shadow(5): sp_min: Ignore field, and clear it

Whenever we were reading it, let's assume it contains a -1 (the integer
representation of an empty field).  Whenever we were writing it, let's
write a -1.

I think this would be worth a CVE.  I've contacted Debian, in case they
can issue a CVE.  Here's the draft I've sent them for the CVE:

shadow-utils: inability to change a compromised password

Description
A flaw was found in /etc/shadow, and the programs that handle
the file.

The /etc/shadow database (documented in shadow(5)) entries
contain a "minimum password age" field.  This field imposes
a minimum password age before the password can be changed.

If a user's password is compromised before that period expires,
the user must contact the administrator to be able to change the
password.  This can usually take hours or days, and during these
hours or days, an attacker would have unlimited access to the
credentials.

One option of the user would be to lock its own password with
'passwd -l', thus being locked out of its own account.

The history of this 4th field of /etc/shadow entries is
considered dubious in retrospective, and the recommended action
is to never set this field.  If the field is set, the
recommended action is to ignore the field, and if possible,
remove it.

Link: <https://github.com/shadow-maint/shadow/pull/1482>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
3 weeks ago*/: login.defs(5): PASS_MIN_DAYS: Remove configuration variable
Alejandro Colomar [Tue, 16 Dec 2025 20:23:19 +0000 (21:23 +0100)] 
*/: login.defs(5): PASS_MIN_DAYS: Remove configuration variable

Link: <https://github.com/shadow-maint/shadow/pull/1482>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
3 weeks ago*/: passwd(1): -n,--mindays: Remove option
Alejandro Colomar [Tue, 16 Dec 2025 19:53:31 +0000 (20:53 +0100)] 
*/: passwd(1): -n,--mindays: Remove option

It makes no sense to limit the frequency of password change.  If one
changes its password, and 5 minutes later the password is leaked, one
should be able to change the password immediately.

Link: <https://github.com/shadow-maint/shadow/pull/1482>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
3 weeks ago*/: chage(1): -m,--mindays: Remove option
Alejandro Colomar [Wed, 17 Dec 2025 12:05:47 +0000 (13:05 +0100)] 
*/: chage(1): -m,--mindays: Remove option

Link: <https://github.com/shadow-maint/shadow/pull/1482>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
3 weeks agosrc/chage.c: Remove interactive -m
Alejandro Colomar [Wed, 17 Dec 2025 12:31:06 +0000 (13:31 +0100)] 
src/chage.c: Remove interactive -m

Link: <https://github.com/shadow-maint/shadow/pull/1482>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
3 weeks agosubids: find_free_range(): skip empty ranges
Hadi Chokr [Thu, 9 Jul 2026 13:28:41 +0000 (13:28 +0000)] 
subids: find_free_range(): skip empty ranges

Empty (count == 0) ranges constrain nothing, so skip them instead of
processing them.  Besides documenting that invariant, this keeps the
range-end computation, first - 1LL + range->count, away from the
count == 0 corner, where for first == 0 it would produce -1 through
unsigned long wrap-around and an implementation-defined conversion on
64-bit systems.

Such entries exist in the wild, since old useradd versions used to
create them, so they are still accepted by the parser; they are only
ignored during allocation.

Co-authored-by: Dan Anderson <https://github.com/MillaFleurs>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Hadi Chokr <hadichokr@icloud.com>
3 weeks agosubids: reject subid file entries that do not fit in id_t
Hadi Chokr [Thu, 9 Jul 2026 07:30:36 +0000 (07:30 +0000)] 
subids: reject subid file entries that do not fit in id_t

range->start and range->count are parsed from /etc/subuid and
/etc/subgid as unsigned long, so a corrupt or malicious entry was not
bounded by id_t: find_free_range() assigned such a start to intmax_t,
which is implementation-defined above INTMAX_MAX, and the range-end
computation could exceed INTMAX_MAX.

Validate the values where they are parsed, instead of hardening each
consumer: bound start to maxof(id_t) in subordinate_parse(), and
bound count so that the last ID of the range, start + count - 1, fits
in id_t as well; the MIN() caps that bound at maxof(id_t), which
also keeps it representable in unsigned long on 32-bit systems.
a2ul() reports ERANGE for out-of-range values.

Rejected entries are skipped when iterating the database
(commonio_next() skips entries whose parse failed), while the raw line
is still preserved if the file is rewritten.  This protects all
consumers of these fields, not just allocation.

After this, every visible range satisfies
0 <= start <= start + count - 1 <= (id_t)-1, so the intmax_t
arithmetic in find_free_range() is exact and cannot overflow, and
oversized values no longer need to be handled there.

This is a separate, pre-existing problem from the regression fixed in
the previous commit: before de7f1c78f70f8df4b2956f7363da3774348bc58e
this arithmetic was done in unsigned long and silently wrapped for
such values.

Co-authored-by: Dan Anderson <https://github.com/MillaFleurs>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Hadi Chokr <hadichokr@icloud.com>
3 weeks agosubids: fix security regression which can cause overlapping ranges
Hadi Chokr [Mon, 6 Jul 2026 12:29:13 +0000 (14:29 +0200)] 
subids: fix security regression which can cause overlapping ranges

Fix bug from de7f1c78f70f8df4b2956f7363da3774348bc58e that changed from
using unsigned long to id_t.  new_subid_range() returns the same value
as the ceiling allowing potentially overlapping subordinate ID ranges.

In a nutshell, the commit updated lib/subordinateio.c which now allows
creation of overlapping subordinate ID ranges. This is caused because
the commit changed from unsigned long to id_t. The bug is that the
internal algorithm still used an exclusive endpoint expression, max + 1,
which was only safe while the intermediate type was wide enough. So
find_free_range() accepts max as an inclusive ID ceiling, but internally
compares holes against max + 1.

When max is (id_t)-1 on an unsigned-ID build, max + 1 wraps to zero.
new_subid_range() passes exactly that value as the ceiling.

Fix it by doing the internal arithmetic in signed types that are
strictly wider than id_t, so that max + 1, last + 1, and the hole
computations cannot wrap:

- The static_assert checks that long long is wider than id_t.  That
  makes max + 1LL exact, and since intmax_t is at least as wide as
  long long, it also guarantees that the intmax_t variables are wider
  than id_t.

- count is converted up front into the intmax_t variable n, which the
  input check and the later size comparisons use directly, without
  casts.  The input check is done in signed arithmetic, as
  n > max - min + 1LL: max >= min holds at that point, so max - min is
  in the range 0 .. (id_t)-1, and adding 1LL to that fits in long long.

- The end of each range is computed as first - 1LL + range->count,
  which likewise needs no cast.

- The final check on the remaining unclaimed area is written as
  max - low >= n - 1 rather than (max - low) + 1 >= n: low <= max and
  n >= 1 hold there, so neither side of the comparison can overflow.

This was found with N184, an open source bug and security vulnerability
scanner: https://github.com/MillaFleurs/N184

Closes: <https://github.com/shadow-maint/shadow/issues/1629>
Co-authored-by: Dan Anderson <https://github.com/MillaFleurs>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Hadi Chokr <hadichokr@icloud.com>
3 weeks agolib/subordinateio.c: Don't rely on id_t being unsigned
Alejandro Colomar [Wed, 8 Jul 2026 23:20:02 +0000 (01:20 +0200)] 
lib/subordinateio.c: Don't rely on id_t being unsigned

POSIX doesn't provide any guarantees about the signedness of id_t.

Reported-by: Serge Hallyn <serge@hallyn.com>
Fixes: de7f1c78f70f (2026-04-09; "lib/subordinateio.c: find_free_range(): Use id_t instead of u_long")
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
3 weeks agolib/typetraits.h: maxof(), minof(): Use the compiler operators if available
Alejandro Colomar [Thu, 27 Nov 2025 00:13:07 +0000 (01:13 +0100)] 
lib/typetraits.h: maxof(), minof(): Use the compiler operators if available

Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
3 weeks ago*/: Rename type_min() => minof(), type_max() => maxof()
Alejandro Colomar [Thu, 27 Nov 2025 00:10:28 +0000 (01:10 +0100)] 
*/: Rename type_min() => minof(), type_max() => maxof()

GCC 16 has added two new operators, _Minof() and _Maxof().
Let's name our macros like these (but without the reserved names).

I'm also working on standardization of these operators within the
C Committee.

Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3628.txt>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
3 weeks agolib/typetraits.h: Compact macros
Alejandro Colomar [Thu, 27 Nov 2025 00:06:13 +0000 (01:06 +0100)] 
lib/typetraits.h: Compact macros

Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
3 weeks agoAvoid falling prey to tiocsti
Serge Hallyn [Tue, 9 Jun 2026 01:08:04 +0000 (20:08 -0500)] 
Avoid falling prey to tiocsti

We've long known (see
https://www.halfdog.net/Security/2012/TtyPushbackPrivilegeEscalation/
and https://jdebp.uk/FGA/dont-abuse-su-for-dropping-privileges.html)
that su should be used to gain but not drop privilege.  Much more
recently, linux added the ability to prevent TIOCSTI through a
configurable /proc/sys/dev/tty/legacy_tiocsti setting.

If /proc/sys/dev/tty/legacy_tiocsti is set to 0, then we are protected
from the callee injecting commands on caller's tty through TIOCSTI.
If it's 1, or doesn't exist, then we are not.  That can be dangerous
if caller is root.  We currently give up the controlling terminal
for non-interactive uses of su (-c).  Let's do that for interactive
calls as well, only in the dangerous case.

3 weeks agoman/cs: fix distribution of Czech man pages
Iker Pedrosa [Wed, 8 Jul 2026 13:57:05 +0000 (15:57 +0200)] 
man/cs: fix distribution of Czech man pages

The Czech Makefile.am was accidentally truncated during the groupmems
removal. This caused the Czech man pages to be excluded from the release
tarballs.

Restoring the Makefile.am and regenerating the release fixes the
problem.

Fixes: 388ce70d ("*/: groupmems(8): Remove program")
Closes: https://github.com/shadow-maint/shadow/issues/1666
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
3 weeks agosrc/newusers.c: A user/group name with a leading digit is valid
Alejandro Colomar [Sat, 3 Jan 2026 23:15:15 +0000 (00:15 +0100)] 
src/newusers.c: A user/group name with a leading digit is valid

Only consider a string to be a UID/GID if it is all digits.

Here's a reproducer of the bug:

$ echo 'foo:p::1a::/tmp/nonexistent:/usr/bin/false' > x
$ sudo newusers ./x
newusers: invalid group ID '1a'
newusers: line 1: can't create group

Where the expected behavior would be the same as for a group name that
doesn't start with a digit:

$ echo 'foo:p::a1a::/tmp/nonexistent:/usr/bin/false' > x
$ sudo newusers ./x
$ tail -n1 /etc/group
a1a:x:1004:
$ tail -n1 /etc/passwd
foo:x:1004:1004::/tmp/nonexistent:/usr/bin/false

Closes: <https://github.com/shadow-maint/shadow/issues/1474>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
4 weeks agopo/ro.po: Update from the Translation Project 'shadow-4.20.0-rc2.ro.po'
Remus-Gabriel Chelu [Sat, 27 Jun 2026 09:47:03 +0000 (11:47 +0200)] 
po/ro.po: Update from the Translation Project 'shadow-4.20.0-rc2.ro.po'

This is the second version we receive of this file.

From: Translation Project Robot <robot@translationproject.org>
Message-Id: <E1wdPct-002asf-2R@duik.vrijschrift.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
4 weeks agopo/de.po: Update from the Translation Project 'shadow-4.20.0-rc2.de.po'
Mario Blättermann [Thu, 25 Jun 2026 19:57:03 +0000 (21:57 +0200)] 
po/de.po: Update from the Translation Project 'shadow-4.20.0-rc2.de.po'

From: Translation Project Robot <robot@translationproject.org>
Message-Id: <E1wcqC7-002KyQ-1w@duik.vrijschrift.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
4 weeks agoman/po/ro.po: Update from the Translation Project 'shadow-man-4.20.0-rc2.ro.po'
Remus-Gabriel Chelu [Thu, 25 Jun 2026 18:37:07 +0000 (20:37 +0200)] 
man/po/ro.po: Update from the Translation Project 'shadow-man-4.20.0-rc2.ro.po'

From: Translation Project Robot <robot@translationproject.org>
Message-Id: <E1wcowl-002KHz-12@duik.vrijschrift.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
4 weeks agopo/nl.po: Update from the Translation Project 'shadow-4.20.0-rc2.nl.po'
Frans Spiesschaert [Thu, 25 Jun 2026 12:47:02 +0000 (14:47 +0200)] 
po/nl.po: Update from the Translation Project 'shadow-4.20.0-rc2.nl.po'

From: Translation Project Robot <robot@translationproject.org>
Message-Id: <E1wcjTy-002H4p-2h@duik.vrijschrift.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
4 weeks agoTests: Force creation of existing group using -f flag
Akshay Sakure [Wed, 1 Jul 2026 09:51:43 +0000 (15:21 +0530)] 
Tests: Force creation of existing group using -f flag

This is Python transformation of the test located in
'tests/grouptools/groupadd/06_groupadd_-f_add_existing_group/groupadd.test'
which checks that 'groupadd' completes successfully while force-creating
an existing group using -f flag

Signed-off-by: Akshay Sakure <asakure@redhat.com>
4 weeks agoTests: Add group with password using -p flag
Akshay Sakure [Tue, 30 Jun 2026 14:09:56 +0000 (19:39 +0530)] 
Tests: Add group with password using -p flag

This is Python transformation of the test located in
'tests/grouptools/groupadd/04_groupadd_set_password/groupadd.test'
which checks that 'groupadd' can create group with password using
-p flag

Signed-off-by: Akshay Sakure <asakure@redhat.com>
4 weeks agoTests: Add group with specified GID using -g flag
Akshay Sakure [Tue, 23 Jun 2026 13:45:43 +0000 (19:15 +0530)] 
Tests: Add group with specified GID using -g flag

This is Python transformation of the test located in
`tests/grouptools/groupadd/05_groupadd_set_GID/groupadd.test`
which checks that `groupadd` can create group with sepcified GID
using -g flag

Signed-off-by: Akshay Sakure <asakure@redhat.com>
4 weeks agoTests: Change multiple user attributes at once
aborah-sudo [Tue, 30 Jun 2026 07:43:49 +0000 (13:13 +0530)] 
Tests: Change multiple user attributes at once

This is the transformation to Python of the test located in
`tests/usertools/01/09_usermod_change_user_info.test`
which checks that `usermod` can change multiple user attributes at once

5 weeks agosrc/: Simplify error strings
Alejandro Colomar [Thu, 25 Jun 2026 20:28:59 +0000 (22:28 +0200)] 
src/: Simplify error strings

Avoid language that would need translation.
Move language that would need translation to a separate argument.

Closes: <https://github.com/shadow-maint/shadow/issues/1662>
Reported-by: Rafael Fontenelle <https://github.com/rffontenelle>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
5 weeks agosrc/: usage(): tfix
Alejandro Colomar [Thu, 25 Jun 2026 20:27:11 +0000 (22:27 +0200)] 
src/: usage(): tfix

Fixes: 1ed06fee4c8d (2026-02-25; "usermod: Add option to automatically find subordinate IDs")
Fixes: 3f7a72e9677b (2022-08-01; "useradd: add -F option for updating /etc/sub[ig]id for system accounts")
Closes: <https://github.com/shadow-maint/shadow/issues/1662>
Reported-by: Rafael Fontenelle <https://github.com/rffontenelle>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
5 weeks agosrc/useradd.c: usage(): wfix
Alejandro Colomar [Thu, 25 Jun 2026 20:24:52 +0000 (22:24 +0200)] 
src/useradd.c: usage(): wfix

Make the text consistent, to help translators.

Closes: <https://github.com/shadow-maint/shadow/issues/1662>
Reported-by: Rafael Fontenelle <https://github.com/rffontenelle>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
5 weeks agopo/ro.po: Update from the Translation Project 'shadow-4.20.0-rc2.ro.po'
Remus-Gabriel Chelu [Tue, 23 Jun 2026 23:42:11 +0000 (01:42 +0200)] 
po/ro.po: Update from the Translation Project 'shadow-4.20.0-rc2.ro.po'

From: Translation Project Robot <robot@translationproject.org>
Message-ID: <E1wcAkt-001z51-1W@duik.vrijschrift.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
5 weeks agopo/uk.po: Update from the Translation Project 'shadow-4.20.0-rc2.uk.po'
Yuri Chornoivan [Tue, 23 Jun 2026 15:52:02 +0000 (17:52 +0200)] 
po/uk.po: Update from the Translation Project 'shadow-4.20.0-rc2.uk.po'

From: Translation Project Robot <robot@translationproject.org>
Message-ID: <E1wc3Pu-001tH3-1q@duik.vrijschrift.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
5 weeks agoAdd notes about translations
Mario Blättermann [Wed, 24 Jun 2026 10:29:55 +0000 (12:29 +0200)] 
Add notes about translations

5 weeks agotests: link unit tests with libshadow.la
Mike Gilbert [Tue, 23 Jun 2026 17:25:50 +0000 (13:25 -0400)] 
tests: link unit tests with libshadow.la

This fixes errors when the compiler chooses not to inline function calls.

Closes: https://github.com/shadow-maint/shadow/issues/1654
Signed-off-by: Mike Gilbert <floppym@gentoo.org>
5 weeks ago(pre-)Release 4.20.0-rc2 4.20.0-rc2
Serge Hallyn [Tue, 23 Jun 2026 02:57:06 +0000 (21:57 -0500)] 
(pre-)Release 4.20.0-rc2

Second pre-release of 4.20, 'Ibores'.

Also update translations.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
5 weeks agosrc/su.c: usage(): Use one fputs(3) call per option
Alejandro Colomar [Sat, 20 Jun 2026 14:59:41 +0000 (16:59 +0200)] 
src/su.c: usage(): Use one fputs(3) call per option

This makes it easier for translators to work.

Reported-by: Benno Schulenberg <coordinator@translationproject.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
5 weeks agopo: tell xgettext that we want line numbers
Serge Hallyn [Sun, 21 Jun 2026 22:42:59 +0000 (17:42 -0500)] 
po: tell xgettext that we want line numbers

This helps translators find the origin of each entry.

On the other hand, in man/po/ tell msgmerge not to add
file:line.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
Acked-by: Alejandro Colomar <alx@kernel.org>
6 weeks agopasswd: add UPN validation support
Iker Pedrosa [Tue, 2 Jun 2026 13:18:31 +0000 (15:18 +0200)] 
passwd: add UPN validation support

Add User Principal Name (UPN) validation to allow passwd command to
accept usernames in user@domain.com format. Currently, passwd will
accept both traditional usernames and UPN format.

Fixes: 326889ca (2024-10-22; "Fix coverity unbound buffer issues")
Closes: <https://github.com/shadow-maint/shadow/issues/1626>
Reported-by: @nooreldeenmansour
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
6 weeks agotests: add unit tests for UPN validation
Iker Pedrosa [Tue, 2 Jun 2026 13:01:36 +0000 (15:01 +0200)] 
tests: add unit tests for UPN validation

Add comprehensive unit tests for is_valid_upn() function in
`tests/unit/test_chkname.c` covering:
- Valid UPN formats (user@domain.com)
- Invalid structures (missing @, multiple @)
- Domain validation (RFC compliance)
- Boundary limits (253/254 char domains, 63+ char labels)

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
6 weeks agolib/chkname.*: Add UPN validation support
Iker Pedrosa [Tue, 2 Jun 2026 11:15:42 +0000 (13:15 +0200)] 
lib/chkname.*: Add UPN validation support

Add is_valid_upn() function to validate User Principal Name format.  UPN
validation splits on @ and validates the prefix using existing username
rules and suffix part using RFC 1035/1123 compliant domain name
validation.

Link: <https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.1>
Co-authored-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Co-authored-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
6 weeks agodoc/contributions/: Add guidelines severely restricting use of AI for contributing
Alejandro Colomar [Fri, 26 Dec 2025 17:34:02 +0000 (18:34 +0100)] 
doc/contributions/: Add guidelines severely restricting use of AI for contributing

This policy has been derived from Gentoo.  I added a requirement that
use of AI is disclosed.  And changes resulting from said use should be
disclosed in detail.  Also, I left a note saying we'll reject
non-negligible use of AI, which is a bit of an escape allowing us to
just say "too much".

Link: <https://arstechnica.com/ai/2025/07/study-finds-ai-tools-made-open-source-software-developers-19-percent-slower/>
Link: <https://petri.com/ai-coding-tools-rising-software-defects/>
Link: <https://ia.acs.org.au/article/2024/ai-coding-tools-may-produce-worse-software-.html>
Link: <https://carbonate.dev/blog/posts/the-ai-code-quality-crisis>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
6 weeks agosrc/login_nopam.c: from_match(): Use strrspn_() instead of its pattern
Alejandro Colomar [Sun, 1 Mar 2026 21:34:00 +0000 (22:34 +0100)] 
src/login_nopam.c: from_match(): Use strrspn_() instead of its pattern

Signed-off-by: Alejandro Colomar <alx@kernel.org>
6 weeks agolib/string/strspn/: strr[c]spn(): Return the length counting from the end
Alejandro Colomar [Sun, 1 Mar 2026 21:27:33 +0000 (22:27 +0100)] 
lib/string/strspn/: strr[c]spn(): Return the length counting from the end

Instead of returning the offset from the start of the string, return the
length of the span counting from the end.

This makes the name of the function more representative of its behavior,
and also makes the functions more useful: one can use them as booleans
to determine whether a string ends in a set of characters or not.

if (strrspn(s, "xyz"))  // Does 's' end in any chars of "xyz"?

Currently, the only uses of strr[c]spn() are for implementing
stpr[c]spn(), so we had to update those too.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
6 weeks agoUpdate translations after pre-release 4.20.0-rc1
Serge Hallyn [Wed, 17 Jun 2026 20:01:36 +0000 (15:01 -0500)] 
Update translations after pre-release

Signed-off-by: Serge Hallyn <serge@hallyn.com>
6 weeks ago(pre-)Release 4.20.0-rc1
Serge Hallyn [Wed, 17 Jun 2026 15:17:01 +0000 (10:17 -0500)] 
(pre-)Release 4.20.0-rc1

First pre-release of 4.20.0, 'Ibores'.

Also bump the libsubid major version, because we have introduced
the deterministic subid calculation mode.

6 weeks agoUpdate translations
Serge Hallyn [Wed, 17 Jun 2026 19:23:53 +0000 (14:23 -0500)] 
Update translations

make -C po
make -C man/po update-po

Signed-off-by: Serge Hallyn <serge@hallyn.com>
6 weeks agoman/po: keep tmpdir out of po files
Serge Hallyn [Wed, 17 Jun 2026 18:55:07 +0000 (13:55 -0500)] 
man/po: keep tmpdir out of po files

When we pass every filename to the itstool call as $tmpdir/$base.out,
the file:line listed in the .po includes the $tmpdir.  That means
every update-po changes every .po.

Instead, cd to $tmpdir and pass in the basenames.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
6 weeks agoUpdated po/ro.po file based upon .pot file from 2025-12-30
Remus-Gabriel Chelu [Sat, 13 Jun 2026 18:55:32 +0000 (20:55 +0200)] 
Updated po/ro.po file based upon .pot file from 2025-12-30

Signed-off-by: Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>
6 weeks agoMake man/po update-po more robust
Serge Hallyn [Tue, 16 Jun 2026 17:35:03 +0000 (12:35 -0500)] 
Make man/po update-po more robust

There were some inconsistencies in how remove-potcdate was named.
It exists as po/remove-potcdate.sin.  The man/po tried to copy that
in, but it referred to it as remove-potcdate.sed.

Just copy it in as remove-potcdate.sed.  I think we can do better
than this, but for now this should make update-po more robust.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
7 weeks agolib/nss.c: Move '\n' check earlier
Alejandro Colomar [Tue, 3 Mar 2026 11:29:56 +0000 (12:29 +0100)] 
lib/nss.c: Move '\n' check earlier

If a line doesn't have a '\n', this is a problem, and the line should be
rejected, immediately.

Also, remove the '\n' during the check (with stpsep()), because we don't
want it there when handling the string.

Link: <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap03.html#tag_03_387>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/nss.c: Fix error handling
Alejandro Colomar [Tue, 3 Mar 2026 15:14:50 +0000 (16:14 +0100)] 
lib/nss.c: Fix error handling

This error message didn't make much sense.  After inspecting the commit
in which it was introduced, it seems the intention was to diagnose if
the line was empty after ignoring white space.  It was incorrectly
written then, so fix it now.

Rewrite it in the following way:

-  If there's not a '\n', the entire line is bogus.  Fail, and report an
   appropriate diagnostic.

-  Then, break the string at the first white space, as we were doing
   before.  No error handling is appropriate here.

-  Then, diagnose if the remaining string is empty.

Fixes: 8492dee6 (2021-04-16; "subids: support nsswitch")
Link: <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap03.html#tag_03_387>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/nss.c: Fix incorrect handling of white space
Alejandro Colomar [Tue, 3 Mar 2026 14:33:34 +0000 (15:33 +0100)] 
lib/nss.c: Fix incorrect handling of white space

Having trailing white space in a line doesn't remove the need for
a trailing '\n'.  Let's fail if a line doesn't have it, regardless of
how much trailing white space there is.

Fixes: 8492dee6 (2021-04-16; "subids: support nsswitch")
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/: Merge "lib/string/ctype/*" files even further
Alejandro Colomar [Fri, 13 Mar 2026 00:16:26 +0000 (01:16 +0100)] 
lib/: Merge "lib/string/ctype/*" files even further

Most of these are just one-liners, so they fit in less files, and that
makes them even easier to compare all at once.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/string/ctype/strisascii.*: Don't special-case ""
Alejandro Colomar [Sat, 3 Jan 2026 13:37:43 +0000 (14:37 +0100)] 
lib/string/ctype/strisascii.*: Don't special-case ""

It is not intuitive or clear what the right behavior should be for an
empty string.  If we define these APIs as "return true if all characters
in the string belong to the specified character set", then an empty
string should return true.  On the other hand, if you ask me if an empty
string is a numeric string, I might naively say no.

It is irrelevant whether we return true or false for an empty string.
All of the callers already handle correctly the case of an empty string.

This makes the implementation simpler, using the argument only once.
This allows implementing these as macros.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/fields.c: valid_field(): Check empty string before strisprint_c()
Alejandro Colomar [Sat, 3 Jan 2026 13:33:44 +0000 (14:33 +0100)] 
lib/fields.c: valid_field(): Check empty string before strisprint_c()

This allows us to not depend on whether strisprint_c("") returns true or
false.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/string/ctype/strchrisascii.h: Use strpbrk(3) to simplify
Alejandro Colomar [Fri, 2 Jan 2026 23:37:18 +0000 (00:37 +0100)] 
lib/string/ctype/strchrisascii.h: Use strpbrk(3) to simplify

This compacts it into a one-liner, more similar to the strisascii_c()
functions.

Since we only use the argument once, we can even turn this into a macro.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/: stris*(): Rename C-locale APIs with a _c suffix
Alejandro Colomar [Fri, 2 Jan 2026 20:46:31 +0000 (21:46 +0100)] 
lib/: stris*(): Rename C-locale APIs with a _c suffix

Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/string/ctype/strisascii.h: Compact definitions
Alejandro Colomar [Fri, 2 Jan 2026 20:40:57 +0000 (21:40 +0100)] 
lib/string/ctype/strisascii.h: Compact definitions

By being closer together, I find them more readable.  The pattern and
the differences are easier to spot.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/string/ctype/strisascii.h: strisprint(): Simplify implementation
Alejandro Colomar [Fri, 2 Jan 2026 20:37:55 +0000 (21:37 +0100)] 
lib/string/ctype/strisascii.h: strisprint(): Simplify implementation

This also makes it consistent with strisdigit().

Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/: Merge directories "lib/string/ctype/*" into unified files
Alejandro Colomar [Fri, 2 Jan 2026 12:57:19 +0000 (13:57 +0100)] 
lib/: Merge directories "lib/string/ctype/*" into unified files

The APIs defined under each of those subdirs are too similar and related
that it makes more sense to define them in the same files.  (BTW, we
only had one API per subdir, except in one subdir that had two APIs, so
in the end, we have almost the same separation.)

Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/, src/: Use isascii_c() functions instead of isascii(3)
Alejandro Colomar [Fri, 2 Jan 2026 20:29:27 +0000 (21:29 +0100)] 
lib/, src/: Use isascii_c() functions instead of isascii(3)

We want to use the C locale.

Reported-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/string/ctype/isascii.[ch]: is*_c(): Add APIs
Alejandro Colomar [Fri, 2 Jan 2026 20:15:24 +0000 (21:15 +0100)] 
lib/string/ctype/isascii.[ch]: is*_c(): Add APIs

These are like the isascii(3) family of APIs, but use the C locale, as
the _c suffix hints.

These macros behave well with non-casted input, unlike isascii(3).

The isascii_c() and iscntrl_c() implementations are different from the
rest because they must return true for '\0'.

Reported-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Cc: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
7 weeks agofix: memory leak: free path/rel in shadowtcb_remove()
Artem Semenov [Mon, 1 Jun 2026 12:57:04 +0000 (15:57 +0300)] 
fix: memory leak: free path/rel in shadowtcb_remove()

In function shadowtcb_remove() (lib/tcbfuncs.c), memory allocated
for 'path' and 'rel' pointers was not released, causing a memory leak.
Added explicit free(path) and free(rel) calls before returning.

Signed-off-by: Artem Semenov <savoptik@altlinux.org>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
7 weeks agolib/, src/, tests/: Use LOGIN_NAME_MAX instead of sysconf(_SC_LOGIN_NAME_MAX)
Alejandro Colomar [Sat, 6 Jun 2026 23:01:37 +0000 (01:01 +0200)] 
lib/, src/, tests/: Use LOGIN_NAME_MAX instead of sysconf(_SC_LOGIN_NAME_MAX)

This provides safer guarantees.  We should be conservative in what we
accept.

Closes: <https://github.com/shadow-maint/shadow/issues/1636>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
8 weeks agoTests: Add two users with same UID using -o flag
aborah-sudo [Wed, 3 Jun 2026 05:39:03 +0000 (11:09 +0530)] 
Tests: Add two users with same UID using -o flag

This is the transformation to Python of the test located in
`tests/usertools/01/04_useradd_add_user_with_existing_UID_with_-o.test`
which checks that `useradd` add two users with same UID using -o flag

2 months agoMerge branch '2026-05-23/alx-sec' into testmaster2
Serge Hallyn [Mon, 25 May 2026 13:17:24 +0000 (08:17 -0500)] 
Merge branch '2026-05-23/alx-sec' into testmaster2

Update SECURITY.md by adding alx@kernel.org, who should have been there
long ago, and retiring Christian.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2 months agoSECURITY.md: Retire Christian Brauner
Serge Hallyn [Mon, 25 May 2026 13:07:59 +0000 (08:07 -0500)] 
SECURITY.md: Retire Christian Brauner

Thanks for your help!

Signed-off-by: Serge Hallyn <serge@hallyn.com>
Cc: Christian Brauner <christian@brauner.io>
2 months agoAdd alx to SECURITY.md
Serge Hallyn [Sat, 23 May 2026 14:41:52 +0000 (09:41 -0500)] 
Add alx to SECURITY.md

While I'm add it, sort by first name for easy finding, and expand
my key fingerprint.  Note (verify) that it has not changed.

Signed-off-by: Serge E. Hallyn <serge@hallyn.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
2 months agolib: apply linux specific pid_t format consistently
Tobias Deiminger [Thu, 7 May 2026 20:47:24 +0000 (22:47 +0200)] 
lib: apply linux specific pid_t format consistently

Also change previously existing linux specific format for pid_t to %d.

Signed-off-by: Tobias Deiminger <tobias.deiminger@linutronix.de>
2 months agoautogen.sh: turn format issues into compiler errors
Tobias Deiminger [Thu, 7 May 2026 19:50:59 +0000 (21:50 +0200)] 
autogen.sh: turn format issues into compiler errors

This protects against undefined behavior from wrongly used conversion
specifiers.

Note: snprintf unit test intentionally uses an empty format string to
test, well, the empt format string. Thus override format-zero-length for
it.

Signed-off-by: Tobias Deiminger <tobias.deiminger@linutronix.de>
fix format error

2 months agolib: simplify check_status and different_namespace interface
Tobias Deiminger [Wed, 6 May 2026 12:39:39 +0000 (14:39 +0200)] 
lib: simplify check_status and different_namespace interface

Change the interface of check_status and different_namespace to take pid
and tid instead of a partially constructed path string.

This is simpler and counters bugs like in the previous commit by design.

Signed-off-by: Tobias Deiminger <tobias.deiminger@linutronix.de>
2 months agouserdel: fix user busy detection for threads
Tobias Deiminger [Wed, 6 May 2026 12:39:39 +0000 (14:39 +0200)] 
userdel: fix user busy detection for threads

On Linux, userdel/usermod check all /proc/<pid> status files to ensure a
to-be-modified user has no more running tasks, or abort modification
otherwise.

However, the check failed to detect threads running as the user if the
corresponding main thread ran as a different user. The user is deleted
despite still being busy. This is due to passing a wrong value to
check_status. The caller passed "<pid>/task", rather than
"<pid>/task/<tid>". In consequence check_status tried to open
"/proc/<pid>/task/status" - a wrong path that never exists - open fails,
and check_status always returns 0. The correct status file name would
have been "/proc/<pid>/task/<tid>/status" instead.

The bug can only be reproduced by rather exotic code using raw syscalls.
POSIX does not allow threads to have different UIDs.

To fix it, construct the correct path to the tid status file in the
caller, before passing it to check_status.

Reproducer:

  // setuid_thread.c

  #include <pthread.h>
  #include <pwd.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <sys/syscall.h>
  #include <unistd.h>

  static uid_t target_uid;

  static void *user_thread(void *arg)
  {
          syscall(SYS_setuid, (long)target_uid);
          for (;;) {
                  printf("thread running as uid %d (pid=%d)\n", (int)target_uid,
                         (int)getpid());
                  sleep(5);
          }
          return NULL;
  }

  int main(int argc, char *argv[])
  {
          if (argc < 2) {
                  fprintf(stderr, "Usage: %s <username>\n", argv[0]);
                  return 1;
          }

          struct passwd *pw = getpwnam(argv[1]);
          if (!pw) {
                  fprintf(stderr, "user not found: %s\n", argv[1]);
                  return 1;
          }
          target_uid = pw->pw_uid;

          pthread_t tid;
          pthread_create(&tid, NULL, user_thread, NULL);
          sleep(60);
          return 0;
  }

Execute in a shell

  gcc setuid_thread.c -o setuid_thread
  sudo useradd --no-create-home testuser
  sudo ./setuid_thread testuser &
  sudo userdel testuser

Behavior without fix:
No output, testuser is deleted.

Behavior with fix:
Output "userdel: user testuser is currently used by process 178863".
testuser is not deleted.

Signed-off-by: Tobias Deiminger <tobias.deiminger@linutronix.de>
2 months agolib/string/README: Document stprintf(,0,)
Alejandro Colomar [Wed, 13 May 2026 13:00:50 +0000 (15:00 +0200)] 
lib/string/README: Document stprintf(,0,)

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 months agolib/salt.c: Use stprintf() instead of snprintf(3)
Alejandro Colomar [Sat, 8 Feb 2025 15:36:26 +0000 (16:36 +0100)] 
lib/salt.c: Use stprintf() instead of snprintf(3)

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 months agolib/string/strcpy/: stpecpy(): Use strtcpy() instead of its pattern
Alejandro Colomar [Mon, 21 Jul 2025 14:56:34 +0000 (16:56 +0200)] 
lib/string/strcpy/: stpecpy(): Use strtcpy() instead of its pattern

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 months agolib/string/: seprintf(), stpecpy(): Add missing const
Alejandro Colomar [Sun, 16 Mar 2025 20:56:25 +0000 (21:56 +0100)] 
lib/string/: seprintf(), stpecpy(): Add missing const

Reported-by: Christopher Bazley <chris.bazley.wg14@gmail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 months agolib/, po/, src/: Rename stpeprintf() => seprintf()
Alejandro Colomar [Mon, 10 Feb 2025 14:06:34 +0000 (15:06 +0100)] 
lib/, po/, src/: Rename stpeprintf() => seprintf()

The old name was too complex, and is inconsistent with all other
sprintf(3)-based APIs having just one letter for differentiation.
This allows breaking less lines.

The original name was chosen for differentiation with the buggy Plan9
API seprint(2).  However, 9front (the current fork where Plan9 is mainly
developed) has acknowledged the bug.  There's still no decision on
fixing the bug or not, due to the age of their code base, and the
projects depending on their library.  It is under consideration
inventing something like a seprint2(2) in 9front for replacement of
seprint(2), but there's no decision yet either.

Considering that 9front acknowledges their bug, and that they *may*
release a fixed API with a similar name, we may as well claim that our
seprintf() is also a fixed version of Plan9's seprint(2).  It has a
different name, after all (we terminate in 'f').

This commit was partially scripted with

$ find * -type f \
| xargs grep -l stpeprintf \
| xargs sed -i 's/stpeprintf/seprintf/g';

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 months agolib/, src/, tests/: Rename snprintf_() => stprintf()
Alejandro Colomar [Sat, 8 Feb 2025 15:30:58 +0000 (16:30 +0100)] 
lib/, src/, tests/: Rename snprintf_() => stprintf()

For consistency with strTcpy(), call it sTprintf().

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 months agolib/string/: Compact documentation
Alejandro Colomar [Mon, 10 Feb 2025 13:49:53 +0000 (14:49 +0100)] 
lib/string/: Compact documentation

In the case of [v]snprintf_(), anticipate the rename in the next commit.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2 months agolib/string/: Redesign stpecpy() and stpeprintf()
Alejandro Colomar [Sat, 8 Feb 2025 13:41:16 +0000 (14:41 +0100)] 
lib/string/: Redesign stpecpy() and stpeprintf()

Make them report truncation via errno and NULL.

Instead of having three possible returns (a pointer to the NUL byte, the
end of the array, or NULL), reduce it to two possible ones: one for
success, and one for error.

Use errno, which is a common way to signal the specific error, and thus
treat truncation as any other error.  This simplifies error handling
after these calls.  Also, if one misuses a pointer after truncation, the
results are better if the pointer is NULL: the program will easily
abort.  If we returned 'end', the program could more easily produce a
buffer overrun.

Suggested-by: Douglas McIlroy <douglas.mcilroy@dartmouth.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>