diff --git a/TODO b/TODO index 756dfd2..b100d37 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,3 @@ - fix the tests so that they work better with "make check" - Allow plymouth to be started from nash instead of the other way around - Drop all the make ram disk and copy code. That was just to make bolting things on easier. We can integrate now. -- check peer credentials on client to make sure it's not running unprivileged diff --git a/src/libply/ply-utils.c b/src/libply/ply-utils.c index 58a3862..910b571 100644 --- a/src/libply/ply-utils.c +++ b/src/libply/ply-utils.c @@ -103,6 +103,7 @@ static int ply_open_unix_socket (const char *path) { int fd; + const int should_pass_credentials = true; assert (path != NULL); @@ -120,6 +121,15 @@ ply_open_unix_socket (const char *path) return -1; } + if (setsockopt (fd, SOL_SOCKET, SO_PASSCRED, + &should_pass_credentials, sizeof (should_pass_credentials)) < 0) + { + ply_save_errno (); + close (fd); + ply_restore_errno (); + return -1; + } + return fd; } @@ -232,6 +242,35 @@ ply_listen_to_unix_socket (const char *path, return fd; } +bool +ply_get_credentials_from_fd (int fd, + pid_t *pid, + uid_t *uid, + gid_t *gid) +{ + struct ucred credentials; + socklen_t credential_size; + + credential_size = sizeof (credentials); + if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &credentials, + &credential_size) < 0) + return false; + + if (credential_size < sizeof (credentials)) + return false; + + if (pid != NULL) + *pid = credentials.pid; + + if (uid != NULL) + *uid = credentials.uid; + + if (gid != NULL) + *gid = credentials.gid; + + return true; +} + int ply_create_unix_socket (const char *path) { diff --git a/src/libply/ply-utils.h b/src/libply/ply-utils.h index 91d01ca..3e2265a 100644 --- a/src/libply/ply-utils.h +++ b/src/libply/ply-utils.h @@ -48,6 +48,10 @@ int ply_connect_to_unix_socket (const char *path, bool is_abstract); int ply_listen_to_unix_socket (const char *path, bool is_abstract); +bool ply_get_credentials_from_fd (int fd, + pid_t *pid, + uid_t *uid, + gid_t *gid); bool ply_write (int fd, const void *buffer, diff --git a/src/ply-boot-protocol.h b/src/ply-boot-protocol.h index 5dc0877..16fce7c 100644 --- a/src/ply-boot-protocol.h +++ b/src/ply-boot-protocol.h @@ -30,6 +30,7 @@ #define PLY_BOOT_PROTOCOL_REQUEST_TYPE_PASSWORD "*" #define PLY_BOOT_PROTOCOL_REQUEST_TYPE_SHOW_SPLASH "$" #define PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK "\x6" +#define PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK "\x15" #define PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ANSWER "\x2" #endif /* PLY_BOOT_PROTOCOL_H */ diff --git a/src/ply-boot-server.c b/src/ply-boot-server.c index d34d04a..517a31b 100644 --- a/src/ply-boot-server.c +++ b/src/ply-boot-server.c @@ -169,6 +169,17 @@ ply_boot_connection_read_request (ply_boot_connection_t *connection, return true; } +static bool +ply_boot_connection_is_from_root (ply_boot_connection_t *connection) +{ + uid_t uid; + + if (!ply_get_credentials_from_fd (connection->fd, NULL, &uid, NULL)) + return false; + + return uid == 0; +} + static void ply_boot_connection_on_request (ply_boot_connection_t *connection) { @@ -185,6 +196,18 @@ ply_boot_connection_on_request (ply_boot_connection_t *connection) &command, &argument)) return; + if (!ply_boot_connection_is_from_root (connection)) + { + ply_error ("request came from non-root user"); + + if (!ply_write (connection->fd, + PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK, + strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK))) + ply_error ("could not write bytes: %m"); + + return; + } + if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_UPDATE) == 0) { if (server->update_handler != NULL) @@ -238,6 +261,12 @@ ply_boot_connection_on_request (ply_boot_connection_t *connection) else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PING) != 0) { ply_error ("received unknown command '%s' from client", command); + + if (!ply_write (connection->fd, + PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK, + strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK))) + ply_error ("could not write bytes: %m"); + return; }