path: root/drivers/serial
diff options
authorAhmad Fatoum <>2019-08-23 11:25:31 +0200
committerSascha Hauer <>2019-09-02 09:12:30 +0200
commit75a74b5c107b3bc30f9c3836208f4c17f9309eed (patch)
tree7e26a790234943bf84c46a1bd37ce4c84f84ed3c /drivers/serial
parentd421771bcea063b9bce551e06552067b9074d015 (diff)
console: fix out-of-bounds read in dputc(/dev/*, ...)
Trying to output a single character via echo -a /dev/serial0-1 currently results in garbage output after the newline, because console.c's fops_write discards the buffer length and passes the buffer to (struct cdev)::puts which only handles NUL-terminated strings. Fix this by amending (struct cdev)::puts with a new nbytes parameter, which is correctly propagated. All this functions now return at most the nbytes parameter they were passed in. This fixes __console_puts, which used to count new lines twice in its return value. Fixes: b4f55fcf35 ("console: expose consoles in devfs") Cc: Bastian Krause <> Signed-off-by: Ahmad Fatoum <> Signed-off-by: Sascha Hauer <>
Diffstat (limited to 'drivers/serial')
2 files changed, 6 insertions, 4 deletions
diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c
index 0703f72..2ca89fa 100644
--- a/drivers/serial/efi-stdio.c
+++ b/drivers/serial/efi-stdio.c
@@ -243,12 +243,13 @@ static int efi_process_key(struct efi_console_priv *priv, const char *inp)
return 1;
-static int efi_console_puts(struct console_device *cdev, const char *s)
+static int efi_console_puts(struct console_device *cdev, const char *s,
+ size_t nbytes)
struct efi_console_priv *priv = to_efi(cdev);
int n = 0;
- while (*s) {
+ while (nbytes--) {
if (*s == 27) {
priv->efi_console_buffer[n] = 0;
diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c
index f0a2b22..667d51f 100644
--- a/drivers/serial/serial_efi.c
+++ b/drivers/serial/serial_efi.c
@@ -130,13 +130,14 @@ static void efi_serial_putc(struct console_device *cdev, char c)
serial->write(serial, &buffersize, &c);
-static int efi_serial_puts(struct console_device *cdev, const char *s)
+static int efi_serial_puts(struct console_device *cdev, const char *s,
+ size_t nbytes)
struct efi_serial_port *uart = to_efi_serial_port(cdev);
struct efi_serial_io_protocol *serial = uart->serial;
uint32_t control;
efi_status_t efiret;
- unsigned long buffersize = strlen(s) * sizeof(char);
+ unsigned long buffersize = nbytes;
do {
efiret = serial->getcontrol(serial, &control);