polkit: temporarily spawn of a polkit agent in terminals for possibly authenticated operations

This commit is contained in:
Lennart Poettering
2012-04-11 20:39:03 +02:00
parent f25626edf4
commit 6bb92a169e
12 changed files with 322 additions and 144 deletions
+85
View File
@@ -6035,3 +6035,88 @@ int fd_inc_rcvbuf(int fd, size_t n) {
return 1;
}
int fork_agent(pid_t *pid, const char *path, ...) {
pid_t parent_pid, agent_pid;
int fd;
bool stdout_is_tty, stderr_is_tty;
unsigned n, i;
va_list ap;
char **l;
assert(pid);
assert(path);
parent_pid = getpid();
/* Spawns a temporary TTY agent, making sure it goes away when
* we go away */
agent_pid = fork();
if (agent_pid < 0)
return -errno;
if (agent_pid != 0) {
*pid = agent_pid;
return 0;
}
/* In the child:
*
* Make sure the agent goes away when the parent dies */
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
_exit(EXIT_FAILURE);
/* Check whether our parent died before we were able
* to set the death signal */
if (getppid() != parent_pid)
_exit(EXIT_SUCCESS);
/* Don't leak fds to the agent */
close_all_fds(NULL, 0);
stdout_is_tty = isatty(STDOUT_FILENO);
stderr_is_tty = isatty(STDERR_FILENO);
if (!stdout_is_tty || !stderr_is_tty) {
/* Detach from stdout/stderr. and reopen
* /dev/tty for them. This is important to
* ensure that when systemctl is started via
* popen() or a similar call that expects to
* read EOF we actually do generate EOF and
* not delay this indefinitely by because we
* keep an unused copy of stdin around. */
fd = open("/dev/tty", O_WRONLY);
if (fd < 0) {
log_error("Failed to open /dev/tty: %m");
_exit(EXIT_FAILURE);
}
if (!stdout_is_tty)
dup2(fd, STDOUT_FILENO);
if (!stderr_is_tty)
dup2(fd, STDERR_FILENO);
if (fd > 2)
close(fd);
}
/* Count arguments */
va_start(ap, path);
for (n = 0; va_arg(ap, char*); n++)
;
va_end(ap);
/* Allocate strv */
l = alloca(sizeof(char *) * (n + 1));
/* Fill in arguments */
va_start(ap, path);
for (i = 0; i <= n; i++)
l[i] = va_arg(ap, char*);
va_end(ap);
execv(path, l);
_exit(EXIT_FAILURE);
}
+3
View File
@@ -528,4 +528,7 @@ int is_kernel_thread(pid_t pid);
int fd_inc_sndbuf(int fd, size_t n);
int fd_inc_rcvbuf(int fd, size_t n);
int fork_agent(pid_t *pid, const char *path, ...);
#endif