On 2018-04-04 10:58, Petr Mladek wrote: > diff --git a/lib/vsprintf.c b/lib/vsprintf.c > index 3551b7957d9e..1a080a75a825 100644 > --- a/lib/vsprintf.c > +++ b/lib/vsprintf.c > @@ -599,12 +599,46 @@ char *__string(char *buf, char *end, const char *s, > struct printf_spec spec) > return widen_string(buf, len, end, spec); > } > > + /* > + * This is not a fool-proof test. 99% of the time that this will fault is > + * due to a bad pointer, not one that crosses into bad memory. Just test > + * the address to make sure it doesn't fault due to a poorly added printk > + * during debugging. > + */ > +static const char *check_pointer_access(const void *ptr) > +{ > + char byte; > + > + if (!ptr) > + return "(null)"; > + > + if (probe_kernel_address(ptr, byte)) > + return "(efault)"; > + > + return NULL; > +} > + > + > +static bool valid_pointer_access(char **buf, char *end, const void *ptr, > + struct printf_spec spec) > +{ > + const char *err_msg; > + > + err_msg = check_pointer_access(ptr); > + if (err_msg) { > + *buf = __string(*buf, end, err_msg, spec); > + return false; > + } > + > + return true; > +} > + > static noinline_for_stack > char *string(char *buf, char *end, const char *s, > struct printf_spec spec) > { > - if ((unsigned long)s < PAGE_SIZE) > - s = "(null)"; > + if (!valid_pointer_access(&buf, end, s, spec)) > + return buf; > > return __string(buf, end, s, spec); > }
Obviously, if you do add a WARN to the check_pointer_access (and please do), that somehow needs to be suppressed for the "%s", NULL and "%s", ZEROPTR cases, which are grandfathered in and I think is relied upon in some places. It should be as simple as keeping the < PAGE_SIZE check and do "else if (!valid...())". Rasmus