Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1283349

[PATCH v3 06/14] lib/vsprintf.c: warn about too large precisions and field widths

From Rasmus Villemoes <linux@rasmusvillemoes.dk>
Newsgroups linux.kernel
Subject [PATCH v3 06/14] lib/vsprintf.c: warn about too large precisions and field widths
Date 2015-12-03 22:00 +0100
Message-ID <qBJ8T-1Cs-65@gated-at.bofh.it> (permalink)
References <qBJ8R-1Cs-3@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


The field width is overloaded to pass some extra information for
some %p extensions (e.g. #bits for %pb). But we might silently
truncate the passed value when we stash it in struct printf_spec (see
e.g. "lib/vsprintf.c: expand field_width to 24 bits").  Hopefully 23
value bits should now be enough for everybody, but if not, let's make
some noise.

Do the same for the precision. In both cases, clamping seems more
sensible than truncating. While, according to POSIX, "A negative
precision is taken as if the precision were omitted.", the kernel's
printf has always treated that case as if the precision was 0, so we
use that as lower bound. For the field width, the smallest
representable value is actually -(1<<23), but a negative field width
means 'set the LEFT flag and use the absolute value', so we want the
absolute value to fit.

Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
---
v3: also do the check in bstr_printf (thanks Andy).

 lib/vsprintf.c | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index d7e27c54fa00..3db2281e6026 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -386,6 +386,8 @@ struct printf_spec {
 	unsigned int	base:8;		/* number base, 8, 10 or 16 only */
 	signed int	precision:16;	/* # of digits/chars */
 } __packed;
+#define FIELD_WIDTH_MAX ((1 << 23) - 1)
+#define PRECISION_MAX ((1 << 15) - 1)
 extern char __check_printf_spec[1-2*(sizeof(struct printf_spec) != 8)];
 
 static noinline_for_stack
@@ -1815,6 +1817,24 @@ qualifier:
 	return ++fmt - start;
 }
 
+static void
+set_field_width(struct printf_spec *spec, int width)
+{
+	spec->field_width = width;
+	if (WARN_ONCE(spec->field_width != width, "field width %d too large", width)) {
+		spec->field_width = clamp(width, -FIELD_WIDTH_MAX, FIELD_WIDTH_MAX);
+	}
+}
+
+static void
+set_precision(struct printf_spec *spec, int prec)
+{
+	spec->precision = prec;
+	if (WARN_ONCE(spec->precision != prec, "precision %d too large", prec)) {
+		spec->precision = clamp(prec, 0, PRECISION_MAX);
+	}
+}
+
 /**
  * vsnprintf - Format a string and place it in a buffer
  * @buf: The buffer to place the result into
@@ -1882,11 +1902,11 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
 		}
 
 		case FORMAT_TYPE_WIDTH:
-			spec.field_width = va_arg(args, int);
+			set_field_width(&spec, va_arg(args, int));
 			break;
 
 		case FORMAT_TYPE_PRECISION:
-			spec.precision = va_arg(args, int);
+			set_precision(&spec, va_arg(args, int));
 			break;
 
 		case FORMAT_TYPE_CHAR: {
@@ -2326,11 +2346,11 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
 		}
 
 		case FORMAT_TYPE_WIDTH:
-			spec.field_width = get_arg(int);
+			set_field_width(&spec, get_arg(int));
 			break;
 
 		case FORMAT_TYPE_PRECISION:
-			spec.precision = get_arg(int);
+			set_precision(&spec, get_arg(int));
 			break;
 
 		case FORMAT_TYPE_CHAR: {
-- 
2.6.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH v3 00/14] printf stuff for 4.5 Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-03 22:00 +0100
  [PATCH v3 01/14] lib/vsprintf.c: pull out padding code from dentry_name() Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-03 22:00 +0100
  Re: [PATCH v3 04/14] lib/vsprintf.c: expand field_width to 24 bits Joe Perches <joe@perches.com> - 2015-12-03 22:00 +0100
    Re: [PATCH v3 04/14] lib/vsprintf.c: expand field_width to 24 bits Andy Shevchenko <andriy.shevchenko@linux.intel.com> - 2015-12-03 22:40 +0100
      Re: [PATCH v3 04/14] lib/vsprintf.c: expand field_width to 24 bits Andrew Morton <akpm@linux-foundation.org> - 2015-12-04 00:40 +0100
        Re: [PATCH v3 04/14] lib/vsprintf.c: expand field_width to 24 bits Joe Perches <joe@perches.com> - 2015-12-04 01:10 +0100
          Re: [PATCH v3 04/14] lib/vsprintf.c: expand field_width to 24 bits Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-04 10:10 +0100
        Re: [PATCH v3 04/14] lib/vsprintf.c: expand field_width to 24 bits Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-04 10:10 +0100
      Re: [PATCH v3 04/14] lib/vsprintf.c: expand field_width to 24 bits Joe Perches <joe@perches.com> - 2015-12-04 00:50 +0100
  [PATCH v3 08/14] lib/test_printf.c: don't BUG Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-03 22:00 +0100
  [PATCH v3 03/14] lib/vsprintf.c: eliminate potential race in string() Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-03 22:00 +0100
  [PATCH v3 06/14] lib/vsprintf.c: warn about too large precisions and field widths Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-03 22:00 +0100
  [PATCH v3 09/14] lib/test_printf.c: check for out-of-bound writes Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-03 22:00 +0100
  [PATCH v3 02/14] lib/vsprintf.c: move string() below widen_string() Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-03 22:00 +0100
  [PATCH v3 14/14] lib/test_printf.c: test dentry printing Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-03 22:00 +0100
    Re: [PATCH v3 14/14] lib/test_printf.c: test dentry printing Andrew Morton <akpm@linux-foundation.org> - 2015-12-04 01:20 +0100
      Re: [PATCH v3 14/14] lib/test_printf.c: test dentry printing Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-04 09:20 +0100
        Re: [PATCH v3 14/14] lib/test_printf.c: test dentry printing Andrew Morton <akpm@linux-foundation.org> - 2015-12-04 09:50 +0100
  [PATCH v3 04/14] lib/vsprintf.c: expand field_width to 24 bits Rasmus Villemoes <linux@rasmusvillemoes.dk> - 2015-12-03 22:00 +0100

csiph-web