[PATCH 4/4] test_printf: test printf family at runtime

2015-09-25 Thread Rasmus Villemoes
This adds a simple module for testing the kernel's printf
facilities. Previously, some %p extensions have caused a wrong return
value in case the entire output didn't fit and/or been unusable in
kasprintf(). This should help catch such issues. Also, it should help
ensure that changes to the formatting algorithms don't break anything.

I'm not sure if we have a struct dentry or struct file lying around at
boot time or if we can fake one, but most %p extensions should be
testable, as should the ordinary number and string formatting.

The nature of vararg functions means we can't use a more conventional
table-driven approach.

For now, this is mostly a skeleton; contributions are very
welcome. Some tests are/will be slightly annoying to write, since the
expected output depends on stuff like CONFIG_*, sizeof(long), runtime
values etc.

Signed-off-by: Rasmus Villemoes 
---
 lib/Kconfig.debug |   3 +
 lib/Makefile  |   1 +
 lib/test_printf.c | 364 ++
 3 files changed, 368 insertions(+)
 create mode 100644 lib/test_printf.c

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index ab76b99adc85..c23fc42dc659 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1685,6 +1685,9 @@ config TEST_STRING_HELPERS
 config TEST_KSTRTOX
tristate "Test kstrto*() family of functions at runtime"
 
+config TEST_PRINTF
+   tristate "Test printf() family of functions at runtime"
+
 config TEST_RHASHTABLE
tristate "Perform selftest on resizable hash table"
default n
diff --git a/lib/Makefile b/lib/Makefile
index 13a7c6ae3fec..775de427ea92 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
 obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
 obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o
 obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
+obj-$(CONFIG_TEST_PRINTF) += test_printf.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/test_printf.c b/lib/test_printf.c
new file mode 100644
index ..d9a2741c2909
--- /dev/null
+++ b/lib/test_printf.c
@@ -0,0 +1,364 @@
+/*
+ * Test cases for printf facility.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#define BUF_SIZE 256
+#define FILL_CHAR '$'
+
+#define PTR1 ((void*)0x01234567)
+#define PTR2 ((void*)(long)(int)0xfedcba98)
+
+#if BITS_PER_LONG == 64
+#define PTR1_ZEROES "0"
+#define PTR1_SPACES " "
+#define PTR1_STR "1234567"
+#define PTR2_STR "fedcba98"
+#define PTR_WIDTH 16
+#else
+#define PTR1_ZEROES "0"
+#define PTR1_SPACES " "
+#define PTR1_STR "1234567"
+#define PTR2_STR "fedcba98"
+#define PTR_WIDTH 8
+#endif
+#define PTR_WIDTH_STR stringify(PTR_WIDTH)
+
+static unsigned total_tests __initdata;
+static unsigned failed_tests __initdata;
+static char *test_buffer __initdata;
+
+static int __printf(4, 0) __init
+do_test(int bufsize, const char *expect, int elen,
+   const char *fmt, va_list ap)
+{
+   va_list aq;
+   int ret, written;
+
+   total_tests++;
+
+   memset(test_buffer, FILL_CHAR, BUF_SIZE);
+   va_copy(aq, ap);
+   ret = vsnprintf(test_buffer, bufsize, fmt, aq);
+   va_end(aq);
+
+   if (ret != elen) {
+   pr_warn("bad return value, expected %d, got %d, format was 
'%s'\n",
+   elen, ret, fmt);
+   return 1;
+   }
+
+   if (!bufsize) {
+   if (memchr_inv(test_buffer, FILL_CHAR, BUF_SIZE)) {
+   pr_warn("vsnprintf(buf, 0, \"%s\", ...) wrote to 
buffer\n",
+   fmt);
+   return 1;
+   }
+   return 0;
+   }
+
+   written = min(bufsize-1, elen);
+   if (test_buffer[written]) {
+   pr_warn("vsnprintf(buf, %d, \"%s\", ...) did not nul-terminate 
buffer\n",
+   bufsize, fmt);
+   return 1;
+   }
+
+   if (memcmp(test_buffer, expect, written)) {
+   pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote '%s', expected 
'%.*s'\n",
+   bufsize, fmt, test_buffer, written, expect);
+   return 1;
+   }
+   return 0;
+}
+
+
+static void __printf(3, 4) __init
+__test(const char *expect, int elen, const char *fmt, ...)
+{
+   va_list ap;
+   int rand;
+   char *p;
+
+   BUG_ON(elen >= BUF_SIZE);
+
+   va_start(ap, fmt);
+
+   /*
+* Every fmt+args is subjected to four tests: Three where we
+* tell vsnprintf varying buffer sizes (plenty, not quite
+* enough and 0), and then we also test that kvasprintf would
+* be able to print it as expected.
+*/
+   failed_tests += do_test(BUF_SIZE, expect, elen, fmt, ap);
+   rand = 1 + prandom_u32_max(elen+1);
+   /* Since elen < BUF_SIZE, we have 1 

Re: [PATCH 4/4] test_printf: test printf family at runtime

2015-09-29 Thread Andy Shevchenko
On Mon, 2015-09-28 at 22:55 +0200, Rasmus Villemoes wrote:
> On Mon, Sep 28 2015, Andy Shevchenko <
> andriy.shevche...@linux.intel.com> wrote:
> 
> > On Fri, 2015-09-25 at 19:41 +0200, Rasmus Villemoes wrote:
> > > This adds a simple module for testing the kernel's printf
> > > facilities. Previously, some %p extensions have caused a wrong 
> > > return
> > > value in case the entire output didn't fit and/or been unusable 
> > > in
> > > kasprintf(). This should help catch such issues. Also, it should 
> > > help
> > > ensure that changes to the formatting algorithms don't break 
> > > anything.
> > > 
> > > I'm not sure if we have a struct dentry or struct file lying 
> > > around 
> > > at
> > > boot time or if we can fake one, but most %p extensions should be
> > > testable, as should the ordinary number and string formatting.
> > > 
> > > The nature of vararg functions means we can't use a more 
> > > conventional
> > > table-driven approach.
> > > 
> > > For now, this is mostly a skeleton; contributions are very
> > > welcome. Some tests are/will be slightly annoying to write, since 
> > > the
> > > expected output depends on stuff like CONFIG_*, sizeof(long), 
> > > runtime
> > > values etc.
> > 
> > Few comments below.


> > > +#define test(expect, fmt, ...)   
> > > \
> > > + __test(expect, strlen(expect), fmt, ##__VA_ARGS__)
> > 
> > Would be __test_m[em] / __test_s[tr] to distinguish them by name?
> 
> Erh, no. The 'mem' version will only be used in a very few cases, and 
> I
> really want the simple name "test" for the common case.

> > > +static void __init
> > > +test_basic(void)
> > > +{
> > > + test("", "");
> > > + test("100%", "100%%");
> > > + test("xxx%yyy", "xxx%cyyy", '%');
> > > + __test("xxx\0yyy", 7, "xxx%cyyy", '\0');
> > 
> > And such pieces will be look better
> > 
> > __test_str("xxx%yyy", "xxx%cyyy", '%');
> > __test_mem("xxx\0yyy", 7, "xxx%cyyy", '\0');
> 
> I don't agree. 

It's still better to distinguish what function does by names
test vs. __test confuses me.

But whatever, this is a test suite, not an actual code anyway.

> >Maybe commentary delimiter here and above where you have double
> >empty
> >line.
> 
> And say what? I can avoid double empty lines if they bother you.

So, what was the reason to add them in the first place?

> > > +
> > > +MODULE_AUTHOR("Rasmus Villemoes ");
> > > +MODULE_LICENSE("GPL");
> > 
> > GPL or ?..
> 
> Honestly, I don't really care. Would you like BSD/GPL or what? I just
> copied from the majority of MODULE_LICENSE() instances.

You are the author, your choice. I'm okay with any applicable type.

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


Re: [PATCH 4/4] test_printf: test printf family at runtime

2015-09-30 Thread Rasmus Villemoes
On Wed, Sep 30 2015, Andy Shevchenko  wrote:

> It's still better to distinguish what function does by names
> test vs. __test confuses me.

Think of test() as the ordinary "public" interface and __test() as
"private, but we expose it because you might need it, if you know what
you're doing". Having two related functions named like this is a
perfectly normal pattern in the kernel (even if one isn't necessarily
implemented in terms of the other); examples are
legio. krealloc/__krealloc (the latter is not called krealloc_nofree),
fls/__fls (not fls_I_know_word_is_nonzero, thank $deity), ...

>> >Maybe commentary delimiter here and above where you have double
>> >empty line.
>> 
>> And say what? I can avoid double empty lines if they bother you.
>
> So, what was the reason to add them in the first place?

Just so we could have this interesting little chat. I don't think it was
intentional, but don't worry, they're gone.

>> > > +MODULE_AUTHOR("Rasmus Villemoes ");
>> > > +MODULE_LICENSE("GPL");
>> > 
>> > GPL or ?..
>> 
>> Honestly, I don't really care. Would you like BSD/GPL or what? I just
>> copied from the majority of MODULE_LICENSE() instances.
>
> You are the author, your choice. I'm okay with any applicable type.

Then I'll stick to GPL, even if that's more cargo-culting than
deliberate informed choice.

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


Re: [PATCH 4/4] test_printf: test printf family at runtime

2015-09-30 Thread Rasmus Villemoes
On Tue, Sep 29 2015, Kees Cook  wrote:

> On Tue, Sep 29, 2015 at 12:10 AM, Rasmus Villemoes
>  wrote:
>
>> I guess I could, but do we really want to intentionally trigger
>> WARN_ON_ONCEs? Say some distro chooses to load this module at boot
>> time, then we'd both spam the kernel log with "false positives", and
>> we'd have effectively disabled the WARN_ON_ONCEs for the actual
>> kernel code.
>
> Distros don't tend to run the test modules by default. The most common
> case is that it's part of a selftests run, in which case the machine
> has usually been freshly booted, etc. I think it's more important to
> catch regressions.
>
>> Maybe we can hide such things behind some module parameter, so that the
>> user explicitly has to ask for them. Also, we can't really probe the
>> "success" if these sanity checks from within the module (can we?) - the
>> user would have to check dmesg manually anyway.
>
> I think it's best that tests run with as few options as possible.
> Surely we can test the behavior? The bstr returns 0, so the string
> should be truncated? I haven't looked closely, but it seemed testable.

Well, yes, obviously we can check that part, but I also think it would
be nice to check that it actually resulted in a warning, which is what I
think would require manual inspection.

I'm still not convinced intentionally triggering a WARN on module load
is a good idea, even if the module wouldn't be loaded by normal
distros. Especially because of the _ONCE part, so that actual bugs might
not be warned about for the rest of that boot's lifetime. I'd certainly
like to hear what others think about this.

>>> I love tests! Thank you. :) One suggestion would be to wire it up to
>>> the tools/testing/selftests tree; it should be trivial once you change
>>> the test_printf_init return code.
>>
>> I'll look into that. Not sure I have too much time to work on this this
>> side of the merge window, and since these all seem to be things that can
>> be incrementally added, I'd prefer seeing something go into 4.4 instead
>> of waiting till it's "perfect". So unless I hear otherwise, I'll post a
>> v2 with the minor things addressed and ask Andrew to take that through
>> -mm.
>
> I'll send the glue patch...

Thanks. v2 coming up. For now I'll just change the return code; we can
always add tests for the sanity checks later, when we figure out the
best way to do them.

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


Re: [PATCH 4/4] test_printf: test printf family at runtime

2015-09-28 Thread Andy Shevchenko
On Fri, 2015-09-25 at 19:41 +0200, Rasmus Villemoes wrote:
> This adds a simple module for testing the kernel's printf
> facilities. Previously, some %p extensions have caused a wrong return
> value in case the entire output didn't fit and/or been unusable in
> kasprintf(). This should help catch such issues. Also, it should help
> ensure that changes to the formatting algorithms don't break 
> anything.
> 
> I'm not sure if we have a struct dentry or struct file lying around 
> at
> boot time or if we can fake one, but most %p extensions should be
> testable, as should the ordinary number and string formatting.
> 
> The nature of vararg functions means we can't use a more conventional
> table-driven approach.
> 
> For now, this is mostly a skeleton; contributions are very
> welcome. Some tests are/will be slightly annoying to write, since the
> expected output depends on stuff like CONFIG_*, sizeof(long), runtime
> values etc.

Few comments below.

> 
> Signed-off-by: Rasmus Villemoes 
> ---
>  lib/Kconfig.debug |   3 +
>  lib/Makefile  |   1 +
>  lib/test_printf.c | 364 
> ++
>  3 files changed, 368 insertions(+)
>  create mode 100644 lib/test_printf.c
> 
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index ab76b99adc85..c23fc42dc659 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -1685,6 +1685,9 @@ config TEST_STRING_HELPERS
>  config TEST_KSTRTOX
>   tristate "Test kstrto*() family of functions at runtime"
>  
> +config TEST_PRINTF
> + tristate "Test printf() family of functions at runtime"
> +
>  config TEST_RHASHTABLE
>   tristate "Perform selftest on resizable hash table"
>   default n
> diff --git a/lib/Makefile b/lib/Makefile
> index 13a7c6ae3fec..775de427ea92 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -41,6 +41,7 @@ obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
>  obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
>  obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o
>  obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
> +obj-$(CONFIG_TEST_PRINTF) += test_printf.o
>  
>  ifeq ($(CONFIG_DEBUG_KOBJECT),y)
>  CFLAGS_kobject.o += -DDEBUG
> diff --git a/lib/test_printf.c b/lib/test_printf.c
> new file mode 100644
> index ..d9a2741c2909
> --- /dev/null
> +++ b/lib/test_printf.c
> @@ -0,0 +1,364 @@
> +/*
> + * Test cases for printf facility.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +
> +#define BUF_SIZE 256
> +#define FILL_CHAR '$'
> +
> +#define PTR1 ((void*)0x01234567)
> +#define PTR2 ((void*)(long)(int)0xfedcba98)
> +
> +#if BITS_PER_LONG == 64
> +#define PTR1_ZEROES "0"
> +#define PTR1_SPACES " "
> +#define PTR1_STR "1234567"
> +#define PTR2_STR "fedcba98"
> +#define PTR_WIDTH 16
> +#else
> +#define PTR1_ZEROES "0"
> +#define PTR1_SPACES " "
> +#define PTR1_STR "1234567"
> +#define PTR2_STR "fedcba98"
> +#define PTR_WIDTH 8
> +#endif
> +#define PTR_WIDTH_STR stringify(PTR_WIDTH)
> +
> +static unsigned total_tests __initdata;
> +static unsigned failed_tests __initdata;
> +static char *test_buffer __initdata;
> +
> +static int __printf(4, 0) __init
> +do_test(int bufsize, const char *expect, int elen,
> + const char *fmt, va_list ap)
> +{
> + va_list aq;
> + int ret, written;
> +
> + total_tests++;
> +
> + memset(test_buffer, FILL_CHAR, BUF_SIZE);
> + va_copy(aq, ap);
> + ret = vsnprintf(test_buffer, bufsize, fmt, aq);
> + va_end(aq);
> +
> + if (ret != elen) {
> + pr_warn("bad return value, expected %d, got %d, 
> format was '%s'\n",
> + elen, ret, fmt);
> + return 1;
> + }
> +
> + if (!bufsize) {
> + if (memchr_inv(test_buffer, FILL_CHAR, BUF_SIZE)) {
> + pr_warn("vsnprintf(buf, 0, \"%s\", ...) 
> wrote to buffer\n",
> + fmt);
> + return 1;
> + }
> + return 0;
> + }
> +
> + written = min(bufsize-1, elen);
> + if (test_buffer[written]) {
> + pr_warn("vsnprintf(buf, %d, \"%s\", ...) did not nul
> -terminate buffer\n",
> + bufsize, fmt);
> + return 1;
> + }
> +
> + if (memcmp(test_buffer, expect, written)) {
> + pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote '%s', 
> expected '%.*s'\n",
> + bufsize, fmt, test_buffer, written, expect);
> + return 1;
> + }
> + return 0;
> +}
> +
> +
> +static void __printf(3, 4) __init
> +__test(const char *expect, int elen, const char *fmt, ...)
> +{
> + va_list ap;
> + int rand;
> + char *p;
> +
> + BUG_ON(elen >= BUF_SIZE);
> +
> + va_start(ap, fmt);
> +
> + /*
> +  * Every fmt+args is subjected to four tests: Three where we
> +  * tell vsnp

Re: [PATCH 4/4] test_printf: test printf family at runtime

2015-09-28 Thread Rasmus Villemoes
On Mon, Sep 28 2015, Andy Shevchenko  wrote:

> On Fri, 2015-09-25 at 19:41 +0200, Rasmus Villemoes wrote:
>> This adds a simple module for testing the kernel's printf
>> facilities. Previously, some %p extensions have caused a wrong return
>> value in case the entire output didn't fit and/or been unusable in
>> kasprintf(). This should help catch such issues. Also, it should help
>> ensure that changes to the formatting algorithms don't break 
>> anything.
>> 
>> I'm not sure if we have a struct dentry or struct file lying around 
>> at
>> boot time or if we can fake one, but most %p extensions should be
>> testable, as should the ordinary number and string formatting.
>> 
>> The nature of vararg functions means we can't use a more conventional
>> table-driven approach.
>> 
>> For now, this is mostly a skeleton; contributions are very
>> welcome. Some tests are/will be slightly annoying to write, since the
>> expected output depends on stuff like CONFIG_*, sizeof(long), runtime
>> values etc.
>
> Few comments below.
>
>> +
>> +#define test(expect, fmt, ...)  \
>> +__test(expect, strlen(expect), fmt, ##__VA_ARGS__)
>
> Would be __test_m[em] / __test_s[tr] to distinguish them by name?

Erh, no. The 'mem' version will only be used in a very few cases, and I
really want the simple name "test" for the common case.

> And might be inline function?

That'd make the vararg handling more cumbersome.

>> +static void __init
>> +test_basic(void)
>> +{
>> +test("", "");
>> +test("100%", "100%%");
>> +test("xxx%yyy", "xxx%cyyy", '%');
>> +__test("xxx\0yyy", 7, "xxx%cyyy", '\0');
>
> And such pieces will be look better
>
> __test_str("xxx%yyy", "xxx%cyyy", '%');
> __test_mem("xxx\0yyy", 7, "xxx%cyyy", '\0');

I don't agree. 

>> +
>> +static void __init
>> +netdev_features(void)
>> +{
>> +}
>> +
>> +
>
> Maybe commentary delimiter here and above where you have double empty
> line.

And say what? I can avoid double empty lines if they bother you.

>> +
>> +return 0;
>
> Do we need this module in a memory?

I guess not. At first I thought it didn't really matter since all
functions and data are __init, but I suppose a little metadata would
stick around if loading is "successful". Will fix.

>> +
>> +MODULE_AUTHOR("Rasmus Villemoes ");
>> +MODULE_LICENSE("GPL");
>
> GPL or ?..

Honestly, I don't really care. Would you like BSD/GPL or what? I just
copied from the majority of MODULE_LICENSE() instances.

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


Re: [PATCH 4/4] test_printf: test printf family at runtime

2015-09-28 Thread Kees Cook
On Fri, Sep 25, 2015 at 10:41 AM, Rasmus Villemoes
 wrote:
> This adds a simple module for testing the kernel's printf
> facilities. Previously, some %p extensions have caused a wrong return
> value in case the entire output didn't fit and/or been unusable in
> kasprintf(). This should help catch such issues. Also, it should help
> ensure that changes to the formatting algorithms don't break anything.
>
> I'm not sure if we have a struct dentry or struct file lying around at
> boot time or if we can fake one, but most %p extensions should be
> testable, as should the ordinary number and string formatting.
>
> The nature of vararg functions means we can't use a more conventional
> table-driven approach.
>
> For now, this is mostly a skeleton; contributions are very
> welcome. Some tests are/will be slightly annoying to write, since the
> expected output depends on stuff like CONFIG_*, sizeof(long), runtime
> values etc.
>
> Signed-off-by: Rasmus Villemoes 
> ---
>  lib/Kconfig.debug |   3 +
>  lib/Makefile  |   1 +
>  lib/test_printf.c | 364 
> ++
>  3 files changed, 368 insertions(+)
>  create mode 100644 lib/test_printf.c
>
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index ab76b99adc85..c23fc42dc659 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -1685,6 +1685,9 @@ config TEST_STRING_HELPERS
>  config TEST_KSTRTOX
> tristate "Test kstrto*() family of functions at runtime"
>
> +config TEST_PRINTF
> +   tristate "Test printf() family of functions at runtime"
> +
>  config TEST_RHASHTABLE
> tristate "Perform selftest on resizable hash table"
> default n
> diff --git a/lib/Makefile b/lib/Makefile
> index 13a7c6ae3fec..775de427ea92 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -41,6 +41,7 @@ obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
>  obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
>  obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o
>  obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
> +obj-$(CONFIG_TEST_PRINTF) += test_printf.o
>
>  ifeq ($(CONFIG_DEBUG_KOBJECT),y)
>  CFLAGS_kobject.o += -DDEBUG
> diff --git a/lib/test_printf.c b/lib/test_printf.c
> new file mode 100644
> index ..d9a2741c2909
> --- /dev/null
> +++ b/lib/test_printf.c
> @@ -0,0 +1,364 @@
> +/*
> + * Test cases for printf facility.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +
> +#define BUF_SIZE 256
> +#define FILL_CHAR '$'
> +
> +#define PTR1 ((void*)0x01234567)
> +#define PTR2 ((void*)(long)(int)0xfedcba98)
> +
> +#if BITS_PER_LONG == 64
> +#define PTR1_ZEROES "0"
> +#define PTR1_SPACES " "
> +#define PTR1_STR "1234567"
> +#define PTR2_STR "fedcba98"
> +#define PTR_WIDTH 16
> +#else
> +#define PTR1_ZEROES "0"
> +#define PTR1_SPACES " "
> +#define PTR1_STR "1234567"
> +#define PTR2_STR "fedcba98"
> +#define PTR_WIDTH 8
> +#endif
> +#define PTR_WIDTH_STR stringify(PTR_WIDTH)
> +
> +static unsigned total_tests __initdata;
> +static unsigned failed_tests __initdata;
> +static char *test_buffer __initdata;
> +
> +static int __printf(4, 0) __init
> +do_test(int bufsize, const char *expect, int elen,
> +   const char *fmt, va_list ap)
> +{
> +   va_list aq;
> +   int ret, written;
> +
> +   total_tests++;
> +
> +   memset(test_buffer, FILL_CHAR, BUF_SIZE);
> +   va_copy(aq, ap);
> +   ret = vsnprintf(test_buffer, bufsize, fmt, aq);
> +   va_end(aq);
> +
> +   if (ret != elen) {
> +   pr_warn("bad return value, expected %d, got %d, format was 
> '%s'\n",
> +   elen, ret, fmt);
> +   return 1;
> +   }
> +
> +   if (!bufsize) {
> +   if (memchr_inv(test_buffer, FILL_CHAR, BUF_SIZE)) {
> +   pr_warn("vsnprintf(buf, 0, \"%s\", ...) wrote to 
> buffer\n",
> +   fmt);
> +   return 1;
> +   }
> +   return 0;
> +   }
> +
> +   written = min(bufsize-1, elen);
> +   if (test_buffer[written]) {
> +   pr_warn("vsnprintf(buf, %d, \"%s\", ...) did not 
> nul-terminate buffer\n",
> +   bufsize, fmt);
> +   return 1;
> +   }
> +
> +   if (memcmp(test_buffer, expect, written)) {
> +   pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote '%s', expected 
> '%.*s'\n",
> +   bufsize, fmt, test_buffer, written, expect);
> +   return 1;
> +   }
> +   return 0;
> +}
> +
> +
> +static void __printf(3, 4) __init
> +__test(const char *expect, int elen, const char *fmt, ...)
> +{
> +   va_list ap;
> +   int rand;
> +   char *p;
> +
> +   BUG_ON(elen >= BUF_SIZE);
> +
> +   va_start(ap, fmt);
> +
> +   /*
> +* Every fmt+args is subjected

Re: [PATCH 4/4] test_printf: test printf family at runtime

2015-09-29 Thread Rasmus Villemoes
On Tue, Sep 29 2015, Kees Cook  wrote:

>> +static void __init
>> +test_string(void)
>> +{
>> +   test("", "%s%.0s", "", "123");
>> +   test("ABCD|abc|123", "%s|%.3s|%.*s", "ABCD", "abcdef", 3, "123456");
>> +   test("1  |  2|3  |  4|5  ", "%-3s|%3s|%-*s|%*s|%*s", "1", "2", 3, 
>> "3", 3, "4", -3, "5");
>> +   /*
>> +* POSIX and C99 say that a missing precision should be
>> +* treated as a precision of 0. However, the kernel's printf
>> +* implementation treats this case as if the . wasn't
>> +* present. Let's add a test case documenting the current
>> +* behaviour; should anyone ever feel the need to follow the
>> +* standards more closely, this can be revisited.
>> +*/
>> +   test("a||", "%.s|%.0s|%.*s", "a", "b", 0, "c");
>> +   test("a  |   |   ", "%-3.s|%-3.0s|%-3.*s", "a", "b", 0, "c");
>> +}
>
> Could you add a test for your 2/4 patch (bstr_printf size > INT_MAX
> change) as well?

