On Tue, Feb 12, 2019 at 06:02:24PM +0000, Catalin Marinas wrote:
On Mon, Feb 11, 2019 at 12:32:55PM -0800, Evgenii Stepanov wrote:[...]
On Mon, Feb 11, 2019 at 9:28 AM Kevin Brodsky <kevin.brodsky@xxxxxxx> wrote:
On 19/12/2018 12:52, Dave Martin wrote:
My aim was to clarify the use case in userspace, since I wasn't directlyAll the above sound well but that's mostly a guideline on what a C* A single C object should be accessed using a single, fixedAgreed. Allocators themselves may need to be excluded though,
pointer tag throughout its entire lifetime.
depending on how they represent their managed memory.
* Tags can be changed only when there are no outstanding pointers toTags can only be changed at the point of deallocation/
the affected object or region that may be used to access the object
or region (i.e., if the object were allocated from the C heap and
is it safe to realloc() it, then it is safe to change the tag; for
other types of allocation, analogous arguments can be applied).
reallocation. Pointers to the object become invalid and cannot
be used after it has been deallocated; memory tagging allows to
catch such invalid usage.
library can do. It doesn't help much with defining the kernel ABI.
Anyway, it's good to clarify the use-cases.
involved in that. The kernel ABI needs to be compatible with the the
use case, but doesn't need to specify must of it.
I'm wondering whether we can piggy-back on existing concepts.
We could say that recolouring memory is safe when and only when
unmapping of the page or removing permissions on the page (via
munmap/mremap/mprotect) would be safe. Otherwise, the resulting
behaviour of the process is undefined.
Hopefully there are friendly fuzzers testing this kind of thing.
[...]
Also put_user() and friends?It would also be valuable to narrow down the set of "relaxed" (i.e.I lost track of the context of this thread but if it's just about
not tag-checking) syscalls as reasonably possible. We would want to
provide tag-checking userspace wrappers for any important calls that
are not checked in the kernel. Is it correct to assume that anything
that goes through copy_from_user / copy_to_user is checked?
relaxing the ABI for hwasan, the kernel has no idea of the compiler
generated structures in user space, so nothing is checked.
If we talk about tags in the context of MTE, than yes, with the current
proposal the tag would be checked by copy_*_user() functions.
It might be reasonable to do the check in access_ok() and skip it in
__put_user() etc.
(I seem to remember some separate discussion about abolishing
__put_user() and friends though, due to the accident risk they pose.)
This is probably reasonable.For aio* operations it would be nice if the tag was checked at theWith aio* (and synchronous iovec-based syscalls), the kernel may access
time of the actual userspace read/write, either instead of or in
addition to at the time of the system call.
the memory while the corresponding user process is scheduled out. Given
that such access is not done in the context of the user process (and
using the user VA like copy_*_user), the kernel cannot handle potential
tag faults. Moreover, the transfer may be done by DMA and the device
does not understand tags.
I'd like to keep tags as a property of the pointer in a specific virtual
address space. The moment you convert it to a different address space
(e.g. kernel linear map, physical address), the tag property is stripped
and I don't think we should re-build it (and have it checked).
Ideally we would check the tag at the point of stripping it off, but
most likely it's going to be rather best-effort.
If memory tagging is essential a debugging feature then this seems
an acceptable compromise.
I think that if the page range is all the same colour then it should beI don't think mprotect() over differently tagged pages was ever aYes, it would be nice if the kernel explicitly promised, ex.* For purposes other than dereference, the kernel shall accept anyThis is a disputed point :) In my opinion, this is the the most
legitimately tagged pointer (according to the above rules) as
identifying the associated memory location.
So, mprotect(some_page_aligned_object, ...); is valid irrespective
of where page_aligned_object() came from. There is no implicit
derefence by the kernel here, hence no tag check.
The kernel does not guarantee to work correctly if the wrong tag
is used, but there is not always a well-defined "right" tag, so
we can't really guarantee to check it. So a pointer derived by
any reasonable means by userspace has to be treated as equally
valid.
reasonable approach.
mprotect() over a range of differently tagged pages to be allowed
(i.e. address tag should be unchecked).
problem. I originally asked that mprotect() and friends do not accept
tagged pointers since these functions deal with memory ranges rather
than dereferencing such pointer (the reason being minimal kernel
changes). However, given how complicated it is to specify an ABI, I came
to the conclusion that a pointer passed to such function should be
allowed to have non-zero top byte. It would be the kernel's
responsibility to strip it out as appropriate.
legitimate to pass a matching tag.
But it doesn't seem reasonable for the kernel to require this. If
free() calls munmap(), the page(s) will contain possibly randomly-
coloured garbage. There's no correct tag to pass in such a case.
The most obvious solution is just to ignore the tags passed by userspace
to such syscalls. This would imply that the kernel must explicitly
strip it out, as you suggest.
The number of affected syscalls is relatively small though.
Cheers
---Dave