Commit Graph

568 Commits

Author SHA1 Message Date
Alejandro Colomar
328958ca01 sizeof.h: Move sizeof()-related macros to their own header
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
246edc0481 memzero.h: Remove no-op assignment
memset(3) returns the input pointer.  The assignment was effectively a
no-op, and just confused the code.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
2daa6cc65d memzero.[ch]: Define memzero() and strzero() as inline functions
There's no need to have these as macros, so use functions, which are a
lot safer: there's no need to worry about multiple evaluation of args,
and there's also more type safety.  Compiler warnings are also simpler,
as they don't dump all the nested macros.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
fca2fd65c0 memzero.h: Remove outdated comments
These comments were wrong.  Remove them instead of fixing them, since
now that we have this small header file, it's much easier to follow the
preprocessor conditionals.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
6b11077f09 memzero.h: Move memzero() and strzero() to their own header
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
093fb605f9 lib: Merge libmisc into libshadow
The separation was unnecessary, and caused build problems.  Let's go
wild and obliterate the library.  The files are moved to libshadow.

Scripted change:

$ find libmisc/ -type f \
| grep '\.[chy]$' \
| xargs mv -t lib;

Plus updating the Makefile and other references.  While at it, I've
sorted the sources lists.

Link: <https://github.com/shadow-maint/shadow/pull/792>
Reported-by: David Seifert <soap@gentoo.org>
Cc: Sam James <sam@gentoo.org>
Cc: Christian Bricart <christian@bricart.de>
Cc: Michael Vetter <jubalh@iodoru.org>
Cc: Robert Förster <Dessa@gmake.de>
[ soap tested the Gentoo package ]
Tested-by: David Seifert <soap@gentoo.org>
Acked-by: David Seifert <soap@gentoo.org>
Acked-by: Serge Hallyn <serge@hallyn.com>
Acked-by: Iker Pedrosa <ipedrosa@redhat.com>
Acked-by: <lslebodn@fedoraproject.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-08-31 08:55:26 +02:00
Alejandro Colomar
c34c2606cf lib, libmisc: Move source files to lib (where their headers were)
Scripted change:

$ find lib/ -type f \
| grep '\.h$' \
| sed 's,lib/,libmisc/,' \
| sed 's,\.h$,.c,' \
| xargs find 2>/dev/null \
| xargs mv -t lib/;

Plus updating the Makefiles.

Closes: <https://github.com/shadow-maint/shadow/issues/791>
Closes: <https://bugs.gentoo.org/912446>
Link: <https://github.com/shadow-maint/shadow/issues/763#issuecomment-1664383425>
Link: <https://github.com/shadow-maint/shadow/pull/776>
Link: <d0518cc250>
Reported-by: Christian Bricart <christian@bricart.de>
Reported-by: Robert Marmorstein <robert@marmorstein.org>
Cc: Sam James <sam@gentoo.org>
[ jubalh tested the openSUSE package ]
Tested-by: Michael Vetter <jubalh@iodoru.org>
Acked-by: Michael Vetter <jubalh@iodoru.org>
[ Robert F. tested the Gentoo package ]
Tested-by: Robert Förster <Dessa@gmake.de>
Cc: David Seifert <soap@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-08-30 17:22:38 +02:00
Christian Göttsche
f76c31f50e Avoid usage of sprintf
sprintf(3) does not take the destination buffer into account. Although
the destination in these case is large enough, sprintf(3) indicates a
code smell.

Use snprintf(3).
2023-08-21 16:04:09 -05:00
Christian Göttsche
e0d3ba6934 commonio: check for path truncations
Bail out if the paths generated for the backup and replacement database
are truncated.
2023-08-21 15:56:44 -05:00
Christian Göttsche
a08021eb0e lib/commonio: drop dead store
commonio.c:522:15: warning: Although the value stored to 'cp' is used in the enclosing expression, the value is never actually read from 'cp' [deadcode.DeadStores]

Reviewed-by: Alejandro Colomar <alx@kernel.org>
2023-08-21 14:05:27 -05:00
Christian Göttsche
15f4421f10 lib: avoid dropping const qualifier during cast
subordinateio.c:360:20: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      360 |         range1 = (*(struct commonio_entry **) p1)->eptr;
          |                    ^
    subordinateio.c:364:20: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      364 |         range2 = (*(struct commonio_entry **) p2)->eptr;
          |                    ^

    groupio.c:215:15: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      215 |         if ((*(struct commonio_entry **) p1)->eptr == NULL) {
          |               ^
    groupio.c:218:15: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      218 |         if ((*(struct commonio_entry **) p2)->eptr == NULL) {
          |               ^
    groupio.c:222:34: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      222 |         u1 = ((struct group *) (*(struct commonio_entry **) p1)->eptr)->gr_gid;
          |                                  ^
    groupio.c:223:34: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      223 |         u2 = ((struct group *) (*(struct commonio_entry **) p2)->eptr)->gr_gid;
          |                                  ^

    pwio.c:187:15: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      187 |         if ((*(struct commonio_entry **) p1)->eptr == NULL)
          |               ^
    pwio.c:189:15: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      189 |         if ((*(struct commonio_entry **) p2)->eptr == NULL)
          |               ^
    pwio.c:192:35: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      192 |         u1 = ((struct passwd *) (*(struct commonio_entry **) p1)->eptr)->pw_uid;
          |                                   ^
    pwio.c:193:35: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      193 |         u2 = ((struct passwd *) (*(struct commonio_entry **) p2)->eptr)->pw_uid;
          |                                   ^

Reviewed-by: Alejandro Colomar <alx@kernel.org>
2023-08-21 13:54:27 -05:00
Christian Göttsche
1aaa4ec5ba lib/tcbfuncs: operate on file descriptor rather than path 2023-08-21 11:29:17 +02:00
Alejandro Colomar
f45498a6c2 libmisc/write_full.c: Improve write_full()
Documentation:

-  Correct the comment documenting the function:

   write_full() doesn't write "up to" count bytes (which is write(2)'s
   behavior, and exactly what this function is designed to avoid), but
   rather exactly count bytes (on success).

-  While fixing the documentation, take the time to add a man-page-like
   comment as in other APIs.  Especially, since we'll have to document
   a few other changes from this patch, such as the modified return
   values.

-  Partial writes are still possible on error.  It's the caller's
   responsibility to handle that possibility.

API:

-  In write(2), it's useful to know how many bytes were transferred,
   since it can have short writes.  In this API, since it either writes
   it all or fails, that value is useless, and callers only want to know
   if it succeeded or not.  Thus, just return 0 or -1.

Implementation:

-  Use `== -1` instead of `< 0` to check for write(2) syscall errors.
   This is wisdom from Michael Kerrisk.  This convention is useful
   because it more explicitly tells maintainers that the only value
   which can lead to that path is -1.  Otherwise, a maintainer of the
   code might be confused to think that other negative values are
   possible.  Keep it simple.

-  The path under `if (res == 0)` was unreachable, since the loop
   condition `while (count > 0)` precludes that possibility.  Remove the
   dead code.

-  Use a temporary variable of type `const char *` to avoid a cast.

-  Rename `res`, which just holds the result from write(2), to `w`,
   which more clearly shows that it's just a very-short-lived variable
   (by it's one-letter name), and also relates itself more to write(2).
   I find it more readable.

-  Move the definition of `w` to the top of the function.  Now that the
   function is significantly shorter, the lifetime of the variable is
   clearer, and I find it more readable this way.

Use:

-  Also use `== -1` to check errors.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-08-18 20:35:15 -05:00
Christian Göttsche
969549fdf0 Add wrapper for write(2)
write(2) may not write the complete given buffer.  Add a wrapper to
avoid short writes.
2023-08-04 17:15:42 -05:00
Iker Pedrosa
3b7cc05387 lib: replace USER_NAME_MAX_LENGTH macro
Replace it by `sysconf(_SC_LOGIN_NAME_MAX)`, which is the maximum
username length supported by the kernel.

Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
ede0665a5a libmisc: implement active_sessions_count()
Implement `active_sessions_count()` in `utmp.c` and `logind.c`.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
1f368e1c18 utmp: update update_utmp()
Remove `utmp` structure as an argument and include its logic inside the
function. This will help remove any reference to utmp from login.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
6b7108e347 utmp: move update_utmp
The functionality from this function is related to utmp. Restrict access
to `setutmp()` to the same file.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
b6ca83ea4c utmp: move failtmp()
The functionality from this function is related to btmp.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
f40bdfa66a libmisc: implement get_session_host()
Implement `get_session_host()` in `utmp.c` and `logind.c`.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
84a10ca019 login: conditionally build lastlog functionality
Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-07-15 07:39:53 -05:00
Jaroslav Jindrak
cc0aaaa18f configure: check whether fgetpwent_r is available before marking xprefix_getpwnam_r as reentrant 2023-06-09 16:22:24 +02:00
Jaroslav Jindrak
68bf73f319 passwd: fall back to non-PAM code when prefix is used
Prefix does not make sense when we use PAM, so when the option
is used behave as if --with-libpam=no was used to configure the
project.
2023-06-09 16:22:24 +02:00
Jaroslav Jindrak
43e60eb681 passwd: Respect --prefix/-P options
Add prefix_getpwnam_r() and xprefix_getpwnam() and make passwd
use prefix-aware functions when handling the database.
2023-06-09 16:22:24 +02:00
Alejandro Colomar
787ea57a18 Use temporary variable
-  Use the temporary variable more, as it helps readability: it removes
   a derefecence, which itself allows removing some parentheses.

-  Use a shorter name, which is more common with temporaries, and so
   there's less to read.

-  Assign to *ranges at the end of the function.  It's the same, but
   with the other changes, I think this makes it slightly clearer.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-08 09:05:39 -05:00
Alejandro Colomar
f2ac1e2540 realloc(NULL, ...) is equivalent to malloc(...)
Don't have a branch for when the old pointer is NULL.  realloc(3) can
handle that case just fine.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-08 09:05:39 -05:00
Alejandro Colomar
09775d3718 Simplify allocation APIs
If we consider simple objects as arrays of size 1, we can considerably
simplify these APIs, merging the *ARRAY and the non-array variants.

That will produce more readable code, since lines will be shorter (by
not having ARRAY in the macro names, as all macros will consistently
handle arrays), and the allocated size will be also more explicit.

The syntax will now be of the form:

    p = MALLOC(42, foo_t);  // allocate 42 elements of type foo_t.
    p = MALLOC(1, bar_t);   // allocate 1 element of type foo_t.

The _array() allocation functions should _never_ be called directly, and
instead these macros should be used.

The non-array functions (e.g., malloc(3)) still have their place, but
are limited to allocating structures with flexible array members.  For
any other uses, the macros should be used.

Thus, we don't use any array or ARRAY variants in any code any more, and
they are only used as implementation details of these macros.

Link: <https://software.codidact.com/posts/285898/288023#answer-288023>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-08 09:05:39 -05:00
Christian Göttsche
065a752b42 Drop alloca(3)
alloca(3) fails silently if not enough memory can be allocated on the
stack.  Use checked dynamic allocation instead.

Also drop unnecessary manual NUL assignment, ensured by snprintf(3).

Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-08 09:05:39 -05:00
Alejandro Colomar
70399856c1 lib/nss.c: Fix use of invalid p
getline(3) might have succeeded in a previous iteration, in which case
p points to an offset that is not valid.  Make p NULL at the end of the
loop, to make sure it doesn't hold old stuff.

Link: <https://github.com/shadow-maint/shadow/pull/737#issuecomment-1568948769>
Reported-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Alejandro Colomar
848a95329c lib/nss.c: Fix use of uninitialized p
getline(3) might have never succeeded, in which case p is uninitialized
when used in strtok_r(3).

Link: <https://github.com/shadow-maint/shadow/pull/737#discussion_r1206007358>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Alejandro Colomar
54ba4814ae Centralize error handling
This makes the function fit in less screens.  This is to avoid consuming
more natural resources than we have available, and everyone knows the
supply of new-lines on a screen is not a renewable source[1].

Some transformations have been done thanks to free(NULL) being an alias
for loopity_loop(), as defined three comits ago.  The real definition of
free(3) that everyone has been hiding is this:

void
free(void *p)
{
	if (p == NULL)
		loopity_loop();
	else
		real_free(p);
}

Link: [1] <https://www.kernel.org/doc/html/v6.3/process/coding-style.html#placing-braces-and-spaces>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Alejandro Colomar
07b885318f Second verse, it gets worse; it gets no better than this
Just in case it's not obious:

	strlen("") < 8
	isalpha('\0') == false
	isdigit('\0') == false
	isspace('\0') == false

Link: <https://github.com/shadow-maint/shadow/pull/737>
Easter-egg: 8492dee663 ("subids: support nsswitch")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Alejandro Colomar
2f9ca4b49d ROFL: Rolling on the floor looping
Please tell me this was an easter egg :P

 #define go_banana() ({ goto nowhere; nowhere: 0-0; })

Closes: <https://github.com/shadow-maint/shadow/issues/736>
Easter-egg: 8492dee663 ("subids: support nsswitch")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Alejandro Colomar
8219fbd421 This ain't no loop
This was to a loop, as "1234" is to computer security.

No really; a loop that ends in a (forward) goto, and has no continue in it.

Still want a loop?  Take two:

 #define loopity_loop() do { for (;;) { break; } continue; } while (0-0)

Closes: <https://github.com/shadow-maint/shadow/issues/736>
Easter-egg: 8492dee663 ("subids: support nsswitch")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Serge Hallyn
a80b792afc sub_[ug]id_{add,remove}: fix return values
On failure, these are meant to return 0 with errno set.  But if
an nss module is loaded, they were returning -ERRNO instead.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-05-26 15:16:29 -05:00
Serge Hallyn
419cf1f1c4 def_load: avoid NULL deref
If econf_getStringValue() fails, it will return an error and
set value to NULL.  Look for the error and avoid dereferencing
value in that case.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-05-22 10:23:12 +02:00
Serge Hallyn
9e854f525d def_load: split the econf from non-econf definition
The function is completely different based on USE_CONF.  Either copy
will be easier to read if we just keep them completely separate.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-05-22 10:23:12 +02:00
Tobias Stoeckmann
8175b1532e Plug econf memory leaks
You can see the memory leaks with address sanitizer if shadow is
compiled with `--enable-vendordir=/usr/etc`.

How to reproduce:

1. Prepare a custom shell file as root
```
mkdir -p /etc/shells.d
echo /bin/myshell > /etc/shells.d/custom
```

2. Run chsh as regular user
```
chsh
```

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2023-05-19 08:02:24 -05:00
Samanta Navarro
4ef4477535 get_pid.c: Use tighter validation checks
Neither a pid_t below 1 nor a negative fd could be valid in this context.

Proof of Concept:

$ newuidmap -1 1 1 1
newuidmap: Could not open proc directory for target 4294967295

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-15 09:21:16 +02:00
Samanta Navarro
72290ede0e commonio: Use do_lock_file again
This avoids regressions introduced with do_fcntl_lock.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-11 10:59:21 -05:00
ed neville
0bce9c9808 open with O_CREAT when lock path does not exist
Reported in #686, by wyj611 when trying to lock a file that is not
present

Lock method should be F_SETLKW rather than open file descriptor
2023-05-08 08:16:11 -05:00
Samanta Navarro
627631bf9a commonio_open: Remove fcntl call
The fcntl call to set FD_CLOEXEC can be performed directly with the
previously performed open call by using the O_CLOEXEC flag.

O_CLOEXEC is required by POSIX.1-2008.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-05 16:15:46 +02:00
Samanta Navarro
e899e3d745 commonio_lock_nowait: Remove deprecated code
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-05 16:15:46 +02:00
Samanta Navarro
7109b7c066 login_prompt: Simplify login_prompt API
The only user of login_prompt is the login tool. This implies that the
first argument is always the same.

It is much easier to verify printf's format string and its argument if
both are next to each other.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-03 07:54:28 -05:00
Christian Göttsche
7078ed1e0b semanage: disconnect to free libsemanage internals
Destroying the handle does not actually disconnect, see [1].
Also free the key on user removal.

[1]: e9072e7d45/libsemanage/src/direct_api.c (L330)

Example adduser leak:

    Direct leak of 1008 byte(s) in 14 object(s) allocated from:
        #0 0x5638f2e782ae in __interceptor_malloc (./src/useradd+0xee2ae)
        #1 0x7fb5cfffad09 in dbase_file_init src/database_file.c:170:45

    Direct leak of 392 byte(s) in 7 object(s) allocated from:
        #0 0x5638f2e782ae in __interceptor_malloc (./src/useradd+0xee2ae)
        #1 0x7fb5cfffc929 in dbase_policydb_init src/database_policydb.c:187:27

    Direct leak of 144 byte(s) in 2 object(s) allocated from:
        #0 0x5638f2e782ae in __interceptor_malloc (./src/useradd+0xee2ae)
        #1 0x7fb5cfffb519 in dbase_join_init src/database_join.c:249:28

    [...]
2023-04-26 17:52:54 -05:00
Christian Göttsche
a8dd8ce6c9 commonio: free removed database entries
Free the actual struct of the removed entry.

Example userdel report:

    Direct leak of 40 byte(s) in 1 object(s) allocated from:
        #0 0x55b230efe857 in reallocarray (./src/userdel+0xda857)
        #1 0x55b230f6041f in mallocarray ./lib/./alloc.h:97:9
        #2 0x55b230f6041f in commonio_open ./lib/commonio.c:563:7
        #3 0x55b230f39098 in open_files ./src/userdel.c:555:6
        #4 0x55b230f39098 in main ./src/userdel.c:1189:2
        #5 0x7f9b48c64189 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
2023-04-26 17:52:54 -05:00
Christian Göttsche
c80788a3ac useradd/usermod: add --selinux-range argument
Add a command line argument to useradd(8) and usermod(8) to specify the
MLS range for a SELinux user mapping.

Improves: #676
2023-04-19 09:19:19 +02:00
Christian Göttsche
2eee4c67f5 sssd: skip flushing if executable does not exist
Avoid unnecessary syslog output, like:

    Apr 01 13:35:09 dlaptop userdel[45872]: userdel: sss_cache exited with status 1
    Apr 01 13:35:09 dlaptop userdel[45872]: userdel: Failed to flush the sssd cache.
2023-04-03 13:05:30 +02:00
Christian Göttsche
2eaea70111 Overhaul valid_field()
e5905c4b ("Added control character check") introduced checking for
control characters but had the logic inverted, so it rejects all
characters that are not control ones.

Cast the character to `unsigned char` before passing to the character
checking functions to avoid UB.

Use strpbrk(3) for the illegal character test and return early.
2023-03-31 09:53:40 -05:00
Martin Kletzander
a5f9ef8b7f semanage: Do not set default SELinux range
Both semanage and libsemanage actually set the user's mls range to the
default of the seuser, which makes more sense and removes a bit of code
for usermod and useradd.  More fine-grained details must always be set
with some other tool
(semanage) anyway.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2023-03-31 16:13:02 +02:00