diff mbox series

[RFC,v2,6/6] prctl.2: Add tagged address ABI control prctls (arm64)

Message ID 1590614258-24728-7-git-send-email-Dave.Martin@arm.com (mailing list archive)
State New, archived
Headers show
Series prctl.2 man page updates for Linux 5.6 | expand

Commit Message

Dave Martin May 27, 2020, 9:17 p.m. UTC
** This patch is a draft for review and should not be applied before it
   has been discussed. **

Add documentation for the the PR_SET_TAGGED_ADDR_CTRL and
PR_GET_TAGGED_ADDR_CTRL prctls added in Linux 5.4 for arm64.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
---

 man2/prctl.2 | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 156 insertions(+)

Comments

Michael Kerrisk (man-pages) June 9, 2020, 11:04 a.m. UTC | #1
Hey folks,

Do we have any review comments for this (extensive!) patch from Dave?

Cheers,

Michael


On 5/27/20 11:17 PM, Dave Martin wrote:
> ** This patch is a draft for review and should not be applied before it
>    has been discussed. **
> 
> Add documentation for the the PR_SET_TAGGED_ADDR_CTRL and
> PR_GET_TAGGED_ADDR_CTRL prctls added in Linux 5.4 for arm64.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will@kernel.org>
> Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
> ---
> 
>  man2/prctl.2 | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 156 insertions(+)
> 
> diff --git a/man2/prctl.2 b/man2/prctl.2
> index 3ee2702..062fd51 100644
> --- a/man2/prctl.2
> +++ b/man2/prctl.2
> @@ -1504,6 +1504,143 @@ For more information, see the kernel source file
>  (or
>  .I Documentation/arm64/sve.txt
>  before Linux 5.3).
> +.\" prctl PR_SET_TAGGED_ADDR_CTRL
> +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> +.TP
> +.BR PR_SET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> +Controls support for passing tagged userspace addresses to the kernel
> +(i.e., addresses where bits 56\(em63 are not all zero).
> +.IP
> +The level of support is selected by
> +.IR "(unsigned int) arg2" ,
> +which can be one of the following:
> +.RS
> +.TP
> +.B 0
> +Addresses that are passed
> +for the purpose of being dereferenced by the kernel
> +must be untagged.
> +.TP
> +.B PR_TAGGED_ADDR_ENABLE
> +Addresses that are passed
> +for the purpose of being dereferenced by the kernel
> +may be tagged, with the exceptions summarized below.
> +.RE
> +.IP
> +The remaining arguments
> +.IR arg3 ", " arg4 " and " arg5
> +must all be zero.
> +.IP
> +On success, the mode specified in
> +.I arg2
> +is set for the calling thread and the the return value is 0.
> +If the arguments are invalid,
> +the mode specified in
> +.I arg2
> +is unrecognized,
> +or if this feature is disabled or unsupported by the kernel,
> +the call fails with
> +.BR EINVAL .
> +.IP
> +In particular, if
> +.BR prctl ( PR_SET_TAGGED_ADDR_CTRL ,
> +0, 0, 0, 0)
> +fails with
> +.B EINVAL
> +then all addresses passed to the kernel must be untagged.
> +.IP
> +Irrespective of which mode is set,
> +addresses passed to certain interfaces
> +must always be untagged:
> +.RS
> +.IP \(em
> +.BR brk (2),
> +.BR mmap (2),
> +.BR shmat (2),
> +and the
> +.I new_address
> +argument of
> +.BR mremap (2).
> +.IP
> +(Prior to Linux 5.6 these accepted tagged addresses,
> +but the behaviour may not be what you expect.
> +Don't rely on it.)
> +.IP \(em
> +\(oqpolymorphic\(cq interfaces
> +that accept pointers to arbitrary types cast to a
> +.I void *
> +or other generic type, specifically
> +.BR prctl (2),
> +.BR ioctl (2),
> +and in general
> +.BR setsockopt (2)
> +(only certain specific
> +.BR setsockopt (2)
> +options allow tagged addresses).
> +.IP \(em
> +.BR shmdt (2).
> +.RE
> +.IP
> +This list of exclusions may shrink
> +when moving from one kernel version to a later kernel version.
> +While the kernel may make some guarantees
> +for backwards compatibility reasons,
> +for the purposes of new software
> +the effect of passing tagged addresses to these interfaces
> +is unspecified.
> +.IP
> +The mode set by this call is inherited across
> +.BR fork (2)
> +and
> +.BR clone (2).
> +The mode is reset by
> +.BR execve (2)
> +to 0
> +(i.e., tagged addresses not permitted in the user/kernel ABI).
> +.IP
> +.B Warning:
> +Because the compiler or run-time environment
> +may make use of address tagging,
> +a successful
> +.B PR_SET_TAGGED_ADDR_CTRL
> +may crash the calling process.
> +The conditions for using it safely are complex and system-dependent.
> +Don't use it unless you know what you are doing.
> +.IP
> +For more information, see the kernel source file
> +.IR Documentation/arm64/tagged\-address\-abi.rst .
> +.\" prctl PR_GET_TAGGED_ADDR_CTRL
> +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> +.TP
> +.BR PR_GET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> +Returns the current tagged address mode
> +for the calling thread.
> +.IP
> +Arguments
> +.IR arg2 ", " arg3 ", " arg4 " and " arg5
> +must all be zero.
> +.IP
> +If the arguments are invalid
> +or this feature is disabled or unsupported by the kernel,
> +the call fails with
> +.BR EINVAL .
> +In particular, if
> +.BR prctl ( PR_GET_TAGGED_ADDR_CTRL ,
> +0, 0, 0, 0)
> +fails with
> +.BR EINVAL ,
> +then this feature is definitely unsupported or disabled,
> +and all addresses passed to the kernel must be untagged.
> +.IP
> +Otherwise, the call returns a nonnegative value
> +describing the current tagged address mode,
> +encoded in the same way as the
> +.I arg2
> +argument of
> +.BR PR_SET_TAGGED_ADDR_CTRL .
> +.IP
> +For more information, see the kernel source file
> +.IR Documentation/arm64/tagged\-address\-abi.rst .
>  .\"
>  .\" prctl PR_TASK_PERF_EVENTS_DISABLE
>  .TP
> @@ -1749,6 +1886,7 @@ On success,
>  .BR PR_GET_SPECULATION_CTRL ,
>  .BR PR_SVE_GET_VL ,
>  .BR PR_SVE_SET_VL ,
> +.BR PR_GET_TAGGED_ADDR_CTRL ,
>  .BR PR_GET_THP_DISABLE ,
>  .BR PR_GET_TIMING ,
>  .BR PR_GET_TIMERSLACK ,
> @@ -2057,6 +2195,24 @@ is
>  .B PR_SVE_GET_VL
>  and SVE is not available on this platform.
>  .TP
> +.B EINVAL
> +.I option
> +is
> +.BR PR_SET_TAGGED_ADDR_CTRL
> +and the arguments are invalid or unsupported.
> +See the description of
> +.B PR_SET_TAGGED_ADDR_CTRL
> +above for details.
> +.TP
> +.B EINVAL
> +.I option
> +is
> +.BR PR_GET_TAGGED_ADDR_CTRL
> +and the arguments are invalid or unsupported.
> +See the description of
> +.B PR_GET_TAGGED_ADDR_CTRL
> +above for details.
> +.TP
>  .B ENODEV
>  .I option
>  was
>
Will Deacon June 9, 2020, 1:38 p.m. UTC | #2
On Tue, Jun 09, 2020 at 01:04:25PM +0200, Michael Kerrisk (man-pages) wrote:
> Do we have any review comments for this (extensive!) patch from Dave?

(Adding Andrey, since he was involved with this ABI)

Regardless, it would be good to have Catalin's ack and I think he was
planning to take a look at this.

Will

> On 5/27/20 11:17 PM, Dave Martin wrote:
> > ** This patch is a draft for review and should not be applied before it
> >    has been discussed. **
> > 
> > Add documentation for the the PR_SET_TAGGED_ADDR_CTRL and
> > PR_GET_TAGGED_ADDR_CTRL prctls added in Linux 5.4 for arm64.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > Cc: Will Deacon <will@kernel.org>
> > Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
> > ---
> > 
> >  man2/prctl.2 | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 156 insertions(+)
> > 
> > diff --git a/man2/prctl.2 b/man2/prctl.2
> > index 3ee2702..062fd51 100644
> > --- a/man2/prctl.2
> > +++ b/man2/prctl.2
> > @@ -1504,6 +1504,143 @@ For more information, see the kernel source file
> >  (or
> >  .I Documentation/arm64/sve.txt
> >  before Linux 5.3).
> > +.\" prctl PR_SET_TAGGED_ADDR_CTRL
> > +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> > +.TP
> > +.BR PR_SET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> > +Controls support for passing tagged userspace addresses to the kernel
> > +(i.e., addresses where bits 56\(em63 are not all zero).
> > +.IP
> > +The level of support is selected by
> > +.IR "(unsigned int) arg2" ,
> > +which can be one of the following:
> > +.RS
> > +.TP
> > +.B 0
> > +Addresses that are passed
> > +for the purpose of being dereferenced by the kernel
> > +must be untagged.
> > +.TP
> > +.B PR_TAGGED_ADDR_ENABLE
> > +Addresses that are passed
> > +for the purpose of being dereferenced by the kernel
> > +may be tagged, with the exceptions summarized below.
> > +.RE
> > +.IP
> > +The remaining arguments
> > +.IR arg3 ", " arg4 " and " arg5
> > +must all be zero.
> > +.IP
> > +On success, the mode specified in
> > +.I arg2
> > +is set for the calling thread and the the return value is 0.
> > +If the arguments are invalid,
> > +the mode specified in
> > +.I arg2
> > +is unrecognized,
> > +or if this feature is disabled or unsupported by the kernel,
> > +the call fails with
> > +.BR EINVAL .
> > +.IP
> > +In particular, if
> > +.BR prctl ( PR_SET_TAGGED_ADDR_CTRL ,
> > +0, 0, 0, 0)
> > +fails with
> > +.B EINVAL
> > +then all addresses passed to the kernel must be untagged.
> > +.IP
> > +Irrespective of which mode is set,
> > +addresses passed to certain interfaces
> > +must always be untagged:
> > +.RS
> > +.IP \(em
> > +.BR brk (2),
> > +.BR mmap (2),
> > +.BR shmat (2),
> > +and the
> > +.I new_address
> > +argument of
> > +.BR mremap (2).
> > +.IP
> > +(Prior to Linux 5.6 these accepted tagged addresses,
> > +but the behaviour may not be what you expect.
> > +Don't rely on it.)
> > +.IP \(em
> > +\(oqpolymorphic\(cq interfaces
> > +that accept pointers to arbitrary types cast to a
> > +.I void *
> > +or other generic type, specifically
> > +.BR prctl (2),
> > +.BR ioctl (2),
> > +and in general
> > +.BR setsockopt (2)
> > +(only certain specific
> > +.BR setsockopt (2)
> > +options allow tagged addresses).
> > +.IP \(em
> > +.BR shmdt (2).
> > +.RE
> > +.IP
> > +This list of exclusions may shrink
> > +when moving from one kernel version to a later kernel version.
> > +While the kernel may make some guarantees
> > +for backwards compatibility reasons,
> > +for the purposes of new software
> > +the effect of passing tagged addresses to these interfaces
> > +is unspecified.
> > +.IP
> > +The mode set by this call is inherited across
> > +.BR fork (2)
> > +and
> > +.BR clone (2).
> > +The mode is reset by
> > +.BR execve (2)
> > +to 0
> > +(i.e., tagged addresses not permitted in the user/kernel ABI).
> > +.IP
> > +.B Warning:
> > +Because the compiler or run-time environment
> > +may make use of address tagging,
> > +a successful
> > +.B PR_SET_TAGGED_ADDR_CTRL
> > +may crash the calling process.
> > +The conditions for using it safely are complex and system-dependent.
> > +Don't use it unless you know what you are doing.
> > +.IP
> > +For more information, see the kernel source file
> > +.IR Documentation/arm64/tagged\-address\-abi.rst .
> > +.\" prctl PR_GET_TAGGED_ADDR_CTRL
> > +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> > +.TP
> > +.BR PR_GET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> > +Returns the current tagged address mode
> > +for the calling thread.
> > +.IP
> > +Arguments
> > +.IR arg2 ", " arg3 ", " arg4 " and " arg5
> > +must all be zero.
> > +.IP
> > +If the arguments are invalid
> > +or this feature is disabled or unsupported by the kernel,
> > +the call fails with
> > +.BR EINVAL .
> > +In particular, if
> > +.BR prctl ( PR_GET_TAGGED_ADDR_CTRL ,
> > +0, 0, 0, 0)
> > +fails with
> > +.BR EINVAL ,
> > +then this feature is definitely unsupported or disabled,
> > +and all addresses passed to the kernel must be untagged.
> > +.IP
> > +Otherwise, the call returns a nonnegative value
> > +describing the current tagged address mode,
> > +encoded in the same way as the
> > +.I arg2
> > +argument of
> > +.BR PR_SET_TAGGED_ADDR_CTRL .
> > +.IP
> > +For more information, see the kernel source file
> > +.IR Documentation/arm64/tagged\-address\-abi.rst .
> >  .\"
> >  .\" prctl PR_TASK_PERF_EVENTS_DISABLE
> >  .TP
> > @@ -1749,6 +1886,7 @@ On success,
> >  .BR PR_GET_SPECULATION_CTRL ,
> >  .BR PR_SVE_GET_VL ,
> >  .BR PR_SVE_SET_VL ,
> > +.BR PR_GET_TAGGED_ADDR_CTRL ,
> >  .BR PR_GET_THP_DISABLE ,
> >  .BR PR_GET_TIMING ,
> >  .BR PR_GET_TIMERSLACK ,
> > @@ -2057,6 +2195,24 @@ is
> >  .B PR_SVE_GET_VL
> >  and SVE is not available on this platform.
> >  .TP
> > +.B EINVAL
> > +.I option
> > +is
> > +.BR PR_SET_TAGGED_ADDR_CTRL
> > +and the arguments are invalid or unsupported.
> > +See the description of
> > +.B PR_SET_TAGGED_ADDR_CTRL
> > +above for details.
> > +.TP
> > +.B EINVAL
> > +.I option
> > +is
> > +.BR PR_GET_TAGGED_ADDR_CTRL
> > +and the arguments are invalid or unsupported.
> > +See the description of
> > +.B PR_GET_TAGGED_ADDR_CTRL
> > +above for details.
> > +.TP
> >  .B ENODEV
> >  .I option
> >  was
> > 
> 
> 
> -- 
> Michael Kerrisk
> Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
> Linux/UNIX System Programming Training: http://man7.org/training/
Catalin Marinas June 9, 2020, 5:22 p.m. UTC | #3
Hi Dave,

On Wed, May 27, 2020 at 10:17:38PM +0100, Dave P Martin wrote:
> --- a/man2/prctl.2
> +++ b/man2/prctl.2
> @@ -1504,6 +1504,143 @@ For more information, see the kernel source file
>  (or
>  .I Documentation/arm64/sve.txt
>  before Linux 5.3).
> +.\" prctl PR_SET_TAGGED_ADDR_CTRL
> +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> +.TP
> +.BR PR_SET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> +Controls support for passing tagged userspace addresses to the kernel
> +(i.e., addresses where bits 56\(em63 are not all zero).

Nitpick: maybe say "userspace addresses" again inside the brackets since
kernel addresses have all top bits 1.

> +.IP
> +The level of support is selected by
> +.IR "(unsigned int) arg2" ,

We use (unsigned long) for arg2.

> +which can be one of the following:
> +.RS
> +.TP
> +.B 0
> +Addresses that are passed
> +for the purpose of being dereferenced by the kernel
> +must be untagged.
> +.TP
> +.B PR_TAGGED_ADDR_ENABLE
> +Addresses that are passed
> +for the purpose of being dereferenced by the kernel
> +may be tagged, with the exceptions summarized below.
> +.RE
> +.IP
> +The remaining arguments
> +.IR arg3 ", " arg4 " and " arg5
> +must all be zero.

Indeed. The above commit didn't have this, we added it later in commit
3e91ec89f527b9870fe42dcbdb74fd389d123a95.

> +.IP
> +On success, the mode specified in
> +.I arg2
> +is set for the calling thread and the the return value is 0.
> +If the arguments are invalid,
> +the mode specified in
> +.I arg2
> +is unrecognized,
> +or if this feature is disabled or unsupported by the kernel,
> +the call fails with
> +.BR EINVAL .
> +.IP
> +In particular, if
> +.BR prctl ( PR_SET_TAGGED_ADDR_CTRL ,
> +0, 0, 0, 0)
> +fails with
> +.B EINVAL
> +then all addresses passed to the kernel must be untagged.
> +.IP
> +Irrespective of which mode is set,
> +addresses passed to certain interfaces
> +must always be untagged:

Maybe you could add some extra info from the kernel comment (commit
b2a84de2a2deb76a6a51609845341f508c518c03) along the lines of "... to
avoid the creation of aliasing mappings in userspace).

> +.RS
> +.IP \(em
> +.BR brk (2),
> +.BR mmap (2),
> +.BR shmat (2),
> +and the
> +.I new_address
> +argument of
> +.BR mremap (2).
> +.IP
> +(Prior to Linux 5.6 these accepted tagged addresses,
> +but the behaviour may not be what you expect.
> +Don't rely on it.)

shmat() was not part of the subsequent fix
(dcde237319e626d1ec3c9d8b7613032f0fd4663a), it always rejected tagged
address. But I guess it doesn't matter much, the user should not pass
tagged addresses to these syscalls anyway.

You could move shmat() down together with shmdt().

> +.IP \(em
> +\(oqpolymorphic\(cq interfaces
> +that accept pointers to arbitrary types cast to a
> +.I void *
> +or other generic type, specifically
> +.BR prctl (2),
> +.BR ioctl (2),
> +and in general
> +.BR setsockopt (2)
> +(only certain specific
> +.BR setsockopt (2)
> +options allow tagged addresses).
> +.IP \(em
> +.BR shmdt (2).
> +.RE
> +.IP
> +This list of exclusions may shrink
> +when moving from one kernel version to a later kernel version.
> +While the kernel may make some guarantees
> +for backwards compatibility reasons,
> +for the purposes of new software
> +the effect of passing tagged addresses to these interfaces
> +is unspecified.
> +.IP
> +The mode set by this call is inherited across
> +.BR fork (2)
> +and
> +.BR clone (2).
> +The mode is reset by
> +.BR execve (2)
> +to 0
> +(i.e., tagged addresses not permitted in the user/kernel ABI).
> +.IP
> +.B Warning:
> +Because the compiler or run-time environment
> +may make use of address tagging,
> +a successful
> +.B PR_SET_TAGGED_ADDR_CTRL
> +may crash the calling process.

I don't think PR_SET_TAGGED_ADDR_CTRL could crash the calling process.
Rather disabling tagged addresses would break it. If a process is using
tagged addresses but does not pass them to the kernel, it will continue
to do so even when the syscalls accept such addresses.

> +The conditions for using it safely are complex and system-dependent.
> +Don't use it unless you know what you are doing.

This syscall is intended for the C library if the heap allocator
generates tagged addresses. So it's not a general purpose prctl() random
application code could call. Anyway I'm fine with your warning of not
doing it but you may want to clarify the intent.

> +.IP
> +For more information, see the kernel source file
> +.IR Documentation/arm64/tagged\-address\-abi.rst .
> +.\" prctl PR_GET_TAGGED_ADDR_CTRL
> +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> +.TP
> +.BR PR_GET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> +Returns the current tagged address mode
> +for the calling thread.
> +.IP
> +Arguments
> +.IR arg2 ", " arg3 ", " arg4 " and " arg5
> +must all be zero.
> +.IP
> +If the arguments are invalid
> +or this feature is disabled or unsupported by the kernel,
> +the call fails with
> +.BR EINVAL .
> +In particular, if
> +.BR prctl ( PR_GET_TAGGED_ADDR_CTRL ,
> +0, 0, 0, 0)
> +fails with
> +.BR EINVAL ,
> +then this feature is definitely unsupported or disabled,

I guess it's outside the scope of the prctl.2 to describe how the
feature was disabled (e.g. sysctl).

> +and all addresses passed to the kernel must be untagged.
> +.IP
> +Otherwise, the call returns a nonnegative value
> +describing the current tagged address mode,
> +encoded in the same way as the
> +.I arg2
> +argument of
> +.BR PR_SET_TAGGED_ADDR_CTRL .
> +.IP
> +For more information, see the kernel source file
> +.IR Documentation/arm64/tagged\-address\-abi.rst .
>  .\"
>  .\" prctl PR_TASK_PERF_EVENTS_DISABLE
>  .TP
> @@ -1749,6 +1886,7 @@ On success,
>  .BR PR_GET_SPECULATION_CTRL ,
>  .BR PR_SVE_GET_VL ,
>  .BR PR_SVE_SET_VL ,
> +.BR PR_GET_TAGGED_ADDR_CTRL ,
>  .BR PR_GET_THP_DISABLE ,
>  .BR PR_GET_TIMING ,
>  .BR PR_GET_TIMERSLACK ,
> @@ -2057,6 +2195,24 @@ is
>  .B PR_SVE_GET_VL
>  and SVE is not available on this platform.
>  .TP
> +.B EINVAL
> +.I option
> +is
> +.BR PR_SET_TAGGED_ADDR_CTRL
> +and the arguments are invalid or unsupported.
> +See the description of
> +.B PR_SET_TAGGED_ADDR_CTRL
> +above for details.
> +.TP
> +.B EINVAL
> +.I option
> +is
> +.BR PR_GET_TAGGED_ADDR_CTRL
> +and the arguments are invalid or unsupported.
> +See the description of
> +.B PR_GET_TAGGED_ADDR_CTRL
> +above for details.
> +.TP
>  .B ENODEV
>  .I option
>  was

Apart from some minor nits above, the documentation looks fine.

Thanks for writing this up.
Dave Martin June 10, 2020, 10:06 a.m. UTC | #4
On Tue, Jun 09, 2020 at 06:22:32PM +0100, Catalin Marinas wrote:
> Hi Dave,
> 
> On Wed, May 27, 2020 at 10:17:38PM +0100, Dave P Martin wrote:
> > --- a/man2/prctl.2
> > +++ b/man2/prctl.2
> > @@ -1504,6 +1504,143 @@ For more information, see the kernel source file
> >  (or
> >  .I Documentation/arm64/sve.txt
> >  before Linux 5.3).
> > +.\" prctl PR_SET_TAGGED_ADDR_CTRL
> > +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> > +.TP
> > +.BR PR_SET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> > +Controls support for passing tagged userspace addresses to the kernel
> > +(i.e., addresses where bits 56\(em63 are not all zero).
> 
> Nitpick: maybe say "userspace addresses" again inside the brackets since
> kernel addresses have all top bits 1.

Happy to do that.  This is a user-facing interface though: userspace
addresses are the only kind of address there is.

> 
> > +.IP
> > +The level of support is selected by
> > +.IR "(unsigned int) arg2" ,
> 
> We use (unsigned long) for arg2.

Hmmm, not quite sure how I came up with unsigned int here.  I'll just
drop this: the type in the prctl() prototype is unsigned long anyway.

The type is actually moot in this case, since the valid values all fit
in an unsigned int.

> > +which can be one of the following:
> > +.RS
> > +.TP
> > +.B 0
> > +Addresses that are passed
> > +for the purpose of being dereferenced by the kernel
> > +must be untagged.
> > +.TP
> > +.B PR_TAGGED_ADDR_ENABLE
> > +Addresses that are passed
> > +for the purpose of being dereferenced by the kernel
> > +may be tagged, with the exceptions summarized below.
> > +.RE
> > +.IP
> > +The remaining arguments
> > +.IR arg3 ", " arg4 " and " arg5
> > +must all be zero.
> 
> Indeed. The above commit didn't have this, we added it later in commit
> 3e91ec89f527b9870fe42dcbdb74fd389d123a95.

Ah, missed that.  Did any full kernel release expose the unchecked
behaviour?

Mind you, there's probably no need to document in any case.

> 
> > +.IP
> > +On success, the mode specified in
> > +.I arg2
> > +is set for the calling thread and the the return value is 0.
> > +If the arguments are invalid,
> > +the mode specified in
> > +.I arg2
> > +is unrecognized,
> > +or if this feature is disabled or unsupported by the kernel,
> > +the call fails with
> > +.BR EINVAL .
> > +.IP
> > +In particular, if
> > +.BR prctl ( PR_SET_TAGGED_ADDR_CTRL ,
> > +0, 0, 0, 0)
> > +fails with
> > +.B EINVAL
> > +then all addresses passed to the kernel must be untagged.
> > +.IP
> > +Irrespective of which mode is set,
> > +addresses passed to certain interfaces
> > +must always be untagged:
> 
> Maybe you could add some extra info from the kernel comment (commit
> b2a84de2a2deb76a6a51609845341f508c518c03) along the lines of "... to
> avoid the creation of aliasing mappings in userspace).

It depends.  It's useful if it helps people to guess highly accurately
the rule for in interface that is too new or that we don't explicitly
document (such as a random setsockopt or perf widget).

If not, it might be best to say nothing and make guarantees only about
the explicitly listed interfaces though.

What do you think?

> > +.RS
> > +.IP \(em
> > +.BR brk (2),
> > +.BR mmap (2),
> > +.BR shmat (2),
> > +and the
> > +.I new_address
> > +argument of
> > +.BR mremap (2).
> > +.IP
> > +(Prior to Linux 5.6 these accepted tagged addresses,
> > +but the behaviour may not be what you expect.
> > +Don't rely on it.)
> 
> shmat() was not part of the subsequent fix
> (dcde237319e626d1ec3c9d8b7613032f0fd4663a), it always rejected tagged
> address. But I guess it doesn't matter much, the user should not pass
> tagged addresses to these syscalls anyway.
> 
> You could move shmat() down together with shmdt().

I guess I was highlighting that shmdt() is a special case, because the
user would guess from the pattern of the other listed calls that shmdt()
should accept tagged addresses.  If you think separating it just adds to
the confusion, I'm happy not too call it out specially here.

OTOH, we could fix shmdt() and document the legacy behaviour as a bug in
specific kernel versions rather than the canonical behaviour.  But I
guess that's one for later.

> > +.IP \(em
> > +\(oqpolymorphic\(cq interfaces
> > +that accept pointers to arbitrary types cast to a
> > +.I void *
> > +or other generic type, specifically
> > +.BR prctl (2),
> > +.BR ioctl (2),
> > +and in general
> > +.BR setsockopt (2)
> > +(only certain specific
> > +.BR setsockopt (2)
> > +options allow tagged addresses).
> > +.IP \(em
> > +.BR shmdt (2).
> > +.RE
> > +.IP
> > +This list of exclusions may shrink
> > +when moving from one kernel version to a later kernel version.
> > +While the kernel may make some guarantees
> > +for backwards compatibility reasons,
> > +for the purposes of new software
> > +the effect of passing tagged addresses to these interfaces
> > +is unspecified.
> > +.IP
> > +The mode set by this call is inherited across
> > +.BR fork (2)
> > +and
> > +.BR clone (2).
> > +The mode is reset by
> > +.BR execve (2)
> > +to 0
> > +(i.e., tagged addresses not permitted in the user/kernel ABI).
> > +.IP
> > +.B Warning:
> > +Because the compiler or run-time environment
> > +may make use of address tagging,
> > +a successful
> > +.B PR_SET_TAGGED_ADDR_CTRL
> > +may crash the calling process.
> 
> I don't think PR_SET_TAGGED_ADDR_CTRL could crash the calling process.
> Rather disabling tagged addresses would break it. If a process is using

This is precisely how PR_SET_TAGGED_ADDR_CTRL could crash the calling
process, no?

Rather than try to explain the different cases in detail here and have
the reader take it as gospel, I thought it would be better to scare them
a bit and encourage them to so some homework.  Perhaps I'm being too
cautious.

> tagged addresses but does not pass them to the kernel, it will continue
> to do so even when the syscalls accept such addresses.
> 
> > +The conditions for using it safely are complex and system-dependent.
> > +Don't use it unless you know what you are doing.
> 
> This syscall is intended for the C library if the heap allocator
> generates tagged addresses. So it's not a general purpose prctl() random
> application code could call. Anyway I'm fine with your warning of not
> doing it but you may want to clarify the intent.

Maybe add something like

"This call is primarily intended for use by the run-time environment."

?

> 
> > +.IP
> > +For more information, see the kernel source file
> > +.IR Documentation/arm64/tagged\-address\-abi.rst .
> > +.\" prctl PR_GET_TAGGED_ADDR_CTRL
> > +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> > +.TP
> > +.BR PR_GET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> > +Returns the current tagged address mode
> > +for the calling thread.
> > +.IP
> > +Arguments
> > +.IR arg2 ", " arg3 ", " arg4 " and " arg5
> > +must all be zero.
> > +.IP
> > +If the arguments are invalid
> > +or this feature is disabled or unsupported by the kernel,
> > +the call fails with
> > +.BR EINVAL .
> > +In particular, if
> > +.BR prctl ( PR_GET_TAGGED_ADDR_CTRL ,
> > +0, 0, 0, 0)
> > +fails with
> > +.BR EINVAL ,
> > +then this feature is definitely unsupported or disabled,
> 
> I guess it's outside the scope of the prctl.2 to describe how the
> feature was disabled (e.g. sysctl).

We could include it here, but I'm thinking we might want a more
comprehensive separate page to describe how to use MTE in general.

For now, is referencing the kernel documentation enough?

> > +and all addresses passed to the kernel must be untagged.
> > +.IP
> > +Otherwise, the call returns a nonnegative value
> > +describing the current tagged address mode,
> > +encoded in the same way as the
> > +.I arg2
> > +argument of
> > +.BR PR_SET_TAGGED_ADDR_CTRL .
> > +.IP
> > +For more information, see the kernel source file
> > +.IR Documentation/arm64/tagged\-address\-abi.rst .
> >  .\"
> >  .\" prctl PR_TASK_PERF_EVENTS_DISABLE
> >  .TP
> > @@ -1749,6 +1886,7 @@ On success,
> >  .BR PR_GET_SPECULATION_CTRL ,
> >  .BR PR_SVE_GET_VL ,
> >  .BR PR_SVE_SET_VL ,
> > +.BR PR_GET_TAGGED_ADDR_CTRL ,
> >  .BR PR_GET_THP_DISABLE ,
> >  .BR PR_GET_TIMING ,
> >  .BR PR_GET_TIMERSLACK ,
> > @@ -2057,6 +2195,24 @@ is
> >  .B PR_SVE_GET_VL
> >  and SVE is not available on this platform.
> >  .TP
> > +.B EINVAL
> > +.I option
> > +is
> > +.BR PR_SET_TAGGED_ADDR_CTRL
> > +and the arguments are invalid or unsupported.
> > +See the description of
> > +.B PR_SET_TAGGED_ADDR_CTRL
> > +above for details.
> > +.TP
> > +.B EINVAL
> > +.I option
> > +is
> > +.BR PR_GET_TAGGED_ADDR_CTRL
> > +and the arguments are invalid or unsupported.
> > +See the description of
> > +.B PR_GET_TAGGED_ADDR_CTRL
> > +above for details.
> > +.TP
> >  .B ENODEV
> >  .I option
> >  was
> 
> Apart from some minor nits above, the documentation looks fine.
> 
> Thanks for writing this up.

Thanks for the review.  I was taking a punt on some of it, so I'm
reassured that you didn't find too many controversial points.

Cheers
---Dave
Catalin Marinas June 10, 2020, 3:26 p.m. UTC | #5
On Wed, Jun 10, 2020 at 11:06:42AM +0100, Dave P Martin wrote:
> On Tue, Jun 09, 2020 at 06:22:32PM +0100, Catalin Marinas wrote:
> > On Wed, May 27, 2020 at 10:17:38PM +0100, Dave P Martin wrote:
> > > --- a/man2/prctl.2
> > > +++ b/man2/prctl.2
> > > @@ -1504,6 +1504,143 @@ For more information, see the kernel source file
> > >  (or
> > >  .I Documentation/arm64/sve.txt
> > >  before Linux 5.3).
> > > +.\" prctl PR_SET_TAGGED_ADDR_CTRL
> > > +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> > > +.TP
> > > +.BR PR_SET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> > > +Controls support for passing tagged userspace addresses to the kernel
> > > +(i.e., addresses where bits 56\(em63 are not all zero).
> > 
> > Nitpick: maybe say "userspace addresses" again inside the brackets since
> > kernel addresses have all top bits 1.
> 
> Happy to do that.  This is a user-facing interface though: userspace
> addresses are the only kind of address there is.

Living in the kernel land for too long, it's hard to switch perspective ;).
I think the original sentence makes sense anyway, it should be obvious
that it refers to user addresses.

> > > +.IP
> > > +The level of support is selected by
> > > +.IR "(unsigned int) arg2" ,
> > 
> > We use (unsigned long) for arg2.
> 
> Hmmm, not quite sure how I came up with unsigned int here.  I'll just
> drop this: the type in the prctl() prototype is unsigned long anyway.
> 
> The type is actually moot in this case, since the valid values all fit
> in an unsigned int.

Passing an int doesn't require that the top 32-bit of the long are
zeroed (in case anyone writes the low-level SVC by hand).

> > > +which can be one of the following:
> > > +.RS
> > > +.TP
> > > +.B 0
> > > +Addresses that are passed
> > > +for the purpose of being dereferenced by the kernel
> > > +must be untagged.
> > > +.TP
> > > +.B PR_TAGGED_ADDR_ENABLE
> > > +Addresses that are passed
> > > +for the purpose of being dereferenced by the kernel
> > > +may be tagged, with the exceptions summarized below.
> > > +.RE
> > > +.IP
> > > +The remaining arguments
> > > +.IR arg3 ", " arg4 " and " arg5
> > > +must all be zero.
> > 
> > Indeed. The above commit didn't have this, we added it later in commit
> > 3e91ec89f527b9870fe42dcbdb74fd389d123a95.
> 
> Ah, missed that.  Did any full kernel release expose the unchecked
> behaviour?

No, they both went into 5.4-rc1. I probably didn't want to rebase the
series and just added a patch on top.

> Mind you, there's probably no need to document in any case.

I agree. Just mentioned it because I looked at the commit you mentioned
and there was no check for the arg3..arg5, so went to check the history.

> > > +.IP
> > > +On success, the mode specified in
> > > +.I arg2
> > > +is set for the calling thread and the the return value is 0.
> > > +If the arguments are invalid,
> > > +the mode specified in
> > > +.I arg2
> > > +is unrecognized,
> > > +or if this feature is disabled or unsupported by the kernel,
> > > +the call fails with
> > > +.BR EINVAL .
> > > +.IP
> > > +In particular, if
> > > +.BR prctl ( PR_SET_TAGGED_ADDR_CTRL ,
> > > +0, 0, 0, 0)
> > > +fails with
> > > +.B EINVAL
> > > +then all addresses passed to the kernel must be untagged.
> > > +.IP
> > > +Irrespective of which mode is set,
> > > +addresses passed to certain interfaces
> > > +must always be untagged:
> > 
> > Maybe you could add some extra info from the kernel comment (commit
> > b2a84de2a2deb76a6a51609845341f508c518c03) along the lines of "... to
> > avoid the creation of aliasing mappings in userspace).
> 
> It depends.  It's useful if it helps people to guess highly accurately
> the rule for in interface that is too new or that we don't explicitly
> document (such as a random setsockopt or perf widget).
> 
> If not, it might be best to say nothing and make guarantees only about
> the explicitly listed interfaces though.

Fine by me to keep it as it is. We can always update the man page if new
syscalls come into this category.

> > > +.RS
> > > +.IP \(em
> > > +.BR brk (2),
> > > +.BR mmap (2),
> > > +.BR shmat (2),
> > > +and the
> > > +.I new_address
> > > +argument of
> > > +.BR mremap (2).
> > > +.IP
> > > +(Prior to Linux 5.6 these accepted tagged addresses,
> > > +but the behaviour may not be what you expect.
> > > +Don't rely on it.)
> > 
> > shmat() was not part of the subsequent fix
> > (dcde237319e626d1ec3c9d8b7613032f0fd4663a), it always rejected tagged
> > address. But I guess it doesn't matter much, the user should not pass
> > tagged addresses to these syscalls anyway.
> > 
> > You could move shmat() down together with shmdt().
> 
> I guess I was highlighting that shmdt() is a special case, because the
> user would guess from the pattern of the other listed calls that shmdt()
> should accept tagged addresses.  If you think separating it just adds to
> the confusion, I'm happy not too call it out specially here.
> 
> OTOH, we could fix shmdt() and document the legacy behaviour as a bug in
> specific kernel versions rather than the canonical behaviour.  But I
> guess that's one for later.

If we patch shmdt() to allow tagged addresses, then it makes sense to
keep shmat() with the rest of the above. Just pointing out that shmat()
never allowed tagged pointers

> > > +.IP \(em
> > > +\(oqpolymorphic\(cq interfaces
> > > +that accept pointers to arbitrary types cast to a
> > > +.I void *
> > > +or other generic type, specifically
> > > +.BR prctl (2),
> > > +.BR ioctl (2),
> > > +and in general
> > > +.BR setsockopt (2)
> > > +(only certain specific
> > > +.BR setsockopt (2)
> > > +options allow tagged addresses).
> > > +.IP \(em
> > > +.BR shmdt (2).
> > > +.RE
> > > +.IP
> > > +This list of exclusions may shrink
> > > +when moving from one kernel version to a later kernel version.
> > > +While the kernel may make some guarantees
> > > +for backwards compatibility reasons,
> > > +for the purposes of new software
> > > +the effect of passing tagged addresses to these interfaces
> > > +is unspecified.
> > > +.IP
> > > +The mode set by this call is inherited across
> > > +.BR fork (2)
> > > +and
> > > +.BR clone (2).
> > > +The mode is reset by
> > > +.BR execve (2)
> > > +to 0
> > > +(i.e., tagged addresses not permitted in the user/kernel ABI).
> > > +.IP
> > > +.B Warning:
> > > +Because the compiler or run-time environment
> > > +may make use of address tagging,
> > > +a successful
> > > +.B PR_SET_TAGGED_ADDR_CTRL
> > > +may crash the calling process.
> > 
> > I don't think PR_SET_TAGGED_ADDR_CTRL could crash the calling process.
> > Rather disabling tagged addresses would break it. If a process is using
> 
> This is precisely how PR_SET_TAGGED_ADDR_CTRL could crash the calling
> process, no?

I see your point. E.g. it was enabled by glibc but disabled by a user
application.

> Rather than try to explain the different cases in detail here and have
> the reader take it as gospel, I thought it would be better to scare them
> a bit and encourage them to so some homework.  Perhaps I'm being too
> cautious.

That's fine, leave the warning in place.

> > tagged addresses but does not pass them to the kernel, it will continue
> > to do so even when the syscalls accept such addresses.
> > 
> > > +The conditions for using it safely are complex and system-dependent.
> > > +Don't use it unless you know what you are doing.
> > 
> > This syscall is intended for the C library if the heap allocator
> > generates tagged addresses. So it's not a general purpose prctl() random
> > application code could call. Anyway I'm fine with your warning of not
> > doing it but you may want to clarify the intent.
> 
> Maybe add something like
> 
> "This call is primarily intended for use by the run-time environment."

That works as well, maybe in addition to the warning. Up to you.

> > > +.IP
> > > +For more information, see the kernel source file
> > > +.IR Documentation/arm64/tagged\-address\-abi.rst .
> > > +.\" prctl PR_GET_TAGGED_ADDR_CTRL
> > > +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> > > +.TP
> > > +.BR PR_GET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> > > +Returns the current tagged address mode
> > > +for the calling thread.
> > > +.IP
> > > +Arguments
> > > +.IR arg2 ", " arg3 ", " arg4 " and " arg5
> > > +must all be zero.
> > > +.IP
> > > +If the arguments are invalid
> > > +or this feature is disabled or unsupported by the kernel,
> > > +the call fails with
> > > +.BR EINVAL .
> > > +In particular, if
> > > +.BR prctl ( PR_GET_TAGGED_ADDR_CTRL ,
> > > +0, 0, 0, 0)
> > > +fails with
> > > +.BR EINVAL ,
> > > +then this feature is definitely unsupported or disabled,
> > 
> > I guess it's outside the scope of the prctl.2 to describe how the
> > feature was disabled (e.g. sysctl).
> 
> We could include it here, but I'm thinking we might want a more
> comprehensive separate page to describe how to use MTE in general.
> 
> For now, is referencing the kernel documentation enough?

I think simply saying "unsupported or disabled" is sufficient in the man
page. The sysctl is not aimed at the user sw/run-time developers but
rather those controlling the system. For the latter, the kernel
documentation is sufficient.

So with the (unsigned int) fixed, feel free to add:

Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>

I don't have a strong opinion on the other nitpicks, so I'll leave the
decision to you.
Dave Martin June 10, 2020, 4:42 p.m. UTC | #6
On Wed, Jun 10, 2020 at 04:26:34PM +0100, Catalin Marinas wrote:
> On Wed, Jun 10, 2020 at 11:06:42AM +0100, Dave P Martin wrote:
> > On Tue, Jun 09, 2020 at 06:22:32PM +0100, Catalin Marinas wrote:
> > > On Wed, May 27, 2020 at 10:17:38PM +0100, Dave P Martin wrote:
> > > > --- a/man2/prctl.2
> > > > +++ b/man2/prctl.2
> > > > @@ -1504,6 +1504,143 @@ For more information, see the kernel source file
> > > >  (or
> > > >  .I Documentation/arm64/sve.txt
> > > >  before Linux 5.3).
> > > > +.\" prctl PR_SET_TAGGED_ADDR_CTRL
> > > > +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> > > > +.TP
> > > > +.BR PR_SET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> > > > +Controls support for passing tagged userspace addresses to the kernel
> > > > +(i.e., addresses where bits 56\(em63 are not all zero).
> > > 
> > > Nitpick: maybe say "userspace addresses" again inside the brackets since
> > > kernel addresses have all top bits 1.
> > 
> > Happy to do that.  This is a user-facing interface though: userspace
> > addresses are the only kind of address there is.
> 
> Living in the kernel land for too long, it's hard to switch perspective ;).
> I think the original sentence makes sense anyway, it should be obvious
> that it refers to user addresses.

OK

> > > > +.IP
> > > > +The level of support is selected by
> > > > +.IR "(unsigned int) arg2" ,
> > > 
> > > We use (unsigned long) for arg2.
> > 
> > Hmmm, not quite sure how I came up with unsigned int here.  I'll just
> > drop this: the type in the prctl() prototype is unsigned long anyway.
> > 
> > The type is actually moot in this case, since the valid values all fit
> > in an unsigned int.
> 
> Passing an int doesn't require that the top 32-bit of the long are
> zeroed (in case anyone writes the low-level SVC by hand).

Fair point, I was forgetting that wrinkle.  Anyway, the convention in
this page seems to be that if the type is unsigned long, we don't
mention it, because the prctl() prototype says that already.

Question: the glibc prototype for prctl is variadic, so surely any
calls that don't explicitly cast the args to unsigned long are already
theoretically broken?  The #defines (and 0) are all implicitly int.
This probably affects lots of prctls.

We may get away with it because the compiler is almost certainly going
to favour a mov over a ldr for getting small integers into regs, and mov
<Wd> fortunately zeroes the top bits for us anyway.

Seems icky though.

> > > > +which can be one of the following:
> > > > +.RS
> > > > +.TP
> > > > +.B 0
> > > > +Addresses that are passed
> > > > +for the purpose of being dereferenced by the kernel
> > > > +must be untagged.
> > > > +.TP
> > > > +.B PR_TAGGED_ADDR_ENABLE
> > > > +Addresses that are passed
> > > > +for the purpose of being dereferenced by the kernel
> > > > +may be tagged, with the exceptions summarized below.
> > > > +.RE
> > > > +.IP
> > > > +The remaining arguments
> > > > +.IR arg3 ", " arg4 " and " arg5
> > > > +must all be zero.
> > > 
> > > Indeed. The above commit didn't have this, we added it later in commit
> > > 3e91ec89f527b9870fe42dcbdb74fd389d123a95.
> > 
> > Ah, missed that.  Did any full kernel release expose the unchecked
> > behaviour?
> 
> No, they both went into 5.4-rc1. I probably didn't want to rebase the
> series and just added a patch on top.
> 
> > Mind you, there's probably no need to document in any case.
> 
> I agree. Just mentioned it because I looked at the commit you mentioned
> and there was no check for the arg3..arg5, so went to check the history.

Ah, OK.  We should keep quiet then, but I can add the commit reference
as an internal comment in case anyone wants to check where the arg
zeroing enforcement came from.

> 
> > > > +.IP
> > > > +On success, the mode specified in
> > > > +.I arg2
> > > > +is set for the calling thread and the the return value is 0.
> > > > +If the arguments are invalid,
> > > > +the mode specified in
> > > > +.I arg2
> > > > +is unrecognized,
> > > > +or if this feature is disabled or unsupported by the kernel,
> > > > +the call fails with
> > > > +.BR EINVAL .
> > > > +.IP
> > > > +In particular, if
> > > > +.BR prctl ( PR_SET_TAGGED_ADDR_CTRL ,
> > > > +0, 0, 0, 0)
> > > > +fails with
> > > > +.B EINVAL
> > > > +then all addresses passed to the kernel must be untagged.
> > > > +.IP
> > > > +Irrespective of which mode is set,
> > > > +addresses passed to certain interfaces
> > > > +must always be untagged:
> > > 
> > > Maybe you could add some extra info from the kernel comment (commit
> > > b2a84de2a2deb76a6a51609845341f508c518c03) along the lines of "... to
> > > avoid the creation of aliasing mappings in userspace).
> > 
> > It depends.  It's useful if it helps people to guess highly accurately
> > the rule for in interface that is too new or that we don't explicitly
> > document (such as a random setsockopt or perf widget).
> > 
> > If not, it might be best to say nothing and make guarantees only about
> > the explicitly listed interfaces though.
> 
> Fine by me to keep it as it is. We can always update the man page if new
> syscalls come into this category.

OK, I'll probably keep it as-is for now, but shout if you change your mind!

> > > > +.RS
> > > > +.IP \(em
> > > > +.BR brk (2),
> > > > +.BR mmap (2),
> > > > +.BR shmat (2),
> > > > +and the
> > > > +.I new_address
> > > > +argument of
> > > > +.BR mremap (2).
> > > > +.IP
> > > > +(Prior to Linux 5.6 these accepted tagged addresses,
> > > > +but the behaviour may not be what you expect.
> > > > +Don't rely on it.)
> > > 
> > > shmat() was not part of the subsequent fix
> > > (dcde237319e626d1ec3c9d8b7613032f0fd4663a), it always rejected tagged
> > > address. But I guess it doesn't matter much, the user should not pass
> > > tagged addresses to these syscalls anyway.
> > > 
> > > You could move shmat() down together with shmdt().
> > 
> > I guess I was highlighting that shmdt() is a special case, because the
> > user would guess from the pattern of the other listed calls that shmdt()
> > should accept tagged addresses.  If you think separating it just adds to
> > the confusion, I'm happy not too call it out specially here.
> > 
> > OTOH, we could fix shmdt() and document the legacy behaviour as a bug in
> > specific kernel versions rather than the canonical behaviour.  But I
> > guess that's one for later.
> 
> If we patch shmdt() to allow tagged addresses, then it makes sense to
> keep shmat() with the rest of the above. Just pointing out that shmat()
> never allowed tagged pointers

Oh, I see what you mean.  I'll have a think when I revisit this.

[...]

> > > > +.B Warning:
> > > > +Because the compiler or run-time environment
> > > > +may make use of address tagging,
> > > > +a successful
> > > > +.B PR_SET_TAGGED_ADDR_CTRL
> > > > +may crash the calling process.
> > > 
> > > I don't think PR_SET_TAGGED_ADDR_CTRL could crash the calling process.
> > > Rather disabling tagged addresses would break it. If a process is using
> > 
> > This is precisely how PR_SET_TAGGED_ADDR_CTRL could crash the calling
> > process, no?
> 
> I see your point. E.g. it was enabled by glibc but disabled by a user
> application.
> 
> > Rather than try to explain the different cases in detail here and have
> > the reader take it as gospel, I thought it would be better to scare them
> > a bit and encourage them to so some homework.  Perhaps I'm being too
> > cautious.
> 
> That's fine, leave the warning in place.
> 
> > > tagged addresses but does not pass them to the kernel, it will continue
> > > to do so even when the syscalls accept such addresses.
> > > 
> > > > +The conditions for using it safely are complex and system-dependent.
> > > > +Don't use it unless you know what you are doing.
> > > 
> > > This syscall is intended for the C library if the heap allocator
> > > generates tagged addresses. So it's not a general purpose prctl() random
> > > application code could call. Anyway I'm fine with your warning of not
> > > doing it but you may want to clarify the intent.
> > 
> > Maybe add something like
> > 
> > "This call is primarily intended for use by the run-time environment."
> 
> That works as well, maybe in addition to the warning. Up to you.

OK, I may try to add that, but I'll try not to go overboard!

> > > > +.IP
> > > > +For more information, see the kernel source file
> > > > +.IR Documentation/arm64/tagged\-address\-abi.rst .
> > > > +.\" prctl PR_GET_TAGGED_ADDR_CTRL
> > > > +.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
> > > > +.TP
> > > > +.BR PR_GET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
> > > > +Returns the current tagged address mode
> > > > +for the calling thread.
> > > > +.IP
> > > > +Arguments
> > > > +.IR arg2 ", " arg3 ", " arg4 " and " arg5
> > > > +must all be zero.
> > > > +.IP
> > > > +If the arguments are invalid
> > > > +or this feature is disabled or unsupported by the kernel,
> > > > +the call fails with
> > > > +.BR EINVAL .
> > > > +In particular, if
> > > > +.BR prctl ( PR_GET_TAGGED_ADDR_CTRL ,
> > > > +0, 0, 0, 0)
> > > > +fails with
> > > > +.BR EINVAL ,
> > > > +then this feature is definitely unsupported or disabled,
> > > 
> > > I guess it's outside the scope of the prctl.2 to describe how the
> > > feature was disabled (e.g. sysctl).
> > 
> > We could include it here, but I'm thinking we might want a more
> > comprehensive separate page to describe how to use MTE in general.
> > 
> > For now, is referencing the kernel documentation enough?
> 
> I think simply saying "unsupported or disabled" is sufficient in the man
> page. The sysctl is not aimed at the user sw/run-time developers but
> rather those controlling the system. For the latter, the kernel
> documentation is sufficient.
> 
> So with the (unsigned int) fixed, feel free to add:
> 
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> 
> I don't have a strong opinion on the other nitpicks, so I'll leave the
> decision to you.

OK, thanks

---Dave
Catalin Marinas June 10, 2020, 5:42 p.m. UTC | #7
On Wed, Jun 10, 2020 at 05:42:09PM +0100, Dave P Martin wrote:
> On Wed, Jun 10, 2020 at 04:26:34PM +0100, Catalin Marinas wrote:
> > On Wed, Jun 10, 2020 at 11:06:42AM +0100, Dave P Martin wrote:
> > > On Tue, Jun 09, 2020 at 06:22:32PM +0100, Catalin Marinas wrote:
> > > > On Wed, May 27, 2020 at 10:17:38PM +0100, Dave P Martin wrote:
> > > > > +.IP
> > > > > +The level of support is selected by
> > > > > +.IR "(unsigned int) arg2" ,
> > > > 
> > > > We use (unsigned long) for arg2.
> > > 
> > > Hmmm, not quite sure how I came up with unsigned int here.  I'll just
> > > drop this: the type in the prctl() prototype is unsigned long anyway.
> > > 
> > > The type is actually moot in this case, since the valid values all fit
> > > in an unsigned int.
> > 
> > Passing an int doesn't require that the top 32-bit of the long are
> > zeroed (in case anyone writes the low-level SVC by hand).
> 
> Fair point, I was forgetting that wrinkle.  Anyway, the convention in
> this page seems to be that if the type is unsigned long, we don't
> mention it, because the prctl() prototype says that already.
> 
> Question: the glibc prototype for prctl is variadic, so surely any
> calls that don't explicitly cast the args to unsigned long are already
> theoretically broken?  The #defines (and 0) are all implicitly int.
> This probably affects lots of prctls.
> 
> We may get away with it because the compiler is almost certainly going
> to favour a mov over a ldr for getting small integers into regs, and mov
> <Wd> fortunately zeroes the top bits for us anyway.

So does LDR Wd.

Anyway, I think glibc (or my reading of it) has something like like:

  register long _x1 asm ("x1") = _x1tmp;

before invoking the SVC. I assume this would do the right conversion to
long. I can't tell about other libraries but I'd say it's their
responsibility to convert the args to long before calling the kernel's
prctl().
Dave Martin June 15, 2020, 2:51 p.m. UTC | #8
On Wed, Jun 10, 2020 at 06:42:05PM +0100, Catalin Marinas wrote:
> On Wed, Jun 10, 2020 at 05:42:09PM +0100, Dave P Martin wrote:
> > On Wed, Jun 10, 2020 at 04:26:34PM +0100, Catalin Marinas wrote:
> > > On Wed, Jun 10, 2020 at 11:06:42AM +0100, Dave P Martin wrote:
> > > > On Tue, Jun 09, 2020 at 06:22:32PM +0100, Catalin Marinas wrote:
> > > > > On Wed, May 27, 2020 at 10:17:38PM +0100, Dave P Martin wrote:
> > > > > > +.IP
> > > > > > +The level of support is selected by
> > > > > > +.IR "(unsigned int) arg2" ,
> > > > > 
> > > > > We use (unsigned long) for arg2.
> > > > 
> > > > Hmmm, not quite sure how I came up with unsigned int here.  I'll just
> > > > drop this: the type in the prctl() prototype is unsigned long anyway.
> > > > 
> > > > The type is actually moot in this case, since the valid values all fit
> > > > in an unsigned int.
> > > 
> > > Passing an int doesn't require that the top 32-bit of the long are
> > > zeroed (in case anyone writes the low-level SVC by hand).
> > 
> > Fair point, I was forgetting that wrinkle.  Anyway, the convention in
> > this page seems to be that if the type is unsigned long, we don't
> > mention it, because the prctl() prototype says that already.
> > 
> > Question: the glibc prototype for prctl is variadic, so surely any
> > calls that don't explicitly cast the args to unsigned long are already
> > theoretically broken?  The #defines (and 0) are all implicitly int.
> > This probably affects lots of prctls.
> > 
> > We may get away with it because the compiler is almost certainly going
> > to favour a mov over a ldr for getting small integers into regs, and mov
> > <Wd> fortunately zeroes the top bits for us anyway.
> 
> So does LDR Wd.
> 
> Anyway, I think glibc (or my reading of it) has something like like:
> 
>   register long _x1 asm ("x1") = _x1tmp;
> 
> before invoking the SVC. I assume this would do the right conversion to
> long. I can't tell about other libraries but I'd say it's their
> responsibility to convert the args to long before calling the kernel's
> prctl().

Ignore me.  I was worrying that glibc would propagate junk in the high
bits of int arguments, due to treating them as longs.  Actually, it
will, but it doesn't matter where we explicitly cast the argument to int
inside the kernel (thanks as usual to -fno-strict-overflow).

Cheers
---Dave
Michael Kerrisk (man-pages) June 24, 2020, 9:54 a.m. UTC | #9
Hi Dave

Is there a plan for future work on this patch?

Thanks,

Michael

On Mon, 15 Jun 2020 at 16:51, Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Wed, Jun 10, 2020 at 06:42:05PM +0100, Catalin Marinas wrote:
> > On Wed, Jun 10, 2020 at 05:42:09PM +0100, Dave P Martin wrote:
> > > On Wed, Jun 10, 2020 at 04:26:34PM +0100, Catalin Marinas wrote:
> > > > On Wed, Jun 10, 2020 at 11:06:42AM +0100, Dave P Martin wrote:
> > > > > On Tue, Jun 09, 2020 at 06:22:32PM +0100, Catalin Marinas wrote:
> > > > > > On Wed, May 27, 2020 at 10:17:38PM +0100, Dave P Martin wrote:
> > > > > > > +.IP
> > > > > > > +The level of support is selected by
> > > > > > > +.IR "(unsigned int) arg2" ,
> > > > > >
> > > > > > We use (unsigned long) for arg2.
> > > > >
> > > > > Hmmm, not quite sure how I came up with unsigned int here.  I'll just
> > > > > drop this: the type in the prctl() prototype is unsigned long anyway.
> > > > >
> > > > > The type is actually moot in this case, since the valid values all fit
> > > > > in an unsigned int.
> > > >
> > > > Passing an int doesn't require that the top 32-bit of the long are
> > > > zeroed (in case anyone writes the low-level SVC by hand).
> > >
> > > Fair point, I was forgetting that wrinkle.  Anyway, the convention in
> > > this page seems to be that if the type is unsigned long, we don't
> > > mention it, because the prctl() prototype says that already.
> > >
> > > Question: the glibc prototype for prctl is variadic, so surely any
> > > calls that don't explicitly cast the args to unsigned long are already
> > > theoretically broken?  The #defines (and 0) are all implicitly int.
> > > This probably affects lots of prctls.
> > >
> > > We may get away with it because the compiler is almost certainly going
> > > to favour a mov over a ldr for getting small integers into regs, and mov
> > > <Wd> fortunately zeroes the top bits for us anyway.
> >
> > So does LDR Wd.
> >
> > Anyway, I think glibc (or my reading of it) has something like like:
> >
> >   register long _x1 asm ("x1") = _x1tmp;
> >
> > before invoking the SVC. I assume this would do the right conversion to
> > long. I can't tell about other libraries but I'd say it's their
> > responsibility to convert the args to long before calling the kernel's
> > prctl().
>
> Ignore me.  I was worrying that glibc would propagate junk in the high
> bits of int arguments, due to treating them as longs.  Actually, it
> will, but it doesn't matter where we explicitly cast the argument to int
> inside the kernel (thanks as usual to -fno-strict-overflow).
>
> Cheers
> ---Dave
Dave Martin June 24, 2020, 10:29 a.m. UTC | #10
On Wed, Jun 24, 2020 at 11:54:45AM +0200, Michael Kerrisk (man-pages) wrote:
> Hi Dave
> 
> Is there a plan for future work on this patch?

I think we have agreement on the content.  Mainly this is waiting for me
to repost.

Cheers
---Dave

[...]
diff mbox series

Patch

diff --git a/man2/prctl.2 b/man2/prctl.2
index 3ee2702..062fd51 100644
--- a/man2/prctl.2
+++ b/man2/prctl.2
@@ -1504,6 +1504,143 @@  For more information, see the kernel source file
 (or
 .I Documentation/arm64/sve.txt
 before Linux 5.3).
+.\" prctl PR_SET_TAGGED_ADDR_CTRL
+.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
+.TP
+.BR PR_SET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
+Controls support for passing tagged userspace addresses to the kernel
+(i.e., addresses where bits 56\(em63 are not all zero).
+.IP
+The level of support is selected by
+.IR "(unsigned int) arg2" ,
+which can be one of the following:
+.RS
+.TP
+.B 0
+Addresses that are passed
+for the purpose of being dereferenced by the kernel
+must be untagged.
+.TP
+.B PR_TAGGED_ADDR_ENABLE
+Addresses that are passed
+for the purpose of being dereferenced by the kernel
+may be tagged, with the exceptions summarized below.
+.RE
+.IP
+The remaining arguments
+.IR arg3 ", " arg4 " and " arg5
+must all be zero.
+.IP
+On success, the mode specified in
+.I arg2
+is set for the calling thread and the the return value is 0.
+If the arguments are invalid,
+the mode specified in
+.I arg2
+is unrecognized,
+or if this feature is disabled or unsupported by the kernel,
+the call fails with
+.BR EINVAL .
+.IP
+In particular, if
+.BR prctl ( PR_SET_TAGGED_ADDR_CTRL ,
+0, 0, 0, 0)
+fails with
+.B EINVAL
+then all addresses passed to the kernel must be untagged.
+.IP
+Irrespective of which mode is set,
+addresses passed to certain interfaces
+must always be untagged:
+.RS
+.IP \(em
+.BR brk (2),
+.BR mmap (2),
+.BR shmat (2),
+and the
+.I new_address
+argument of
+.BR mremap (2).
+.IP
+(Prior to Linux 5.6 these accepted tagged addresses,
+but the behaviour may not be what you expect.
+Don't rely on it.)
+.IP \(em
+\(oqpolymorphic\(cq interfaces
+that accept pointers to arbitrary types cast to a
+.I void *
+or other generic type, specifically
+.BR prctl (2),
+.BR ioctl (2),
+and in general
+.BR setsockopt (2)
+(only certain specific
+.BR setsockopt (2)
+options allow tagged addresses).
+.IP \(em
+.BR shmdt (2).
+.RE
+.IP
+This list of exclusions may shrink
+when moving from one kernel version to a later kernel version.
+While the kernel may make some guarantees
+for backwards compatibility reasons,
+for the purposes of new software
+the effect of passing tagged addresses to these interfaces
+is unspecified.
+.IP
+The mode set by this call is inherited across
+.BR fork (2)
+and
+.BR clone (2).
+The mode is reset by
+.BR execve (2)
+to 0
+(i.e., tagged addresses not permitted in the user/kernel ABI).
+.IP
+.B Warning:
+Because the compiler or run-time environment
+may make use of address tagging,
+a successful
+.B PR_SET_TAGGED_ADDR_CTRL
+may crash the calling process.
+The conditions for using it safely are complex and system-dependent.
+Don't use it unless you know what you are doing.
+.IP
+For more information, see the kernel source file
+.IR Documentation/arm64/tagged\-address\-abi.rst .
+.\" prctl PR_GET_TAGGED_ADDR_CTRL
+.\" commit 63f0c60379650d82250f22e4cf4137ef3dc4f43d
+.TP
+.BR PR_GET_TAGGED_ADDR_CTRL " (since Linux 5.4, only on arm64)"
+Returns the current tagged address mode
+for the calling thread.
+.IP
+Arguments
+.IR arg2 ", " arg3 ", " arg4 " and " arg5
+must all be zero.
+.IP
+If the arguments are invalid
+or this feature is disabled or unsupported by the kernel,
+the call fails with
+.BR EINVAL .
+In particular, if
+.BR prctl ( PR_GET_TAGGED_ADDR_CTRL ,
+0, 0, 0, 0)
+fails with
+.BR EINVAL ,
+then this feature is definitely unsupported or disabled,
+and all addresses passed to the kernel must be untagged.
+.IP
+Otherwise, the call returns a nonnegative value
+describing the current tagged address mode,
+encoded in the same way as the
+.I arg2
+argument of
+.BR PR_SET_TAGGED_ADDR_CTRL .
+.IP
+For more information, see the kernel source file
+.IR Documentation/arm64/tagged\-address\-abi.rst .
 .\"
 .\" prctl PR_TASK_PERF_EVENTS_DISABLE
 .TP
@@ -1749,6 +1886,7 @@  On success,
 .BR PR_GET_SPECULATION_CTRL ,
 .BR PR_SVE_GET_VL ,
 .BR PR_SVE_SET_VL ,
+.BR PR_GET_TAGGED_ADDR_CTRL ,
 .BR PR_GET_THP_DISABLE ,
 .BR PR_GET_TIMING ,
 .BR PR_GET_TIMERSLACK ,
@@ -2057,6 +2195,24 @@  is
 .B PR_SVE_GET_VL
 and SVE is not available on this platform.
 .TP
+.B EINVAL
+.I option
+is
+.BR PR_SET_TAGGED_ADDR_CTRL
+and the arguments are invalid or unsupported.
+See the description of
+.B PR_SET_TAGGED_ADDR_CTRL
+above for details.
+.TP
+.B EINVAL
+.I option
+is
+.BR PR_GET_TAGGED_ADDR_CTRL
+and the arguments are invalid or unsupported.
+See the description of
+.B PR_GET_TAGGED_ADDR_CTRL
+above for details.
+.TP
 .B ENODEV
 .I option
 was