Commit 8fb331e1 authored by Arvind Sankar's avatar Arvind Sankar Committed by Ard Biesheuvel

efi/printf: Turn vsprintf into vsnprintf

Implement vsnprintf instead of vsprintf to avoid the possibility of a
buffer overflow.
Signed-off-by: default avatarArvind Sankar <nivedita@alum.mit.edu>
Link: https://lore.kernel.org/r/20200518190716.751506-17-nivedita@alum.mit.eduSigned-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent f97ca2c8
...@@ -60,10 +60,14 @@ int efi_printk(const char *fmt, ...) ...@@ -60,10 +60,14 @@ int efi_printk(const char *fmt, ...)
int printed; int printed;
va_start(args, fmt); va_start(args, fmt);
printed = vsprintf(printf_buf, fmt, args); printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
va_end(args); va_end(args);
efi_puts(printf_buf); efi_puts(printf_buf);
if (printed >= sizeof(printf_buf)) {
efi_puts("[Message truncated]\n");
return -1;
}
return printed; return printed;
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h>
static static
int skip_atoi(const char **s) int skip_atoi(const char **s)
...@@ -237,16 +238,22 @@ char get_sign(long long *num, int flags) ...@@ -237,16 +238,22 @@ char get_sign(long long *num, int flags)
return 0; return 0;
} }
int vsprintf(char *buf, const char *fmt, va_list ap) #define PUTC(c) \
do { \
if (pos < size) \
buf[pos] = (c); \
++pos; \
} while (0);
int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
{ {
/* The maximum space required is to print a 64-bit number in octal */ /* The maximum space required is to print a 64-bit number in octal */
char tmp[(sizeof(unsigned long long) * 8 + 2) / 3]; char tmp[(sizeof(unsigned long long) * 8 + 2) / 3];
char *tmp_end = &tmp[ARRAY_SIZE(tmp)]; char *tmp_end = &tmp[ARRAY_SIZE(tmp)];
long long num; long long num;
int base; int base;
char *str;
const char *s; const char *s;
int len; size_t len, pos;
char sign; char sign;
int flags; /* flags to number() */ int flags; /* flags to number() */
...@@ -274,9 +281,9 @@ int vsprintf(char *buf, const char *fmt, va_list ap) ...@@ -274,9 +281,9 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
*/ */
va_copy(args, ap); va_copy(args, ap);
for (str = buf; *fmt; ++fmt) { for (pos = 0; *fmt; ++fmt) {
if (*fmt != '%' || *++fmt == '%') { if (*fmt != '%' || *++fmt == '%') {
*str++ = *fmt; PUTC(*fmt);
continue; continue;
} }
...@@ -416,40 +423,41 @@ int vsprintf(char *buf, const char *fmt, va_list ap) ...@@ -416,40 +423,41 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
/* Leading padding with ' ' */ /* Leading padding with ' ' */
if (!(flags & LEFT)) if (!(flags & LEFT))
while (field_width-- > 0) while (field_width-- > 0)
*str++ = ' '; PUTC(' ');
/* sign */ /* sign */
if (sign) if (sign)
*str++ = sign; PUTC(sign);
/* 0x/0X for hexadecimal */ /* 0x/0X for hexadecimal */
if (flags & SPECIAL) { if (flags & SPECIAL) {
*str++ = '0'; PUTC('0');
*str++ = 'X' | (flags & SMALL); PUTC( 'X' | (flags & SMALL));
} }
/* Zero padding and excess precision */ /* Zero padding and excess precision */
while (precision-- > len) while (precision-- > len)
*str++ = '0'; PUTC('0');
/* Actual output */ /* Actual output */
while (len-- > 0) while (len-- > 0)
*str++ = *s++; PUTC(*s++);
/* Trailing padding with ' ' */ /* Trailing padding with ' ' */
while (field_width-- > 0) while (field_width-- > 0)
*str++ = ' '; PUTC(' ');
} }
fail: fail:
*str = '\0';
va_end(args); va_end(args);
return str - buf; if (size)
buf[min(pos, size-1)] = '\0';
return pos;
} }
int sprintf(char *buf, const char *fmt, ...) int snprintf(char *buf, size_t size, const char *fmt, ...)
{ {
va_list args; va_list args;
int i; int i;
va_start(args, fmt); va_start(args, fmt);
i = vsprintf(buf, fmt, args); i = vsnprintf(buf, size, fmt, args);
va_end(args); va_end(args);
return i; return i;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment