/src/systemd/src/shared/polkit-agent.c
Line | Count | Source |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | | |
3 | | #include <poll.h> |
4 | | #include <signal.h> |
5 | | #include <unistd.h> |
6 | | |
7 | | #include "bus-util.h" |
8 | | #include "exec-util.h" |
9 | | #include "fd-util.h" |
10 | | #include "io-util.h" |
11 | | #include "log.h" |
12 | | #include "polkit-agent.h" |
13 | | #include "process-util.h" |
14 | | #include "stdio-util.h" |
15 | | |
16 | | #if ENABLE_POLKIT |
17 | | static pid_t agent_pid = 0; |
18 | | |
19 | | int polkit_agent_open(void) { |
20 | | _cleanup_close_pair_ int pipe_fd[2] = EBADF_PAIR; |
21 | | char notify_fd[DECIMAL_STR_MAX(int) + 1]; |
22 | | int r; |
23 | | |
24 | | if (agent_pid > 0) |
25 | | return 0; |
26 | | |
27 | | /* Clients that run as root don't need to activate/query polkit */ |
28 | | if (geteuid() == 0) |
29 | | return 0; |
30 | | |
31 | | r = shall_fork_agent(); |
32 | | if (r <= 0) |
33 | | return r; |
34 | | |
35 | | if (pipe2(pipe_fd, 0) < 0) |
36 | | return -errno; |
37 | | |
38 | | xsprintf(notify_fd, "%i", pipe_fd[1]); |
39 | | |
40 | | r = fork_agent("(polkit-agent)", |
41 | | &pipe_fd[1], |
42 | | 1, |
43 | | &agent_pid, |
44 | | POLKIT_AGENT_BINARY_PATH, |
45 | | "--notify-fd", notify_fd, |
46 | | "--fallback"); |
47 | | if (r < 0) |
48 | | return log_error_errno(r, "Failed to fork polkit agent: %m"); |
49 | | |
50 | | /* Close the writing side, because that's the one for the agent */ |
51 | | pipe_fd[1] = safe_close(pipe_fd[1]); |
52 | | |
53 | | /* Wait until the agent closes the fd */ |
54 | | (void) fd_wait_for_event(pipe_fd[0], POLLHUP, USEC_INFINITY); |
55 | | |
56 | | return 1; |
57 | | } |
58 | | |
59 | | void polkit_agent_close(void) { |
60 | | |
61 | | if (agent_pid <= 0) |
62 | | return; |
63 | | |
64 | | /* Inform agent that we are done */ |
65 | | sigterm_wait(TAKE_PID(agent_pid)); |
66 | | } |
67 | | |
68 | | #else |
69 | | |
70 | 0 | int polkit_agent_open(void) { |
71 | 0 | return 0; |
72 | 0 | } |
73 | | |
74 | 0 | void polkit_agent_close(void) { |
75 | 0 | } |
76 | | |
77 | | #endif |
78 | | |
79 | 0 | int polkit_agent_open_if_enabled(BusTransport transport, bool ask_password) { |
80 | | |
81 | | /* Open the polkit agent as a child process if necessary */ |
82 | |
|
83 | 0 | if (transport != BUS_TRANSPORT_LOCAL) |
84 | 0 | return 0; |
85 | | |
86 | 0 | if (!ask_password) |
87 | 0 | return 0; |
88 | | |
89 | 0 | return polkit_agent_open(); |
90 | 0 | } |