Skip to content

Commit 8fb331e

Browse files
nivedita76ardbiesheuvel
authored andcommitted
efi/printf: Turn vsprintf into vsnprintf
Implement vsnprintf instead of vsprintf to avoid the possibility of a buffer overflow. Signed-off-by: Arvind Sankar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent f97ca2c commit 8fb331e

File tree

2 files changed

+30
-18
lines changed

2 files changed

+30
-18
lines changed

drivers/firmware/efi/libstub/efi-stub-helper.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,14 @@ int efi_printk(const char *fmt, ...)
6060
int printed;
6161

6262
va_start(args, fmt);
63-
printed = vsprintf(printf_buf, fmt, args);
63+
printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
6464
va_end(args);
6565

6666
efi_puts(printf_buf);
67+
if (printed >= sizeof(printf_buf)) {
68+
efi_puts("[Message truncated]\n");
69+
return -1;
70+
}
6771

6872
return printed;
6973
}

drivers/firmware/efi/libstub/vsprintf.c

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/kernel.h>
1818
#include <linux/limits.h>
1919
#include <linux/string.h>
20+
#include <linux/types.h>
2021

2122
static
2223
int skip_atoi(const char **s)
@@ -237,16 +238,22 @@ char get_sign(long long *num, int flags)
237238
return 0;
238239
}
239240

240-
int vsprintf(char *buf, const char *fmt, va_list ap)
241+
#define PUTC(c) \
242+
do { \
243+
if (pos < size) \
244+
buf[pos] = (c); \
245+
++pos; \
246+
} while (0);
247+
248+
int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
241249
{
242250
/* The maximum space required is to print a 64-bit number in octal */
243251
char tmp[(sizeof(unsigned long long) * 8 + 2) / 3];
244252
char *tmp_end = &tmp[ARRAY_SIZE(tmp)];
245253
long long num;
246254
int base;
247-
char *str;
248255
const char *s;
249-
int len;
256+
size_t len, pos;
250257
char sign;
251258

252259
int flags; /* flags to number() */
@@ -274,9 +281,9 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
274281
*/
275282
va_copy(args, ap);
276283

277-
for (str = buf; *fmt; ++fmt) {
284+
for (pos = 0; *fmt; ++fmt) {
278285
if (*fmt != '%' || *++fmt == '%') {
279-
*str++ = *fmt;
286+
PUTC(*fmt);
280287
continue;
281288
}
282289

@@ -416,40 +423,41 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
416423
/* Leading padding with ' ' */
417424
if (!(flags & LEFT))
418425
while (field_width-- > 0)
419-
*str++ = ' ';
426+
PUTC(' ');
420427
/* sign */
421428
if (sign)
422-
*str++ = sign;
429+
PUTC(sign);
423430
/* 0x/0X for hexadecimal */
424431
if (flags & SPECIAL) {
425-
*str++ = '0';
426-
*str++ = 'X' | (flags & SMALL);
432+
PUTC('0');
433+
PUTC( 'X' | (flags & SMALL));
427434
}
428435
/* Zero padding and excess precision */
429436
while (precision-- > len)
430-
*str++ = '0';
437+
PUTC('0');
431438
/* Actual output */
432439
while (len-- > 0)
433-
*str++ = *s++;
440+
PUTC(*s++);
434441
/* Trailing padding with ' ' */
435442
while (field_width-- > 0)
436-
*str++ = ' ';
443+
PUTC(' ');
437444
}
438445
fail:
439-
*str = '\0';
440-
441446
va_end(args);
442447

443-
return str - buf;
448+
if (size)
449+
buf[min(pos, size-1)] = '\0';
450+
451+
return pos;
444452
}
445453

446-
int sprintf(char *buf, const char *fmt, ...)
454+
int snprintf(char *buf, size_t size, const char *fmt, ...)
447455
{
448456
va_list args;
449457
int i;
450458

451459
va_start(args, fmt);
452-
i = vsprintf(buf, fmt, args);
460+
i = vsnprintf(buf, size, fmt, args);
453461
va_end(args);
454462
return i;
455463
}

0 commit comments

Comments
 (0)