What were you trying to do that didn't work?
When having a service configured to load credentials, the child process of systemd aborts in assertion because of passing an invalid directory fd (-1 instead of AT_FDCWD):
(gdb) bt
#0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0)
at pthread_kill.c:44
#1 0x00007fae912a15b3 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at pthread_kill.c:78
#2 0x00007fae91254d06 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3 0x00007fae912287f3 in __GI_abort () at abort.c:79
#4 0x00007fae91687da0 in log_assert_failed (text=<optimized out>, file=<optimized out>, line=<optimized out>,
func=<optimized out>) at ../src/basic/log.c:853
#5 0x00007fae917c14e7 in connect_unix_path (fd=4, dir_fd=-1, path=0x556d5cc6bf70 "/run/repro.socket")
at ../src/basic/socket-util.c:1437
#6 0x00007fae91794a02 in read_full_file_full (dir_fd=dir_fd@entry=-1, filename=0x556d5cc6bf70 "/run/repro.socket",
offset=offset@entry=18446744073709551615, size=size@entry=1048576,
flags=flags@entry=(READ_FULL_FILE_SECURE | READ_FULL_FILE_CONNECT_SOCKET | READ_FULL_FILE_FAIL_WHEN_LARGER),
bind_name=<optimized out>, ret_contents=0x7ffd71011e30, ret_size=0x7ffd71011e20) at ../src/basic/fileio.c:798
#7 0x00007fae91aa51f4 in load_credential (context=0x556d5cdc6b98, params=<optimized out>, id=0x556d5cdf6c90 "foo",
path=0x556d5cc6bf70 "/run/repro.socket", encrypted=<optimized out>, unit=<optimized out>, read_dfd=-1,
write_dfd=3, uid=4294967295, ownership_ok=true, left=0x7ffd71011f30) at ../src/core/execute.c:2734
#8 0x00007fae91aa59c3 in acquire_credentials (ownership_ok=true, uid=4294967295, p=<optimized out>,
unit=0x556d5ccd4930 "reproducer.service", params=0x7ffd71012580, context=0x556d5cdc6b98)
at ../src/core/execute.c:2884
:
(gdb) f 5
#5 0x00007fae917c14e7 in connect_unix_path (fd=4, dir_fd=-1, path=0x556d5cc6bf70 "/run/repro.socket")
at ../src/basic/socket-util.c:1437
1437 assert(dir_fd == AT_FDCWD || dir_fd >= 0);
(gdb) p dir_fd
$1 = -1
(gdb) up
#6 0x00007fae91794a02 in read_full_file_full (dir_fd=dir_fd@entry=-1, filename=0x556d5cc6bf70 "/run/repro.socket",
offset=offset@entry=18446744073709551615, size=size@entry=1048576,
flags=flags@entry=(READ_FULL_FILE_SECURE | READ_FULL_FILE_CONNECT_SOCKET | READ_FULL_FILE_FAIL_WHEN_LARGER),
bind_name=<optimized out>, ret_contents=0x7ffd71011e30, ret_size=0x7ffd71011e20) at ../src/basic/fileio.c:798
798 r = connect_unix_path(sk, dir_fd, filename);
(gdb)
#7 0x00007fae91aa51f4 in load_credential (context=0x556d5cdc6b98, params=<optimized out>, id=0x556d5cdf6c90 "foo",
path=0x556d5cc6bf70 "/run/repro.socket", encrypted=<optimized out>, unit=<optimized out>, read_dfd=-1,
write_dfd=3, uid=4294967295, ownership_ok=true, left=0x7ffd71011f30) at ../src/core/execute.c:2734
2734 r = read_full_file_full(
(gdb)
#8 0x00007fae91aa59c3 in acquire_credentials (ownership_ok=true, uid=4294967295, p=<optimized out>,
unit=0x556d5ccd4930 "reproducer.service", params=0x7ffd71012580, context=0x556d5cdc6b98)
at ../src/core/execute.c:2884
2884 r = load_credential(
(gdb) list
2879 return log_debug_errno(errno, "Failed to open '%s': %m", lc->path);
2880 }
2881
2882 if (sub_fd < 0)
2883 /* Regular file (incl. a credential passed in from higher up) */
2884 r = load_credential(
2885 context,
2886 params,
2887 lc->id,
2888 lc->path,
(gdb)
2889 lc->encrypted,
2890 unit,
2891 -1,
2892 dfd,
2893 uid,
2894 ownership_ok,
2895 &left);
2896 else
2897 /* Directory */
2898 r = recurse_dir(
:
Faulty line is 2891, which passes -1.
This got fixed Upstream by the following commit:
commit 661e4251a5b157d1aee1df98fbd2f0c95285ebba
Author: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Tue Dec 13 10:50:01 2022 +0000
execute: Pass AT_FDCWD instead of -1
Let's enforce that callers pass AT_FDCWD as read_dfd to load_credential()
to avoid an assert() in read_full_file_full() if read_dfd is -1.
Please provide the package NVR for which bug is seen:
systemd-252-18.el9
How reproducible:
Always
Steps to reproduce
- Create a dummy service loading credentials from a Unix socket
# cat /etc/systemd/system/reproducer.service [Service] Type=oneshot LoadCredential=foo:/run/repro.socket ExecStart=/bin/true - Start the unix socket
# ncat -l -U /run/repro.socket &
- Set SELinux to Permissive (because of context issues) and start the service
# setenforce 0 # systemctl start reproducer
Expected results
No assertion failure
Actual results
Apr 04 15:20:31 vm-rhel9 systemd[1]: Starting reproducer.service...
Apr 04 15:20:31 vm-rhel9 systemd[39710]: Assertion 'dir_fd == AT_FDCWD || dir_fd >= 0' failed at src/basic/socket-util.c:1437, function connect_unix_path(). Aborting.
- clones
-
RHEL-31783 systemd service child crashes when loading credentials
-
- Closed
-