• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 22810165351

07 Mar 2026 03:22PM UTC coverage: 72.6% (-0.03%) from 72.63%
22810165351

push

github

web-flow
user-record: fix segfault when processing matchHostname field (#40979)

Fix a typo which causes a segfault when processing a user record
with `matchHostname` when it's an array instead of a simple string:

```
$ echo '{"userName":"crashhostarray","perMachine":[{"matchHostname":["host1","host2"],"locked":false}]}' | userdbctl -F -
Segmentation fault         (core dumped)

$ coredumpctl info
...
       Message: Process 1172301 (userdbctl) of user 1000 dumped core.

                Module libz.so.1 from rpm zlib-ng-2.3.3-1.fc43.x86_64
                Module libcrypto.so.3 from rpm openssl-3.5.4-2.fc43.x86_64
                Stack trace of thread 1172301:
                #0  0x00007fded7b3a656 __strcmp_evex (libc.so.6 + 0x159656)
                #1  0x00007fded7e95397 per_machine_hostname_match (libsystemd-shared-260.so + 0x295397)
                #2  0x00007fded7e955b5 per_machine_match (libsystemd-shared-260.so + 0x2955b5)
                #3  0x00007fded7e957c6 dispatch_per_machine (libsystemd-shared-260.so + 0x2957c6)
                #4  0x00007fded7e96c97 user_record_load (libsystemd-shared-260.so + 0x296c97)
                #5  0x000000000040572d display_user (/home/fsumsal/repos/@systemd/systemd/build/userdbctl + 0x572d)
                #6  0x00007fded7ea9727 dispatch_verb (libsystemd-shared-260.so + 0x2a9727)
                #7  0x000000000041077c run (/home/fsumsal/repos/@systemd/systemd/build/userdbctl + 0x1077c)
                #8  0x00000000004107ce main (/home/fsumsal/repos/@systemd/systemd/build/userdbctl + 0x107ce)
                #9  0x00007fded79e45b5 __libc_start_call_main (libc.so.6 + 0x35b5)
                #10 0x00007fded79e4668 __libc_start_main@@GLIBC_2.34 (libc.so.6 + 0x3668)
                #11 0x00000000004038d5 _start (/home/fsumsal/repos/@systemd/systemd/build/userdbctl + 0x38d5)
                ELF object binary architecture: AMD x86-64
```

5 of 35 new or added lines in 2 files covered. (14.29%)

340 existing lines in 46 files now uncovered.

316214 of 435555 relevant lines covered (72.6%)

1144732.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.4
/src/shared/journal-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <unistd.h>
4

5
#include "sd-bus.h"
6
#include "sd-journal.h"
7

8
#include "acl-util.h"
9
#include "alloc-util.h"
10
#include "bus-error.h"
11
#include "bus-locator.h"
12
#include "bus-util.h"
13
#include "fd-util.h"
14
#include "fs-util.h"
15
#include "hashmap.h"
16
#include "journal-internal.h"
17
#include "journal-util.h"
18
#include "log.h"
19
#include "strv.h"
20
#include "user-util.h"
21

22
static int access_check_var_log_journal(sd_journal *j, bool want_other_users) {
11✔
23
        int r;
11✔
24

25
        assert(j);
11✔
26

27
        /* If we are root, we should have access, don't warn. */
28
        if (getuid() == 0)
11✔
29
                return 0;
11✔
30

31
        /* If we are in the 'systemd-journal' group, we should have
32
         * access too. */
33
        r = in_group("systemd-journal");
11✔
34
        if (r < 0)
11✔
35
                return log_error_errno(r, "Failed to check if we are in the 'systemd-journal' group: %m");
×
36
        if (r > 0)
11✔
37
                return 0;
38

39
#if HAVE_ACL
40
        _cleanup_strv_free_ char **g = NULL;
11✔
41
        const char* dir;
11✔
42

43
        if (access_nofollow("/run/log/journal", F_OK) >= 0)
11✔
44
                dir = "/run/log/journal";
45
        else
46
                dir = "/var/log/journal";
×
47

48
        /* If we are in any of the groups listed in the journal ACLs,
49
         * then all is good, too. Let's enumerate all groups from the
50
         * default ACL of the directory, which generally should allow
51
         * access to most journal files too. */
52
        r = acl_search_groups(dir, &g);
11✔
53
        if (r < 0)
11✔
54
                return log_error_errno(r, "Failed to search journal ACL: %m");
×
55
        if (r > 0)
11✔
56
                return 0;
57

58
        /* Print a pretty list, if there were ACLs set. */
59
        if (!strv_isempty(g)) {
11✔
60
                _cleanup_free_ char *s = NULL;
11✔
61

62
                /* There are groups in the ACL, let's list them */
63
                r = strv_extend(&g, "systemd-journal");
11✔
64
                if (r < 0)
11✔
65
                        return log_oom();
×
66

67
                strv_sort_uniq(g);
11✔
68

69
                s = strv_join(g, "', '");
11✔
70
                if (!s)
11✔
71
                        return log_oom();
×
72

73
                log_notice("Hint: You are currently not seeing messages from %s.\n"
11✔
74
                           "      Users in groups '%s' can see all messages.\n"
75
                           "      Pass -q to turn off this notice.",
76
                           want_other_users ? "other users and the system" : "the system",
77
                           s);
78
                return 1;
11✔
79
        }
80
#endif
81

82
        /* If no ACLs were found, print a short version of the message. */
83
        log_notice("Hint: You are currently not seeing messages from %s.\n"
×
84
                   "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
85
                   "      turn off this notice.",
86
                   want_other_users ? "other users and the system" : "the system");
87

88
        return 1;
89
}
90

91
int journal_access_blocked(sd_journal *j) {
20✔
92
        return hashmap_contains(j->errors, INT_TO_PTR(-EACCES));
20✔
93
}
94

95
int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_users) {
2,240✔
96
        void *code;
2,240✔
97
        char *path;
2,240✔
98
        int r = 0;
2,240✔
99

100
        assert(j);
2,240✔
101

102
        if (hashmap_isempty(j->errors)) {
2,240✔
103
                if (ordered_hashmap_isempty(j->files) && !quiet)
2,220✔
UNCOV
104
                        log_notice("No journal files were found.");
×
105

106
                return 0;
2,220✔
107
        }
108

109
        if (journal_access_blocked(j)) {
20✔
110
                if (!quiet)
11✔
111
                        (void) access_check_var_log_journal(j, want_other_users);
11✔
112

113
                if (ordered_hashmap_isempty(j->files))
11✔
114
                        r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions.");
×
115
        }
116

117
        HASHMAP_FOREACH_KEY(path, code, j->errors) {
74✔
118
                int err;
34✔
119

120
                err = ABS(PTR_TO_INT(code));
34✔
121

122
                switch (err) {
34✔
123
                case EACCES:
11✔
124
                        continue;
11✔
125

126
                case ENODATA:
127
                        log_warning_errno(err, "Journal file %s is truncated, ignoring file.", path);
6✔
128
                        break;
129

130
                case EPROTONOSUPPORT:
131
                        log_warning_errno(err, "Journal file %1$s uses an unsupported feature, ignoring file.\n"
6✔
132
                                               "Use SYSTEMD_LOG_LEVEL=debug journalctl --file=%1$s to see the details.",
133
                                               path);
134
                        break;
135

136
                case EBADMSG:
137
                        log_warning_errno(err, "Journal file %s corrupted, ignoring file.", path);
6✔
138
                        break;
139

140
                case ETOOMANYREFS:
141
                        log_warning_errno(err, "Too many journal files (limit is at %u) in scope, ignoring file '%s'.", JOURNAL_FILES_MAX, path);
×
142
                        break;
143

144
                default:
145
                        log_warning_errno(err, "An error was encountered while opening journal file or directory %s, ignoring file: %m", path);
59✔
146
                }
147
        }
148

149
        return r;
20✔
150
}
151

