Re: [PATCH v6 11/11] arm64: annotate user pointers casts detected by sparse

From: Linus Torvalds
Date: Fri Sep 07 2018 - 12:30:51 EST


On Fri, Sep 7, 2018 at 8:26 AM Catalin Marinas <catalin.marinas@xxxxxxx> wrote:
>
> So it's not about casting to another pointer; it's rather about no
> longer using the value as a user pointer but as an actual (untyped,
> untagged) virtual address.
>
> There may be better options to address this but I haven't seen any
> concrete proposal so far. Or we could simply consider that we've found
> all places where it matters and not bother with any static analysis
> tools (but for the time being it's still worth investigating whether we
> can do better than this).

I actually originally wanted to have sparse not just check types, but
actually do transformations too, in order to check more.

For example, for just the user pointer case, we actually have two
wildy different kinds of user pointers: "checked" user pointers and
"wild" user pointers.

Most of the time it doesn't matter, but it does for the unsafe ones:
"__get_user()" and friends.

So long long ago I wanted sparse to not just do the completely static
type analysis, but also do actual "data flow" analysis where doing an
"access_on()" on a pointer would turn it from "wild" to "checked", and
then I could have warned about "hey, this function does __get_user(),
but the flow analysis shows that you passed it a pointer that had
never been checked".

But sparse never ended up doing that kind of much smarter things. Some
of the lock context stuff does it on a very small local level, and not
very well there either.

But it sounds like this is exactly what you guys would want for the
tagged pointers. Some functions can take a "wild" pointer, because
they deal with the tag part natively. And others need to be "checked"
and have gone through the cleaning and verification.

But sparse is sadly not the right tool for this, and having a single
"__user" address space is not sufficient. I guess for the arm64 case,
you really could make up a *new* address space: "__user_untagged", and
then have functions that convert from "void __user *" to "void
__user_untagged *", and then mark the functions that need the tag
removed as taking that new kind of user pointer.

And if you never mix types, that would actually work. But I'm guessing
you can also pass "__user_untagged" pointers to the regular user
access functions, and you do?

Linus