I suppose you'd also want checks for the somewhat more important
vsnprintf size check and unknown specifiers? I guess I could, but do we
really want to intentionally trigger WARN_ON_ONCEs? Say some distro
chooses to load this module at boot time, then we'd both spam the kernel
log with "false positives", and we'd have effectively disabled the
WARN_ON_ONCEs for the actual kernel code.

Maybe we can hide such things behind some module parameter, so that the
user explicitly has to ask for them. Also, we can't really probe the
"success" if these sanity checks from within the module (can we?) - the
user would have to check dmesg manually anyway.

>> +
>> +static void __init
>> +dentry(void)
>> +{
>> +}
>> +
>> +static void __init
>> +struct_va_format(void)
>> +{
>> +}
>> +
>> +static void __init
>> +struct_clk(void)
>> +{
>> +}
>
> For the empty functions, maybe just add a pr_info("TODO: struct_clk")
> or something?

I think that would be unnecessarily spammy. It should be obvious from
the code that it is just waiting for someone to fill in the blanks.

>> +static int __init
>> +test_printf_init(void)
>> +{
>> +   test_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
>> +   if (!test_buffer)
>> +   return -ENOMEM;
>> +
>> +   test_basic();
>> +   test_number();
>> +   test_string();
>> +   test_pointer();
>> +
>> +   kfree(test_buffer);
>> +
>> +   if (failed_tests == 0)
>> +   pr_info("all %u tests passed\n", total_tests);
>> +   else
>> +   pr_warn("failed %u out of %u tests\n", failed_tests, 
>> total_tests);
>> +
>> +   return 0;
>> +}
>
> I actually have different feedback on leaving the module loaded: I
> think it should succeed to load when the tests pass and fail when they
> don't. This makes it a one-step test to check things ("what is
> modprobe's return code?"), instead of needed to parse dmesg.

