Commit 15bfd167 authored by Vincenzo Frascino's avatar Vincenzo Frascino
Browse files

kselftest/arm64: Verify that TCO is enabled in load_unaligned_zeropad()

load_unaligned_zeropad() and __get/put_kernel_nofault() functions can
read passed some buffer limits which may include some MTE granule with a
different tag.

When MTE async mode is enable, the load operation crosses the boundaries
and the next granule has a different tag the PE sets the TFSR_EL1.TF1
bit as if an asynchronous tag fault is happened:

 BUG: KASAN: invalid-access
 Asynchronous mode enabled: no access details available

 CPU: 0 PID: 1 Comm: init Not tainted 5.12.0-rc1-ge1045c86

-dirty #8
 Hardware name: FVP Base RevC (DT)
 Call trace:

Verify that Tag Check Override (TCO) is enabled in these functions before
the load and disable it afterwards to prevent this to happen.

Note: The issue has been observed only with an MTE enabled userspace.

Cc: Catalin Marinas <>
Cc: Will Deacon <>
Reported-by: default avatarBranislav Rankov <>
Signed-off-by: Vincenzo Frascino's avatarVincenzo Frascino <>
parent 1b8aed65
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2020 ARM Limited
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/auxv.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "kselftest.h"
#include "mte_common_util.h"
#include "mte_def.h"
#define NUM_DEVICES 8
static char *dev[NUM_DEVICES] = {
"/proc/device-tre", /* incorrect path */
#define FAKE_PERMISSION 0x88000
#define MAX_DESCRIPTOR 0xffffffff
int mte_read_beyond_buffer_test(void)
int fd[NUM_DEVICES];
unsigned int _desc, _dev;
for (_desc = 0; _desc <= MAX_DESCRIPTOR; _desc++) {
for (_dev = 0; _dev < NUM_DEVICES; _dev++) {
#ifdef _TEST_DEBUG
printf("[TEST]: openat(0x%x, %s, 0x%x)\n", _desc, dev[_dev], FAKE_PERMISSION);
fd[_dev] = openat(_desc, dev[_dev], FAKE_PERMISSION);
for (_dev = 0; _dev <= NUM_DEVICES; _dev++)
return KSFT_PASS;
int main(int argc, char *argv[])
int err;
err = mte_default_setup();
if (err)
return err;
"Verify that TCO is enabled correctly if a read beyond buffer occurs\n");
return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment