diff --git a/src/libply/ply-utils.c b/src/libply/ply-utils.c index 0d7bdd66..d8010701 100644 --- a/src/libply/ply-utils.c +++ b/src/libply/ply-utils.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -939,4 +940,93 @@ ply_utf8_string_get_length (const char *string, return count; } +char * +ply_get_process_command_line (pid_t pid) +{ + char *path; + char *command_line; + ssize_t bytes_read; + int fd; + ssize_t i; + + path = NULL; + command_line = NULL; + + asprintf (&path, "/proc/%ld/cmdline", (long) pid); + + fd = open (path, O_RDONLY); + + if (fd < 0) + { + ply_trace ("Could not open %s: %m", path); + goto error; + } + + command_line = calloc (PAGE_SIZE, sizeof (char)); + bytes_read = read (fd, command_line, PAGE_SIZE - 1); + if (bytes_read < 0) + { + ply_trace ("Could not read %s: %m", path); + close (fd); + goto error; + } + close (fd); + free (path); + + for (i = 0; i < bytes_read - 1; i++) + { + if (command_line[i] == '\0') + command_line[i] = ' '; + } + command_line[i] = '\0'; + + return command_line; + +error: + free (path); + free (command_line); + return NULL; +} + +pid_t +ply_get_process_parent_pid (pid_t pid) +{ + char *path; + char *stat; + FILE *fp; + int ppid; + + asprintf (&path, "/proc/%ld/stat", (long) pid); + + ppid = 0; + fp = fopen (path, "r"); + + if (fp == NULL) + { + ply_trace ("Could not open %s: %m", path); + goto out; + } + + stat = calloc (PAGE_SIZE, sizeof (char)); + if (fscanf (fp, "%*d %*s %*c %d", &ppid) != 1) + { + ply_trace ("Could not parse %s: %m", path); + goto out; + } + + if (ppid <= 0) + { + ply_trace ("%s is returning invalid parent pid %d", path, ppid); + ppid = 0; + goto out; + } + +out: + free (path); + + if (fp != NULL) + fclose (fp); + + return (pid_t) ppid; +} /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply/ply-utils.h b/src/libply/ply-utils.h index 2c4b3c73..8af8172d 100644 --- a/src/libply/ply-utils.h +++ b/src/libply/ply-utils.h @@ -110,6 +110,9 @@ int ply_utf8_character_get_size (const char *string, int ply_utf8_string_get_length (const char *string, size_t n); +char *ply_get_process_command_line (pid_t pid); +pid_t ply_get_process_parent_pid (pid_t pid); + #endif #endif /* PLY_UTILS_H */ diff --git a/src/ply-boot-server.c b/src/ply-boot-server.c index d744a204..297074ec 100644 --- a/src/ply-boot-server.c +++ b/src/ply-boot-server.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -38,11 +39,15 @@ #include "ply-trigger.h" #include "ply-utils.h" -typedef struct +typedef struct { int fd; ply_fd_watch_t *watch; ply_boot_server_t *server; + uid_t uid; + pid_t pid; + + uint32_t credentials_read : 1; } ply_boot_connection_t; struct _ply_boot_server @@ -198,6 +203,8 @@ ply_boot_connection_read_request (ply_boot_connection_t *connection, assert (connection != NULL); assert (connection->fd >= 0); + connection->credentials_read = false; + if (!ply_read (connection->fd, header, sizeof (header))) return false; @@ -224,21 +231,31 @@ ply_boot_connection_read_request (ply_boot_connection_t *connection, return false; } } + + if (!ply_get_credentials_from_fd (connection->fd, &connection->pid, &connection->uid, NULL)) + { + ply_trace ("couldn't read credentials from connection: %m"); + free (*argument); + free (*command); + return false; + } + connection->credentials_read = true; + return true; } static bool ply_boot_connection_is_from_root (ply_boot_connection_t *connection) { - uid_t uid; + if (!connection->credentials_read) + { + ply_trace ("Asked if connection is from root, but haven't checked credentials yet"); + return false; + } - if (!ply_get_credentials_from_fd (connection->fd, NULL, &uid, NULL)) - return false; - - return uid == 0; + return connection->uid == 0; } - static void ply_boot_connection_send_answer (ply_boot_connection_t *connection, const char *answer) @@ -325,6 +342,24 @@ ply_boot_connection_on_keystroke_answer (ply_boot_connection_t *connection, ply_boot_connection_send_answer (connection, key); } +static void +print_connection_process_identity (ply_boot_connection_t *connection) +{ + char *command_line, *parent_command_line; + pid_t parent_pid; + + command_line = ply_get_process_command_line (connection->pid); + parent_pid = ply_get_process_parent_pid (connection->pid); + parent_command_line = ply_get_process_command_line (parent_pid); + + ply_trace ("connection is from pid %ld (%s) with parent pid %ld (%s)", + (long) connection->pid, command_line, + (long) parent_pid, parent_command_line); + + free (command_line); + free (parent_command_line); +} + static void ply_boot_connection_on_request (ply_boot_connection_t *connection) { @@ -344,6 +379,9 @@ ply_boot_connection_on_request (ply_boot_connection_t *connection) return; } + if (ply_is_tracing ()) + print_connection_process_identity (connection); + if (!ply_boot_connection_is_from_root (connection)) { ply_error ("request came from non-root user");