Hm, I guess that makes sense. But, assuming we go with the module param
suggested above, would it be possible to (unload and) load with a
different set of parameters? 

> I love tests! Thank you. :) One suggestion would be to wire it up to
> the tools/testing/selftests tree; it should be trivial once you change
> the test_printf_init return code.

I'll look into that. Not sure I have too much time to work on this this
side of the merge window, and since these all seem to be things that can
be incrementally added, I'd prefer seeing something go into 4.4 instead
of waiting till it's "perfect". So unless I hear otherwise, I'll post a
v2 with the minor things addressed and ask Andrew to take that through
-mm.

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


Re: [PATCH 4/4] test_printf: test printf family at runtime

2015-09-29 Thread Kees Cook
On Tue, Sep 29, 2015 at 12:10 AM, Rasmus Villemoes
 wrote:
> On Tue, Sep 29 2015, Kees Cook  wrote:
>
>>> +static void __init
>>> +test_string(void)
>>> +{
>>> +   test("", "%s%.0s", "", "123");
>>> +   test("ABCD|abc|123", "%s|%.3s|%.*s", "ABCD", "abcdef", 3, "123456");
>>> +   test("1  |  2|3  |  4|5  ", "%-3s|%3s|%-*s|%*s|%*s", "1", "2", 3, 
>>> "3", 3, "4", -3, "5");
>>> +   /*
>>> +* POSIX and C99 say that a missing precision should be
>>> +* treated as a precision of 0. However, the kernel's printf
>>> +* implementation treats this case as if the . wasn't
>>> +* present. Let's add a test case documenting the current
>>> +* behaviour; should anyone ever feel the need to follow the
>>> +* standards more closely, this can be revisited.
>>> +*/
>>> +   test("a||", "%.s|%.0s|%.*s", "a", "b", 0, "c");
>>> +   test("a  |   |   ", "%-3.s|%-3.0s|%-3.*s", "a", "b", 0, "c");
>>> +}
>>
>> Could you add a test for your 2/4 patch (bstr_printf size > INT_MAX
>> change) as well?
>
> I suppose you'd also want checks for the somewhat more important
> vsnprintf size check and unknown specifiers? I guess I could, but do we
> really want to intentionally trigger WARN_ON_ONCEs? Say some distro
> chooses to load this module at boot time, then we'd both spam the kernel
> log with "false positives", and we'd have effectively disabled the
> WARN_ON_ONCEs for the actual kernel code.

