ask-password: reject oversized Plymouth prompts (#43102)
Plymouth encodes the password prompt length in a single byte. Reject prompts whose length cannot be represented instead of wrapping the encoded length while sending the complete message.
This commit is contained in:
@@ -302,9 +302,9 @@ int ask_password_plymouth(
|
||||
_cleanup_close_ int fd = -EBADF, inotify_fd = -EBADF;
|
||||
_cleanup_free_ char *packet = NULL;
|
||||
ssize_t k;
|
||||
int r, n;
|
||||
int r;
|
||||
char buffer[LINE_MAX];
|
||||
size_t p = 0;
|
||||
size_t packet_size, p = 0;
|
||||
|
||||
assert(req);
|
||||
assert(ret);
|
||||
@@ -329,13 +329,16 @@ int ask_password_plymouth(
|
||||
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED)) {
|
||||
packet = strdup("c");
|
||||
n = 1;
|
||||
} else if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0)
|
||||
packet = NULL;
|
||||
packet_size = 2;
|
||||
} else {
|
||||
r = plymouth_build_password_packet(message, &packet, &packet_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
if (!packet)
|
||||
return -ENOMEM;
|
||||
|
||||
r = loop_write_full(fd, packet, n + 1, USEC_INFINITY);
|
||||
r = loop_write_full(fd, packet, packet_size, USEC_INFINITY);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -416,10 +419,11 @@ int ask_password_plymouth(
|
||||
* with a normal password request */
|
||||
packet = mfree(packet);
|
||||
|
||||
if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0)
|
||||
return -ENOMEM;
|
||||
r = plymouth_build_password_packet(message, &packet, &packet_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = loop_write_full(fd, packet, n + 1, USEC_INFINITY);
|
||||
r = loop_write_full(fd, packet, packet_size, USEC_INFINITY);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -7,6 +7,35 @@
|
||||
#include "plymouth-util.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
int plymouth_build_password_packet(const char *message, char **ret_packet, size_t *ret_size) {
|
||||
size_t l, sz;
|
||||
char *packet;
|
||||
|
||||
assert(message);
|
||||
assert(ret_packet);
|
||||
assert(ret_size);
|
||||
|
||||
l = strlen(message);
|
||||
if (l >= UCHAR_MAX)
|
||||
return -EMSGSIZE;
|
||||
|
||||
/* 3 byte header ('*', command, payload length), followed by the message and its NUL terminator. */
|
||||
sz = 3 + l + 1;
|
||||
|
||||
packet = new(char, sz);
|
||||
if (!packet)
|
||||
return -ENOMEM;
|
||||
|
||||
packet[0] = '*';
|
||||
packet[1] = '\x02';
|
||||
packet[2] = (uint8_t) (l + 1);
|
||||
memcpy(packet + 3, message, l + 1);
|
||||
|
||||
*ret_packet = packet;
|
||||
*ret_size = sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plymouth_connect(int flags) {
|
||||
static const union sockaddr_union sa = {
|
||||
.un.sun_family = AF_UNIX,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "forward.h"
|
||||
|
||||
int plymouth_connect(int flags);
|
||||
int plymouth_build_password_packet(const char *message, char **ret_packet, size_t *ret_size);
|
||||
int plymouth_send_raw(const void *raw, size_t size, int flags);
|
||||
int plymouth_send_msg(const char *text, bool pause_spinner);
|
||||
int plymouth_hide_splash(void);
|
||||
|
||||
@@ -171,6 +171,7 @@ simple_tests += files(
|
||||
'test-path-util.c',
|
||||
'test-percent-util.c',
|
||||
'test-pidref.c',
|
||||
'test-plymouth-util.c',
|
||||
'test-pressure.c',
|
||||
'test-pretty-print.c',
|
||||
'test-printf.c',
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "plymouth-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
TEST(build_password_packet) {
|
||||
_cleanup_free_ char *packet = NULL;
|
||||
size_t size;
|
||||
|
||||
ASSERT_OK(plymouth_build_password_packet("Password:", &packet, &size));
|
||||
ASSERT_EQ(size, 13U);
|
||||
ASSERT_EQ(memcmp(packet, "*\x02\x0aPassword:\0", size), 0);
|
||||
|
||||
packet = mfree(packet);
|
||||
|
||||
char message[UCHAR_MAX];
|
||||
memset(message, 'x', sizeof(message) - 1);
|
||||
message[sizeof(message) - 1] = '\0';
|
||||
|
||||
ASSERT_OK(plymouth_build_password_packet(message, &packet, &size));
|
||||
ASSERT_EQ(size, 3U + sizeof(message));
|
||||
ASSERT_EQ((uint8_t) packet[2], UCHAR_MAX);
|
||||
ASSERT_EQ(memcmp(packet + 3, message, sizeof(message)), 0);
|
||||
|
||||
packet = mfree(packet);
|
||||
ASSERT_ERROR(plymouth_build_password_packet(strjoina(message, "x"), &packet, &size), EMSGSIZE);
|
||||
ASSERT_NULL(packet);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
Reference in New Issue
Block a user