152
int journal_open_machine(sd_journal **ret, const char *machine, int flags) {
1✔
153
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
×
154
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1✔
155
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
1✔
156
        _cleanup_(sd_journal_closep) sd_journal *j = NULL;
1✔
157
        _cleanup_close_ int machine_fd = -EBADF;
1✔
158
        int fd, r;
1✔
159

160
        assert(ret);
1✔
161
        assert(machine);
1✔
162

163
        if (geteuid() != 0)
1✔
164
                /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
165
                 * the container, thus we need root privileges to override them. */
166
                return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Using the --machine= switch requires root privileges.");
×
167

168
        r = sd_bus_open_system(&bus);
1✔
169
        if (r < 0)
1✔
170
                return log_error_errno(r, "Failed to open system bus: %m");
×
171

172
        r = bus_call_method(bus, bus_machine_mgr, "OpenMachineRootDirectory", &error, &reply, "s", machine);
1✔
173
        if (r < 0)
1✔
174
                return log_error_errno(r, "Failed to open root directory of machine '%s': %s",
×
175
                                       machine, bus_error_message(&error, r));
176

177
        r = sd_bus_message_read(reply, "h", &fd);
1✔
178
        if (r < 0)
1✔
179
                return bus_log_parse_error(r);
×
180

181
        machine_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1✔
182
        if (machine_fd < 0)
1✔
183
                return log_error_errno(errno, "Failed to duplicate file descriptor: %m");
×
184

185
        r = sd_journal_open_directory_fd(&j, machine_fd, SD_JOURNAL_OS_ROOT | SD_JOURNAL_TAKE_DIRECTORY_FD | flags);
1✔
186
        if (r < 0)
1✔
187
                return log_error_errno(r, "Failed to open journal in machine '%s': %m", machine);
×
188

189
        TAKE_FD(machine_fd);
1✔
190
        *ret = TAKE_PTR(j);
1✔
191
        return 0;
1✔
192
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc