Bug Summary

File:build-scan/../src/shared/ask-password-api.c
Warning:line 720, column 17
Potential leak of memory pointed to by 'socket_name'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ask-password-api.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/shared/libsystemd-shared-239.a.p -I src/shared -I ../src/shared -I src/basic -I ../src/basic -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I /usr/include/blkid -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility default -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/shared/ask-password-api.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <fcntl.h>
5#include <inttypes.h>
6#include <limits.h>
7#include <poll.h>
8#include <signal.h>
9#include <stdbool.h>
10#include <stddef.h>
11#include <stdint.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/inotify.h>
16#include <sys/signalfd.h>
17#include <sys/socket.h>
18#include <sys/stat.h>
19#include <sys/time.h>
20#include <sys/uio.h>
21#include <sys/un.h>
22#include <termios.h>
23#include <unistd.h>
24
25#include "alloc-util.h"
26#include "ask-password-api.h"
27#include "fd-util.h"
28#include "fileio.h"
29#include "format-util.h"
30#include "io-util.h"
31#include "log.h"
32#include "macro.h"
33#include "missing.h"
34#include "mkdir.h"
35#include "process-util.h"
36#include "random-util.h"
37#include "signal-util.h"
38#include "socket-util.h"
39#include "string-util.h"
40#include "strv.h"
41#include "terminal-util.h"
42#include "time-util.h"
43#include "umask-util.h"
44#include "utf8.h"
45#include "util.h"
46
47#define KEYRING_TIMEOUT_USEC((5 * ((usec_t) (60ULL*((usec_t) 1000000ULL)))) / 2) ((5 * USEC_PER_MINUTE((usec_t) (60ULL*((usec_t) 1000000ULL)))) / 2)
48
49static int lookup_key(const char *keyname, key_serial_t *ret) {
50 key_serial_t serial;
51
52 assert(keyname)do { if ((__builtin_expect(!!(!(keyname)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("keyname"), "../src/shared/ask-password-api.c"
, 52, __PRETTY_FUNCTION__); } while (0)
;
53 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/shared/ask-password-api.c"
, 53, __PRETTY_FUNCTION__); } while (0)
;
54
55 serial = request_keymissing_request_key("user", keyname, NULL((void*)0), 0);
56 if (serial == -1)
57 return negative_errno();
58
59 *ret = serial;
60 return 0;
61}
62
63static int retrieve_key(key_serial_t serial, char ***ret) {
64 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
65 long m = 100, n;
66 char **l;
67
68 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/shared/ask-password-api.c"
, 68, __PRETTY_FUNCTION__); } while (0)
;
69
70 for (;;) {
71 p = new(char, m)((char*) malloc_multiply(sizeof(char), (m)));
72 if (!p)
73 return -ENOMEM12;
74
75 n = keyctlmissing_keyctl(KEYCTL_READ11, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0);
76 if (n < 0)
77 return -errno(*__errno_location ());
78
79 if (n < m)
80 break;
81
82 explicit_bzero(p, m);
83 free(p);
84 m *= 2;
85 }
86
87 l = strv_parse_nulstr(p, n);
88 if (!l)
89 return -ENOMEM12;
90
91 explicit_bzero(p, n);
92
93 *ret = l;
94 return 0;
95}
96
97static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **passwords) {
98 _cleanup_strv_free_erase___attribute__((cleanup(strv_free_erasep))) char **l = NULL((void*)0);
99 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
100 key_serial_t serial;
101 size_t n;
102 int r;
103
104 assert(keyname)do { if ((__builtin_expect(!!(!(keyname)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("keyname"), "../src/shared/ask-password-api.c"
, 104, __PRETTY_FUNCTION__); } while (0)
;
105 assert(passwords)do { if ((__builtin_expect(!!(!(passwords)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("passwords"), "../src/shared/ask-password-api.c"
, 105, __PRETTY_FUNCTION__); } while (0)
;
106
107 if (!(flags & ASK_PASSWORD_PUSH_CACHE))
108 return 0;
109
110 r = lookup_key(keyname, &serial);
111 if (r >= 0) {
112 r = retrieve_key(serial, &l);
113 if (r < 0)
114 return r;
115 } else if (r != -ENOKEY126)
116 return r;
117
118 r = strv_extend_strv(&l, passwords, true1);
119 if (r <= 0)
120 return r;
121
122 r = strv_make_nulstr(l, &p, &n);
123 if (r < 0)
124 return r;
125
126 serial = add_keymissing_add_key("user", keyname, p, n, KEY_SPEC_USER_KEYRING-4);
127 explicit_bzero(p, n);
128 if (serial == -1)
129 return -errno(*__errno_location ());
130
131 if (keyctlmissing_keyctl(KEYCTL_SET_TIMEOUT15,
132 (unsigned long) serial,
133 (unsigned long) DIV_ROUND_UP(KEYRING_TIMEOUT_USEC, USEC_PER_SEC)({ const typeof((((5 * ((usec_t) (60ULL*((usec_t) 1000000ULL)
))) / 2))) __unique_prefix_X35 = ((((5 * ((usec_t) (60ULL*((usec_t
) 1000000ULL)))) / 2))); const typeof((((usec_t) 1000000ULL))
) __unique_prefix_Y36 = ((((usec_t) 1000000ULL))); (__unique_prefix_X35
/ __unique_prefix_Y36 + !!(__unique_prefix_X35 % __unique_prefix_Y36
)); })
, 0, 0) < 0)
134 log_debug_errno(errno, "Failed to adjust timeout: %m")({ int _level = ((7)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/shared/ask-password-api.c", 134,
__func__, "Failed to adjust timeout: %m") : -abs(_e); })
;
135
136 log_debug("Added key to keyring as %" PRIi32 ".", serial)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/ask-password-api.c", 136, __func__, "Added key to keyring as %"
"i" ".", serial) : -abs(_e); })
;
137
138 return 1;
139}
140
141static int add_to_keyring_and_log(const char *keyname, AskPasswordFlags flags, char **passwords) {
142 int r;
143
144 assert(keyname)do { if ((__builtin_expect(!!(!(keyname)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("keyname"), "../src/shared/ask-password-api.c"
, 144, __PRETTY_FUNCTION__); } while (0)
;
145 assert(passwords)do { if ((__builtin_expect(!!(!(passwords)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("passwords"), "../src/shared/ask-password-api.c"
, 145, __PRETTY_FUNCTION__); } while (0)
;
146
147 r = add_to_keyring(keyname, flags, passwords);
148 if (r < 0)
149 return log_debug_errno(r, "Failed to add password to keyring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/ask-password-api.c", 149, __func__, "Failed to add password to keyring: %m"
) : -abs(_e); })
;
150
151 return 0;
152}
153
154int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret) {
155
156 key_serial_t serial;
157 int r;
158
159 assert(keyname)do { if ((__builtin_expect(!!(!(keyname)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("keyname"), "../src/shared/ask-password-api.c"
, 159, __PRETTY_FUNCTION__); } while (0)
;
160 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/shared/ask-password-api.c"
, 160, __PRETTY_FUNCTION__); } while (0)
;
161
162 if (!(flags & ASK_PASSWORD_ACCEPT_CACHED))
163 return -EUNATCH49;
164
165 r = lookup_key(keyname, &serial);
166 if (r == -ENOSYS38) /* when retrieving the distinction doesn't matter */
167 return -ENOKEY126;
168 if (r < 0)
169 return r;
170
171 return retrieve_key(serial, ret);
172}
173
174static void backspace_chars(int ttyfd, size_t p) {
175
176 if (ttyfd < 0)
177 return;
178
179 while (p > 0) {
180 p--;
181
182 loop_write(ttyfd, "\b \b", 3, false0);
183 }
184}
185
186static void backspace_string(int ttyfd, const char *str) {
187 size_t m;
188
189 assert(str)do { if ((__builtin_expect(!!(!(str)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("str"), "../src/shared/ask-password-api.c"
, 189, __PRETTY_FUNCTION__); } while (0)
;
190
191 if (ttyfd < 0)
192 return;
193
194 /* Backspaces through enough characters to entirely undo printing of the specified string. */
195
196 m = utf8_n_codepoints(str);
197 if (m == (size_t) -1)
198 m = strlen(str); /* Not a valid UTF-8 string? If so, let's backspace the number of bytes output. Most
199 * likely this happened because we are not in an UTF-8 locale, and in that case that
200 * is the correct thing to do. And even if it's not, terminals tend to stop
201 * backspacing at the leftmost column, hence backspacing too much should be mostly
202 * OK. */
203
204 backspace_chars(ttyfd, m);
205}
206
207int ask_password_tty(
208 int ttyfd,
209 const char *message,
210 const char *keyname,
211 usec_t until,
212 AskPasswordFlags flags,
213 const char *flag_file,
214 char **ret) {
215
216 enum {
217 POLL_TTY,
218 POLL_INOTIFY,
219 _POLL_MAX,
220 };
221
222 bool_Bool reset_tty = false0, dirty = false0, use_color = false0;
223 _cleanup_close___attribute__((cleanup(closep))) int cttyfd = -1, notify = -1;
224 struct termios old_termios, new_termios;
225 char passphrase[LINE_MAX2048 + 1] = {}, *x;
226 struct pollfd pollfd[_POLL_MAX];
227 size_t p = 0, codepoint = 0;
228 int r;
229
230 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/shared/ask-password-api.c"
, 230, __PRETTY_FUNCTION__); } while (0)
;
231
232 if (flags & ASK_PASSWORD_NO_TTY)
233 return -EUNATCH49;
234
235 if (!message)
236 message = "Password:";
237
238 if (flag_file) {
239 notify = inotify_init1(IN_CLOEXECIN_CLOEXEC|IN_NONBLOCKIN_NONBLOCK);
240 if (notify < 0)
241 return -errno(*__errno_location ());
242
243 if (inotify_add_watch(notify, flag_file, IN_ATTRIB0x00000004 /* for the link count */) < 0)
244 return -errno(*__errno_location ());
245 }
246
247 /* If the caller didn't specify a TTY, then use the controlling tty, if we can. */
248 if (ttyfd < 0)
249 ttyfd = cttyfd = open("/dev/tty", O_RDWR02|O_NOCTTY0400|O_CLOEXEC02000000);
250
251 if (ttyfd >= 0) {
252 if (tcgetattr(ttyfd, &old_termios) < 0)
253 return -errno(*__errno_location ());
254
255 if (flags & ASK_PASSWORD_CONSOLE_COLOR)
256 use_color = dev_console_colors_enabled();
257 else
258 use_color = colors_enabled();
259
260 if (use_color)
261 (void) loop_write(ttyfd, ANSI_HIGHLIGHT"\x1B[0;1;39m", STRLEN(ANSI_HIGHLIGHT)(sizeof("""\x1B[0;1;39m""") - 1), false0);
262
263 (void) loop_write(ttyfd, message, strlen(message), false0);
264 (void) loop_write(ttyfd, " ", 1, false0);
265
266 if (use_color)
267 (void) loop_write(ttyfd, ANSI_NORMAL"\x1B[0m", STRLEN(ANSI_NORMAL)(sizeof("""\x1B[0m""") - 1), false0);
268
269 new_termios = old_termios;
270 new_termios.c_lflag &= ~(ICANON0000002|ECHO0000010);
271 new_termios.c_cc[VMIN6] = 1;
272 new_termios.c_cc[VTIME5] = 0;
273
274 if (tcsetattr(ttyfd, TCSADRAIN1, &new_termios) < 0) {
275 r = -errno(*__errno_location ());
276 goto finish;
277 }
278
279 reset_tty = true1;
280 }
281
282 pollfd[POLL_TTY] = (struct pollfd) {
283 .fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO0,
284 .events = POLLIN0x001,
285 };
286 pollfd[POLL_INOTIFY] = (struct pollfd) {
287 .fd = notify,
288 .events = POLLIN0x001,
289 };
290
291 for (;;) {
292 int sleep_for = -1, k;
293 ssize_t n;
294 char c;
295
296 if (until > 0) {
297 usec_t y;
298
299 y = now(CLOCK_MONOTONIC1);
300
301 if (y > until) {
302 r = -ETIME62;
303 goto finish;
304 }
305
306 sleep_for = (int) DIV_ROUND_UP(until - y, USEC_PER_MSEC)({ const typeof((until - y)) __unique_prefix_X37 = ((until - y
)); const typeof((((usec_t) 1000ULL))) __unique_prefix_Y38 = (
(((usec_t) 1000ULL))); (__unique_prefix_X37 / __unique_prefix_Y38
+ !!(__unique_prefix_X37 % __unique_prefix_Y38)); })
;
307 }
308
309 if (flag_file)
310 if (access(flag_file, F_OK0) < 0) {
311 r = -errno(*__errno_location ());
312 goto finish;
313 }
314
315 k = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for);
316 if (k < 0) {
317 if (errno(*__errno_location ()) == EINTR4)
318 continue;
319
320 r = -errno(*__errno_location ());
321 goto finish;
322 } else if (k == 0) {
323 r = -ETIME62;
324 goto finish;
325 }
326
327 if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0)
328 (void) flush_fd(notify);
329
330 if (pollfd[POLL_TTY].revents == 0)
331 continue;
332
333 n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO0, &c, 1);
334 if (n < 0) {
335 if (IN_SET(errno, EINTR, EAGAIN)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){4, 11})/sizeof(int)]; switch((*__errno_location
())) { case 4: case 11: _found = 1; break; default: break; }
_found; })
)
336 continue;
337
338 r = -errno(*__errno_location ());
339 goto finish;
340
341 }
342
343 /* We treat EOF, newline and NUL byte all as valid end markers */
344 if (n == 0 || c == '\n' || c == 0)
345 break;
346
347 if (c == 21) { /* C-u */
348
349 if (!(flags & ASK_PASSWORD_SILENT))
350 backspace_string(ttyfd, passphrase);
351
352 explicit_bzero(passphrase, sizeof(passphrase));
353 p = codepoint = 0;
354
355 } else if (IN_SET(c, '\b', 127)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){'\b', 127})/sizeof(int)]; switch(c) { case
'\b': case 127: _found = 1; break; default: break; } _found;
})
) {
356
357 if (p > 0) {
358 size_t q;
359
360 if (!(flags & ASK_PASSWORD_SILENT))
361 backspace_chars(ttyfd, 1);
362
363 /* Remove a full UTF-8 codepoint from the end. For that, figure out where the last one
364 * begins */
365 q = 0;
366 for (;;) {
367 size_t z;
368
369 z = utf8_encoded_valid_unichar(passphrase + q);
370 if (z == 0) {
371 q = (size_t) -1; /* Invalid UTF8! */
372 break;
373 }
374
375 if (q + z >= p) /* This one brings us over the edge */
376 break;
377
378 q += z;
379 }
380
381 p = codepoint = q == (size_t) -1 ? p - 1 : q;
382 explicit_bzero(passphrase + p, sizeof(passphrase) - p);
383
384 } else if (!dirty && !(flags & ASK_PASSWORD_SILENT)) {
385
386 flags |= ASK_PASSWORD_SILENT;
387
388 /* There are two ways to enter silent mode. Either by pressing backspace as first key
389 * (and only as first key), or ... */
390
391 if (ttyfd >= 0)
392 (void) loop_write(ttyfd, "(no echo) ", 10, false0);
393
394 } else if (ttyfd >= 0)
395 (void) loop_write(ttyfd, "\a", 1, false0);
396
397 } else if (c == '\t' && !(flags & ASK_PASSWORD_SILENT)) {
398
399 backspace_string(ttyfd, passphrase);
400 flags |= ASK_PASSWORD_SILENT;
401
402 /* ... or by pressing TAB at any time. */
403
404 if (ttyfd >= 0)
405 (void) loop_write(ttyfd, "(no echo) ", 10, false0);
406
407 } else if (p >= sizeof(passphrase)-1) {
408
409 /* Reached the size limit */
410 if (ttyfd >= 0)
411 (void) loop_write(ttyfd, "\a", 1, false0);
412
413 } else {
414 passphrase[p++] = c;
415
416 if (!(flags & ASK_PASSWORD_SILENT) && ttyfd >= 0) {
417 /* Check if we got a complete UTF-8 character now. If so, let's output one '*'. */
418 n = utf8_encoded_valid_unichar(passphrase + codepoint);
419 if (n >= 0) {
420 codepoint = p;
421 (void) loop_write(ttyfd, (flags & ASK_PASSWORD_ECHO) ? &c : "*", 1, false0);
422 }
423 }
424
425 dirty = true1;
426 }
427
428 /* Let's forget this char, just to not keep needlessly copies of key material around */
429 c = 'x';
430 }
431
432 x = strndup(passphrase, p);
433 explicit_bzero(passphrase, sizeof(passphrase));
434 if (!x) {
435 r = -ENOMEM12;
436 goto finish;
437 }
438
439 if (keyname)
440 (void) add_to_keyring_and_log(keyname, flags, STRV_MAKE(x)((char**) ((const char*[]) { x, ((void*)0) })));
441
442 *ret = x;
443 r = 0;
444
445finish:
446 if (ttyfd >= 0 && reset_tty) {
447 (void) loop_write(ttyfd, "\n", 1, false0);
448 (void) tcsetattr(ttyfd, TCSADRAIN1, &old_termios);
449 }
450
451 return r;
452}
453
454static int create_socket(char **name) {
455 union sockaddr_union sa = {
456 .un.sun_family = AF_UNIX1,
457 };
458 _cleanup_close___attribute__((cleanup(closep))) int fd = -1;
459 static const int one = 1;
460 char *c;
461 int r;
462
463 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/shared/ask-password-api.c"
, 463, __PRETTY_FUNCTION__); } while (0)
;
22
Taking false branch
23
Loop condition is false. Exiting loop
464
465 fd = socket(AF_UNIX1, SOCK_DGRAMSOCK_DGRAM|SOCK_CLOEXECSOCK_CLOEXEC|SOCK_NONBLOCKSOCK_NONBLOCK, 0);
466 if (fd < 0)
24
Assuming 'fd' is >= 0
25
Taking false branch
467 return -errno(*__errno_location ());
468
469 snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/run/systemd/ask-password/sck.%" PRIx64"l" "x", random_u64());
470
471 RUN_WITH_UMASK(0177)for (__attribute__((cleanup(_reset_umask_))) struct _umask_struct_
_saved_umask_ = { umask(0177), 0 }; !_saved_umask_.quit ; _saved_umask_
.quit = 1)
{
26
Loop condition is true. Entering loop body
34
Loop condition is false. Execution continues on line 476
472 if (bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)({ const struct sockaddr_un *_sa = &(sa.un); do { if ((__builtin_expect
(!!(!(_sa->sun_family == 1)),0))) log_assert_failed_realm(
LOG_REALM_SYSTEMD, ("_sa->sun_family == AF_UNIX"), "../src/shared/ask-password-api.c"
, 472, __PRETTY_FUNCTION__); } while (0); __builtin_offsetof(
struct sockaddr_un, sun_path) + (_sa->sun_path[0] == 0 ? 1
+ strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : strnlen
(_sa->sun_path, sizeof(_sa->sun_path))); })
) < 0
)
27
Assuming field 'sun_family' is equal to 1
28
Taking false branch
29
Loop condition is false. Exiting loop
30
Assuming the condition is true
31
'?' condition is true
32
Assuming the condition is false
33
Taking false branch
473 return -errno(*__errno_location ());
474 }
475
476 if (setsockopt(fd, SOL_SOCKET1, SO_PASSCRED16, &one, sizeof(one)) < 0)
35
Assuming the condition is false
36
Taking false branch
477 return -errno(*__errno_location ());
478
479 c = strdup(sa.un.sun_path);
37
Memory is allocated
480 if (!c)
38
Assuming 'c' is non-null
39
Taking false branch
481 return -ENOMEM12;
482
483 *name = c;
484
485 r = fd;
486 fd = -1;
487
488 return r;
489}
490
491int ask_password_agent(
492 const char *message,
493 const char *icon,
494 const char *id,
495 const char *keyname,
496 usec_t until,
497 AskPasswordFlags flags,
498 char ***ret) {
499
500 enum {
501 FD_SOCKET,
502 FD_SIGNAL,
503 _FD_MAX
504 };
505
506 _cleanup_close___attribute__((cleanup(closep))) int socket_fd = -1, signal_fd = -1, fd = -1;
507 char temp[] = "/run/systemd/ask-password/tmp.XXXXXX";
508 char final[sizeof(temp)] = "";
509 _cleanup_free___attribute__((cleanup(freep))) char *socket_name = NULL((void*)0);
510 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **l = NULL((void*)0);
511 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0);
512 struct pollfd pollfd[_FD_MAX];
513 sigset_t mask, oldmask;
514 int r;
515
516 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/shared/ask-password-api.c"
, 516, __PRETTY_FUNCTION__); } while (0)
;
1
Assuming 'ret' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
517
518 if (flags & ASK_PASSWORD_NO_AGENT)
4
Assuming the condition is false
5
Taking false branch
519 return -EUNATCH49;
520
521 assert_se(sigemptyset(&mask) >= 0)do { if ((__builtin_expect(!!(!(sigemptyset(&mask) >= 0
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("sigemptyset(&mask) >= 0"
), "../src/shared/ask-password-api.c", 521, __PRETTY_FUNCTION__
); } while (0)
;
6
Assuming the condition is true
7
Taking false branch
8
Loop condition is false. Exiting loop
522 assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0)do { if ((__builtin_expect(!!(!(sigset_add_many(&mask, 2,
15, -1) >= 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0")
, "../src/shared/ask-password-api.c", 522, __PRETTY_FUNCTION__
); } while (0)
;
9
Assuming the condition is true
10
Taking false branch
11
Loop condition is false. Exiting loop
523 assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0)do { if ((__builtin_expect(!!(!(sigprocmask(0, &mask, &
oldmask) >= 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0")
, "../src/shared/ask-password-api.c", 523, __PRETTY_FUNCTION__
); } while (0)
;
12
Assuming the condition is true
13
Taking false branch
14
Loop condition is false. Exiting loop
524
525 (void) mkdir_p_label("/run/systemd/ask-password", 0755);
526
527 fd = mkostemp_safe(temp);
528 if (fd < 0) {
15
Assuming 'fd' is >= 0
16
Taking false branch
529 r = fd;
530 goto finish;
531 }
532
533 (void) fchmod(fd, 0644);
534
535 f = fdopen(fd, "w");
536 if (!f) {
17
Assuming 'f' is non-null
18
Taking false branch
537 r = -errno(*__errno_location ());
538 goto finish;
539 }
540
541 fd = -1;
542
543 signal_fd = signalfd(-1, &mask, SFD_NONBLOCKSFD_NONBLOCK|SFD_CLOEXECSFD_CLOEXEC);
544 if (signal_fd < 0) {
19
Assuming 'signal_fd' is >= 0
20
Taking false branch
545 r = -errno(*__errno_location ());
546 goto finish;
547 }
548
549 socket_fd = create_socket(&socket_name);
21
Calling 'create_socket'
40
Returned allocated memory via 1st parameter
550 if (socket_fd
40.1
'socket_fd' is >= 0
< 0) {
41
Taking false branch
551 r = socket_fd;
552 goto finish;
553 }
554
555 fprintf(f,
556 "[Ask]\n"
557 "PID="PID_FMT"%" "i""\n"
558 "Socket=%s\n"
559 "AcceptCached=%i\n"
560 "Echo=%i\n"
561 "NotAfter="USEC_FMT"%" "l" "u""\n",
562 getpid_cached(),
563 socket_name,
564 (flags & ASK_PASSWORD_ACCEPT_CACHED) ? 1 : 0,
42
Assuming the condition is false
43
'?' condition is false
565 (flags & ASK_PASSWORD_ECHO) ? 1 : 0,
44
Assuming the condition is false
45
'?' condition is false
566 until);
567
568 if (message)
46
Assuming 'message' is null
47
Taking false branch
569 fprintf(f, "Message=%s\n", message);
570
571 if (icon)
48
Assuming 'icon' is null
49
Taking false branch
572 fprintf(f, "Icon=%s\n", icon);
573
574 if (id)
50
Assuming 'id' is null
51
Taking false branch
575 fprintf(f, "Id=%s\n", id);
576
577 r = fflush_and_check(f);
578 if (r < 0)
52
Assuming 'r' is < 0
53
Taking true branch
579 goto finish;
54
Control jumps to line 719
580
581 memcpy(final, temp, sizeof(temp));
582
583 final[sizeof(final)-11] = 'a';
584 final[sizeof(final)-10] = 's';
585 final[sizeof(final)-9] = 'k';
586
587 if (rename(temp, final) < 0) {
588 r = -errno(*__errno_location ());
589 goto finish;
590 }
591
592 zero(pollfd)(({ size_t _l_ = (sizeof(pollfd)); void *_x_ = (&(pollfd)
); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); }))
;
593 pollfd[FD_SOCKET].fd = socket_fd;
594 pollfd[FD_SOCKET].events = POLLIN0x001;
595 pollfd[FD_SIGNAL].fd = signal_fd;
596 pollfd[FD_SIGNAL].events = POLLIN0x001;
597
598 for (;;) {
599 char passphrase[LINE_MAX2048+1];
600 struct msghdr msghdr;
601 struct iovec iovec;
602 struct ucred *ucred;
603 union {
604 struct cmsghdr cmsghdr;
605 uint8_t buf[CMSG_SPACE(sizeof(struct ucred))((((sizeof(struct ucred)) + sizeof (size_t) - 1) & (size_t
) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof
(size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)))
];
606 } control;
607 ssize_t n;
608 int k;
609 usec_t t;
610
611 t = now(CLOCK_MONOTONIC1);
612
613 if (until > 0 && until <= t) {
614 r = -ETIME62;
615 goto finish;
616 }
617
618 k = poll(pollfd, _FD_MAX, until > 0 ? (int) ((until-t)/USEC_PER_MSEC((usec_t) 1000ULL)) : -1);
619 if (k < 0) {
620 if (errno(*__errno_location ()) == EINTR4)
621 continue;
622
623 r = -errno(*__errno_location ());
624 goto finish;
625 }
626
627 if (k <= 0) {
628 r = -ETIME62;
629 goto finish;
630 }
631
632 if (pollfd[FD_SIGNAL].revents & POLLIN0x001) {
633 r = -EINTR4;
634 goto finish;
635 }
636
637 if (pollfd[FD_SOCKET].revents != POLLIN0x001) {
638 r = -EIO5;
639 goto finish;
640 }
641
642 zero(iovec)(({ size_t _l_ = (sizeof(iovec)); void *_x_ = (&(iovec));
_l_ == 0 ? _x_ : memset(_x_, 0, _l_); }))
;
643 iovec.iov_base = passphrase;
644 iovec.iov_len = sizeof(passphrase);
645
646 zero(control)(({ size_t _l_ = (sizeof(control)); void *_x_ = (&(control
)); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); }))
;
647 zero(msghdr)(({ size_t _l_ = (sizeof(msghdr)); void *_x_ = (&(msghdr)
); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); }))
;
648 msghdr.msg_iov = &iovec;
649 msghdr.msg_iovlen = 1;
650 msghdr.msg_control = &control;
651 msghdr.msg_controllen = sizeof(control);
652
653 n = recvmsg(socket_fd, &msghdr, 0);
654 if (n < 0) {
655 if (IN_SET(errno, EAGAIN, EINTR)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){11, 4})/sizeof(int)]; switch((*__errno_location
())) { case 11: case 4: _found = 1; break; default: break; }
_found; })
)
656 continue;
657
658 r = -errno(*__errno_location ());
659 goto finish;
660 }
661
662 cmsg_close_all(&msghdr);
663
664 if (n <= 0) {
665 log_debug("Message too short")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/ask-password-api.c", 665, __func__, "Message too short"
) : -abs(_e); })
;
666 continue;
667 }
668
669 if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred))((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t
) ~(sizeof (size_t) - 1)) + (sizeof(struct ucred)))
||
670 control.cmsghdr.cmsg_level != SOL_SOCKET1 ||
671 control.cmsghdr.cmsg_type != SCM_CREDENTIALSSCM_CREDENTIALS ||
672 control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t
) ~(sizeof (size_t) - 1)) + (sizeof(struct ucred)))
) {
673 log_debug("Received message without credentials. Ignoring.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/ask-password-api.c", 673, __func__, "Received message without credentials. Ignoring."
) : -abs(_e); })
;
674 continue;
675 }
676
677 ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr)((&control.cmsghdr)->__cmsg_data);
678 if (ucred->uid != 0) {
679 log_debug("Got request from unprivileged user. Ignoring.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/ask-password-api.c", 679, __func__, "Got request from unprivileged user. Ignoring."
) : -abs(_e); })
;
680 continue;
681 }
682
683 if (passphrase[0] == '+') {
684 /* An empty message refers to the empty password */
685 if (n == 1)
686 l = strv_new("", NULL((void*)0));
687 else
688 l = strv_parse_nulstr(passphrase+1, n-1);
689 explicit_bzero(passphrase, n);
690 if (!l) {
691 r = -ENOMEM12;
692 goto finish;
693 }
694
695 if (strv_isempty(l)) {
696 l = strv_free(l);
697 log_debug("Invalid packet")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/ask-password-api.c", 697, __func__, "Invalid packet"
) : -abs(_e); })
;
698 continue;
699 }
700
701 break;
702 }
703
704 if (passphrase[0] == '-') {
705 r = -ECANCELED125;
706 goto finish;
707 }
708
709 log_debug("Invalid packet")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/ask-password-api.c", 709, __func__, "Invalid packet"
) : -abs(_e); })
;
710 }
711
712 if (keyname)
713 (void) add_to_keyring_and_log(keyname, flags, l);
714
715 *ret = TAKE_PTR(l)({ typeof(l) _ptr_ = (l); (l) = ((void*)0); _ptr_; });
716 r = 0;
717
718finish:
719 if (socket_name
54.1
'socket_name' is non-null
)
55
Taking true branch
720 (void) unlink(socket_name);
56
Potential leak of memory pointed to by 'socket_name'
721
722 (void) unlink(temp);
723
724 if (final[0])
725 (void) unlink(final);
726
727 assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0)do { if ((__builtin_expect(!!(!(sigprocmask(2, &oldmask, (
(void*)0)) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0"), "../src/shared/ask-password-api.c"
, 727, __PRETTY_FUNCTION__); } while (0)
;
728 return r;
729}
730
731int ask_password_auto(
732 const char *message,
733 const char *icon,
734 const char *id,
735 const char *keyname,
736 usec_t until,
737 AskPasswordFlags flags,
738 char ***ret) {
739
740 int r;
741
742 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/shared/ask-password-api.c"
, 742, __PRETTY_FUNCTION__); } while (0)
;
743
744 if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
745 r = ask_password_keyring(keyname, flags, ret);
746 if (r != -ENOKEY126)
747 return r;
748 }
749
750 if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO0)) {
751 char *s = NULL((void*)0), **l = NULL((void*)0);
752
753 r = ask_password_tty(-1, message, keyname, until, flags, NULL((void*)0), &s);
754 if (r < 0)
755 return r;
756
757 r = strv_push(&l, s);
758 if (r < 0) {
759 string_erase(s);
760 free(s);
761 return -ENOMEM12;
762 }
763
764 *ret = l;
765 return 0;
766 }
767
768 if (!(flags & ASK_PASSWORD_NO_AGENT))
769 return ask_password_agent(message, icon, id, keyname, until, flags, ret);
770
771 return -EUNATCH49;
772}