arm64/mte: Remove asymmetric mode from the prctl() interface
As pointed out by Evgenii Stepanov one potential issue with the new ABI for enabling asymmetric is that if there are multiple places where MTE is configured in a process, some of which were compiled with the old prctl.h and some of which were compiled with the new prctl.h, there may be problems keeping track of which MTE modes are requested. For example some code may disable only sync and async modes leaving asymmetric mode enabled when it intended to fully disable MTE. In order to avoid such mishaps remove asymmetric mode from the prctl(), instead implicitly allowing it if both sync and async modes are requested. This should not disrupt userspace since a process requesting both may already see a mix of sync and async modes due to differing defaults between CPUs or changes in default while the process is running but it does mean that userspace is unable to explicitly request asymmetric mode without changing the system default for CPUs. Reported-by: Evgenii Stepanov <eugenis@google.com> Signed-off-by: Mark Brown <broonie@kernel.org> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Evgenii Stepanov <eugenis@google.com> Cc: Peter Collingbourne <pcc@google.com> Cc: Joey Gouly <joey.gouly@arm.com> Cc: Branislav Rankov <branislav.rankov@arm.com> Link: https://lore.kernel.org/r/20220309131200.112637-1-broonie@kernel.org Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
parent
d8fd5a1e78
commit
cf220ad674
|
@ -88,7 +88,6 @@ bit-field:
|
||||||
(ignored if combined with other options)
|
(ignored if combined with other options)
|
||||||
- ``PR_MTE_TCF_SYNC`` - *Synchronous* tag check fault mode
|
- ``PR_MTE_TCF_SYNC`` - *Synchronous* tag check fault mode
|
||||||
- ``PR_MTE_TCF_ASYNC`` - *Asynchronous* tag check fault mode
|
- ``PR_MTE_TCF_ASYNC`` - *Asynchronous* tag check fault mode
|
||||||
- ``PR_MTE_TCF_ASYMM`` - *Asymmetric* tag check fault mode
|
|
||||||
|
|
||||||
If no modes are specified, tag check faults are ignored. If a single
|
If no modes are specified, tag check faults are ignored. If a single
|
||||||
mode is specified, the program will run in that mode. If multiple
|
mode is specified, the program will run in that mode. If multiple
|
||||||
|
@ -149,17 +148,19 @@ default preferred mode for each CPU is ``async``.
|
||||||
To allow a program to potentially run in the CPU's preferred tag
|
To allow a program to potentially run in the CPU's preferred tag
|
||||||
checking mode, the user program may set multiple tag check fault mode
|
checking mode, the user program may set multiple tag check fault mode
|
||||||
bits in the ``flags`` argument to the ``prctl(PR_SET_TAGGED_ADDR_CTRL,
|
bits in the ``flags`` argument to the ``prctl(PR_SET_TAGGED_ADDR_CTRL,
|
||||||
flags, 0, 0, 0)`` system call. If the CPU's preferred tag checking
|
flags, 0, 0, 0)`` system call. If both synchronous and asynchronous
|
||||||
mode is in the task's set of provided tag checking modes, that
|
modes are requested then asymmetric mode may also be selected by the
|
||||||
mode will be selected. Otherwise, one of the modes in the task's mode
|
kernel. If the CPU's preferred tag checking mode is in the task's set
|
||||||
selected by the kernel using the preference order:
|
of provided tag checking modes, that mode will be selected. Otherwise,
|
||||||
|
one of the modes in the task's mode will be selected by the kernel
|
||||||
|
from the task's mode set using the preference order:
|
||||||
|
|
||||||
1. Asynchronous
|
1. Asynchronous
|
||||||
2. Asymmetric
|
2. Asymmetric
|
||||||
3. Synchronous
|
3. Synchronous
|
||||||
|
|
||||||
If asymmetric mode is specified by the program but not supported by
|
Note that there is no way for userspace to request multiple modes and
|
||||||
either the system or the kernel then an error will be returned.
|
also disable asymmetric mode.
|
||||||
|
|
||||||
Initial process state
|
Initial process state
|
||||||
---------------------
|
---------------------
|
||||||
|
|
|
@ -311,7 +311,16 @@ long set_mte_ctrl(struct task_struct *task, unsigned long arg)
|
||||||
mte_ctrl |= MTE_CTRL_TCF_ASYNC;
|
mte_ctrl |= MTE_CTRL_TCF_ASYNC;
|
||||||
if (arg & PR_MTE_TCF_SYNC)
|
if (arg & PR_MTE_TCF_SYNC)
|
||||||
mte_ctrl |= MTE_CTRL_TCF_SYNC;
|
mte_ctrl |= MTE_CTRL_TCF_SYNC;
|
||||||
if (arg & PR_MTE_TCF_ASYMM)
|
|
||||||
|
/*
|
||||||
|
* If the system supports it and both sync and async modes are
|
||||||
|
* specified then implicitly enable asymmetric mode.
|
||||||
|
* Userspace could see a mix of both sync and async anyway due
|
||||||
|
* to differing or changing defaults on CPUs.
|
||||||
|
*/
|
||||||
|
if (cpus_have_cap(ARM64_MTE_ASYMM) &&
|
||||||
|
(arg & PR_MTE_TCF_ASYNC) &&
|
||||||
|
(arg & PR_MTE_TCF_SYNC))
|
||||||
mte_ctrl |= MTE_CTRL_TCF_ASYMM;
|
mte_ctrl |= MTE_CTRL_TCF_ASYMM;
|
||||||
|
|
||||||
task->thread.mte_ctrl = mte_ctrl;
|
task->thread.mte_ctrl = mte_ctrl;
|
||||||
|
@ -341,8 +350,6 @@ long get_mte_ctrl(struct task_struct *task)
|
||||||
ret |= PR_MTE_TCF_ASYNC;
|
ret |= PR_MTE_TCF_ASYNC;
|
||||||
if (mte_ctrl & MTE_CTRL_TCF_SYNC)
|
if (mte_ctrl & MTE_CTRL_TCF_SYNC)
|
||||||
ret |= PR_MTE_TCF_SYNC;
|
ret |= PR_MTE_TCF_SYNC;
|
||||||
if (mte_ctrl & MTE_CTRL_TCF_ASYMM)
|
|
||||||
ret |= PR_MTE_TCF_ASYMM;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -637,8 +637,6 @@ long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg)
|
||||||
if (system_supports_mte())
|
if (system_supports_mte())
|
||||||
valid_mask |= PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC \
|
valid_mask |= PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC \
|
||||||
| PR_MTE_TAG_MASK;
|
| PR_MTE_TAG_MASK;
|
||||||
if (cpus_have_cap(ARM64_MTE_ASYMM))
|
|
||||||
valid_mask |= PR_MTE_TCF_ASYMM;
|
|
||||||
|
|
||||||
if (arg & ~valid_mask)
|
if (arg & ~valid_mask)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -238,9 +238,7 @@ struct prctl_mm_map {
|
||||||
# define PR_MTE_TCF_NONE 0UL
|
# define PR_MTE_TCF_NONE 0UL
|
||||||
# define PR_MTE_TCF_SYNC (1UL << 1)
|
# define PR_MTE_TCF_SYNC (1UL << 1)
|
||||||
# define PR_MTE_TCF_ASYNC (1UL << 2)
|
# define PR_MTE_TCF_ASYNC (1UL << 2)
|
||||||
# define PR_MTE_TCF_ASYMM (1UL << 19)
|
# define PR_MTE_TCF_MASK (PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC)
|
||||||
# define PR_MTE_TCF_MASK (PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC | \
|
|
||||||
PR_MTE_TCF_ASYMM)
|
|
||||||
/* MTE tag inclusion mask */
|
/* MTE tag inclusion mask */
|
||||||
# define PR_MTE_TAG_SHIFT 3
|
# define PR_MTE_TAG_SHIFT 3
|
||||||
# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
|
# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
|
||||||
|
|
Loading…
Reference in New Issue