diff mbox series

[v5,32/38] kmsan: disable strscpy() optimization under KMSAN

Message ID 20200325161249.55095-33-glider@google.com (mailing list archive)
State New, archived
Headers show
Series Add KernelMemorySanitizer infrastructure | expand

Commit Message

Alexander Potapenko March 25, 2020, 4:12 p.m. UTC
Disable the efficient 8-byte reading under KMSAN to avoid false positives.

Signed-off-by: Alexander Potapenko <glider@google.com>
To: Alexander Potapenko <glider@google.com>
Cc: Vegard Nossum <vegard.nossum@oracle.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Marco Elver <elver@google.com>
Cc: Andrey Konovalov <andreyknvl@google.com>
Cc: linux-mm@kvack.org

---

v4:
 - actually disable the optimization under KMSAN via max=0
 - use IS_ENABLED as requested by Marco Elver

Change-Id: I25d1acf5c3df6eff85894cd94f5ddbe93308271c
---
 lib/string.c | 8 ++++++++
 1 file changed, 8 insertions(+)

Comments

Andrey Konovalov April 8, 2020, 4 p.m. UTC | #1
On Wed, Mar 25, 2020 at 5:14 PM <glider@google.com> wrote:
>
> Disable the efficient 8-byte reading under KMSAN to avoid false positives.

Another user of read_word_at_a_time() is dentry_string_cmp() in
dcache.c, should we disable it there as well?


>
> Signed-off-by: Alexander Potapenko <glider@google.com>
> To: Alexander Potapenko <glider@google.com>
> Cc: Vegard Nossum <vegard.nossum@oracle.com>
> Cc: Dmitry Vyukov <dvyukov@google.com>
> Cc: Marco Elver <elver@google.com>
> Cc: Andrey Konovalov <andreyknvl@google.com>
> Cc: linux-mm@kvack.org
>
> ---
>
> v4:
>  - actually disable the optimization under KMSAN via max=0
>  - use IS_ENABLED as requested by Marco Elver
>
> Change-Id: I25d1acf5c3df6eff85894cd94f5ddbe93308271c
> ---
>  lib/string.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/lib/string.c b/lib/string.c
> index 6012c385fb314..fec929e70f1a5 100644
> --- a/lib/string.c
> +++ b/lib/string.c
> @@ -202,6 +202,14 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
>                 max = 0;
>  #endif
>
> +       /*
> +        * read_word_at_a_time() below may read uninitialized bytes after the
> +        * trailing zero and use them in comparisons. Disable this optimization
> +        * under KMSAN to prevent false positive reports.
> +        */
> +       if (IS_ENABLED(CONFIG_KMSAN))
> +               max = 0;
> +
>         while (max >= sizeof(unsigned long)) {
>                 unsigned long c, data;
>
> --
> 2.25.1.696.g5e7596f4ac-goog
>
Alexander Potapenko April 13, 2020, 2:19 p.m. UTC | #2
On Wed, Apr 8, 2020 at 6:01 PM Andrey Konovalov <andreyknvl@google.com> wrote:
>
> On Wed, Mar 25, 2020 at 5:14 PM <glider@google.com> wrote:
> >
> > Disable the efficient 8-byte reading under KMSAN to avoid false positives.
>
> Another user of read_word_at_a_time() is dentry_string_cmp() in
> dcache.c, should we disable it there as well?
>

I think we'd better disable DCACHE_WORD_ACCESS if KMSAN is enabled.
Will do that in v6.

> >
> > Signed-off-by: Alexander Potapenko <glider@google.com>
> > To: Alexander Potapenko <glider@google.com>
> > Cc: Vegard Nossum <vegard.nossum@oracle.com>
> > Cc: Dmitry Vyukov <dvyukov@google.com>
> > Cc: Marco Elver <elver@google.com>
> > Cc: Andrey Konovalov <andreyknvl@google.com>
> > Cc: linux-mm@kvack.org
> >
> > ---
> >
> > v4:
> >  - actually disable the optimization under KMSAN via max=0
> >  - use IS_ENABLED as requested by Marco Elver
> >
> > Change-Id: I25d1acf5c3df6eff85894cd94f5ddbe93308271c
> > ---
> >  lib/string.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/lib/string.c b/lib/string.c
> > index 6012c385fb314..fec929e70f1a5 100644
> > --- a/lib/string.c
> > +++ b/lib/string.c
> > @@ -202,6 +202,14 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
> >                 max = 0;
> >  #endif
> >
> > +       /*
> > +        * read_word_at_a_time() below may read uninitialized bytes after the
> > +        * trailing zero and use them in comparisons. Disable this optimization
> > +        * under KMSAN to prevent false positive reports.
> > +        */
> > +       if (IS_ENABLED(CONFIG_KMSAN))
> > +               max = 0;
> > +
> >         while (max >= sizeof(unsigned long)) {
> >                 unsigned long c, data;
> >
> > --
> > 2.25.1.696.g5e7596f4ac-goog
> >
Steven Rostedt April 13, 2020, 3:32 p.m. UTC | #3
On Mon, 13 Apr 2020 16:19:40 +0200
Alexander Potapenko <glider@google.com> wrote:

> On Wed, Apr 8, 2020 at 6:01 PM Andrey Konovalov <andreyknvl@google.com> wrote:
> >
> > On Wed, Mar 25, 2020 at 5:14 PM <glider@google.com> wrote:  
> > >
> > > Disable the efficient 8-byte reading under KMSAN to avoid false positives.  
> >
> > Another user of read_word_at_a_time() is dentry_string_cmp() in
> > dcache.c, should we disable it there as well?
> >  
> 
> I think we'd better disable DCACHE_WORD_ACCESS if KMSAN is enabled.
> Will do that in v6.
> 
> > >
> > > Signed-off-by: Alexander Potapenko <glider@google.com>
> > > To: Alexander Potapenko <glider@google.com>
> > > Cc: Vegard Nossum <vegard.nossum@oracle.com>
> > > Cc: Dmitry Vyukov <dvyukov@google.com>
> > > Cc: Marco Elver <elver@google.com>
> > > Cc: Andrey Konovalov <andreyknvl@google.com>
> > > Cc: linux-mm@kvack.org
> > >
> > > ---
> > >
> > > v4:
> > >  - actually disable the optimization under KMSAN via max=0
> > >  - use IS_ENABLED as requested by Marco Elver
> > >
> > > Change-Id: I25d1acf5c3df6eff85894cd94f5ddbe93308271c
> > > ---
> > >  lib/string.c | 8 ++++++++
> > >  1 file changed, 8 insertions(+)
> > >
> > > diff --git a/lib/string.c b/lib/string.c
> > > index 6012c385fb314..fec929e70f1a5 100644
> > > --- a/lib/string.c
> > > +++ b/lib/string.c
> > > @@ -202,6 +202,14 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
> > >                 max = 0;
> > >  #endif
> > >
> > > +       /*
> > > +        * read_word_at_a_time() below may read uninitialized bytes after the
> > > +        * trailing zero and use them in comparisons. Disable this optimization
> > > +        * under KMSAN to prevent false positive reports.
> > > +        */
> > > +       if (IS_ENABLED(CONFIG_KMSAN))
> > > +               max = 0;
> > > +

Instead of disabling the optimization, can't you make KMSAN aware of the
"has_zero()" call (which I believe is the part that will trip up KMSAN) and
just not report it?

-- Steve


> > >         while (max >= sizeof(unsigned long)) {
> > >                 unsigned long c, data;
> > >
> > > --
> > > 2.25.1.696.g5e7596f4ac-goog
> > >  
> 
> 
>
Alexander Potapenko April 13, 2020, 4:16 p.m. UTC | #4
>
> Instead of disabling the optimization, can't you make KMSAN aware of the
> "has_zero()" call (which I believe is the part that will trip up KMSAN) and
> just not report it?
>
> -- Steve

I don't think this is the right thing to do.
If we read a short string - e.g. only 4 bytes long, using
read_word_at_a_time(), we'll also read uninitialized bytes after the
trailing zero, which will lead to false positives we're trying to
avoid.
But if there's no trailing zero, or if the first 4 bytes are
uninitialized as well, we want to catch that, so we must not ignore
functions that operate on those bytes.
We could theoretically make read_word_at_a_time() mask out the bytes
past the trailing zero in KMSAN mode, but IIUC that function may read
binary data as well.
diff mbox series

Patch

diff --git a/lib/string.c b/lib/string.c
index 6012c385fb314..fec929e70f1a5 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -202,6 +202,14 @@  ssize_t strscpy(char *dest, const char *src, size_t count)
 		max = 0;
 #endif
 
+	/*
+	 * read_word_at_a_time() below may read uninitialized bytes after the
+	 * trailing zero and use them in comparisons. Disable this optimization
+	 * under KMSAN to prevent false positive reports.
+	 */
+	if (IS_ENABLED(CONFIG_KMSAN))
+		max = 0;
+
 	while (max >= sizeof(unsigned long)) {
 		unsigned long c, data;