Distros don't tend to run the test modules by default. The most common
case is that it's part of a selftests run, in which case the machine
has usually been freshly booted, etc. I think it's more important to
catch regressions.

> Maybe we can hide such things behind some module parameter, so that the
> user explicitly has to ask for them. Also, we can't really probe the
> "success" if these sanity checks from within the module (can we?) - the
> user would have to check dmesg manually anyway.

I think it's best that tests run with as few options as possible.
Surely we can test the behavior? The bstr returns 0, so the string
should be truncated? I haven't looked closely, but it seemed testable.

>
>>> +
>>> +static void __init
>>> +dentry(void)
>>> +{
>>> +}
>>> +
>>> +static void __init
>>> +struct_va_format(void)
>>> +{
>>> +}
>>> +
>>> +static void __init
>>> +struct_clk(void)
>>> +{
>>> +}
>>
>> For the empty functions, maybe just add a pr_info("TODO: struct_clk")
>> or something?
>
> I think that would be unnecessarily spammy. It should be obvious from
> the code that it is just waiting for someone to fill in the blanks.

Ok.

>
>>> +static int __init
>>> +test_printf_init(void)
>>> +{
>>> +   test_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
>>> +   if (!test_buffer)
>>> +   return -ENOMEM;
>>> +
>>> +   test_basic();
>>> +   test_number();
>>> +   test_string();
>>> +   test_pointer();
>>> +
>>> +   kfree(test_buffer);
>>> +
>>> +   if (failed_tests == 0)
>>> +   pr_info("all %u tests passed\n", total_tests);
>>> +   else
>>> +   pr_warn("failed %u out of %u tests\n", failed_tests, 
>>> total_tests);
>>> +
>>> +   return 0;
>>> +}
>>
>> I actually have different feedback on leaving the module loaded: I
>> think it should succeed to load when the tests pass and fail when they
>> don't. This makes it a one-step test to check things ("what is
>> modprobe's return code?"), instead of needed to parse dmesg.
>
> Hm, I guess that makes sense. But, assuming we go with the module param
> suggested above, would it be possible to (unload and) load with a
> different set of parameters?

Sure, you've freed memory already, it should be entirely safe to
unload (which is what the selftests script should do anyway). I still
don't think it should have options, though.

>> I love tests! Thank you. :) One suggestion would be to wire it up to
>> the tools/testing/selftests tree; it should be trivial once you change
>> the test_printf_init return code.
>
> I'll look into that. Not sure I have too much time to work on this this
> side of the merge window, and since these all seem to be things that can
> be incrementally added, I'd prefer seeing something go into 4.4 instead
> of waiting till it's "perfect". So unless I hear otherwise, I'll post a
> v2 with the minor things addressed and ask Andrew to take that through
> -mm.

I'll send the glue patch...

-Kees

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