| 0/0 |
2026/05/15 19:28 |
flow |
assessment-security |
1h06m
Results: map[DenialOfService:true Explanation:**Bug Analysis:**
The bug report indicates a possible circular locking dependency (AB-BA deadlock)
in the `ntfs3` filesystem involving `ni->ni_lock` and
`mapping->invalidate_lock`.
By examining the source code, we can trace the exact deadlock scenario:
1. **Thread 1 (`fallocate`)**: An unprivileged user calls `fallocate(fd,
FALLOC_FL_PUNCH_HOLE, ...)` on an `ntfs3` file. The `ntfs_fallocate` function
first acquires `mapping->invalidate_lock` for write (exclusive) via
`filemap_invalidate_lock(mapping)`. It then proceeds to call `attr_punch_hole`,
which attempts to acquire `ni->ni_lock` via `ni_lock(ni)`.
2. **Thread 2 (`ioctl FIEMAP`)**: Concurrently, the user calls `ioctl(fd,
FS_IOC_FIEMAP, ...)` on the same file. The user provides a `fieinfo` buffer that
is `mmap`ed to the same file (or another file that would cause a page fault).
The `ntfs_fiemap` function first acquires `ni->ni_lock`. It then calls
`ni_fiemap` -> `fiemap_fill_next_extent`, which uses `copy_to_user()` to write
the extent data to the user-provided buffer.
3. **Page Fault**: The `copy_to_user()` call triggers a page fault on the user
buffer. The page fault handler (`do_page_fault`) acquires the `mm->mmap_lock`
for read, and then calls `filemap_fault`, which attempts to acquire
`mapping->invalidate_lock` for read (shared).
**Deadlock:**
- Thread 1 holds `mapping->invalidate_lock` and is blocked waiting for
`ni->ni_lock`.
- Thread 2 holds `ni->ni_lock` and is blocked in the page fault handler waiting
for `mapping->invalidate_lock`.
**Security Impact Assessment:**
* **Exploitable:** False. This is a pure locking issue (deadlock) and does not
lead to memory corruption, use-after-free, or any other condition that could be
exploited for privilege escalation or arbitrary code execution.
* **Denial Of Service:** True. The deadlock will cause the involved threads to
hang indefinitely in the uninterruptible sleep (`D`) state. Because Thread 2
also holds `mmap_lock` (read) while blocked, any other thread in the same
process attempting to modify the memory map (e.g., `mmap`, `munmap`, `mprotect`,
or even thread exit) will also hang forever. Furthermore, the `ntfs3` inode
locks are held, preventing any other processes from accessing the file.
* **Accessible From Unprivileged Processes:** True. The bug can be triggered by
any unprivileged user who has read and write access to a file on an `ntfs3`
filesystem. Standard desktop Linux environments often auto-mount NTFS-formatted
USB drives and grant the logged-in user full read/write access to the files,
making this easily reachable.
* **Accessible From User Namespaces:** False. The `ntfs3` filesystem does not
have the `FS_USERNS_MOUNT` flag, meaning an unprivileged user cannot mount an
`ntfs3` image inside a user namespace to trigger this. It requires the
filesystem to be already mounted by the system (e.g., via admin or
auto-mounting).
* **Malicious Filesystem / Peripheral Trigger:** False. The bug is a logical
flaw in the syscall handling of the filesystem driver. It does not require a
maliciously crafted filesystem image or a malicious USB device to exploit; it
works perfectly on a completely normal, benign `ntfs3` filesystem.
* **Remote / Network / VM Triggers:** False. The bug is triggered via local
system calls and is not exposed to network traffic or virtualization boundaries. Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:true UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
|
| 1/1 |
2026/05/15 19:28 |
action |
syz-repro-to-c-repro |
0m
Results: map[SimplifiedCRepro:// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <setjmp.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/loop.h>
#ifndef __NR_memfd_create
#define __NR_memfd_create 319
#endif
static unsigned long long procid;
//% This code is derived from puff.{c,h}, found in the zlib development. The
//% original files come with the following copyright notice:
//% Copyright (C) 2002-2013 Mark Adler, all rights reserved
//% version 2.3, 21 Jan 2013
//% This software is provided 'as-is', without any express or implied
//% warranty. In no event will the author be held liable for any damages
//% arising from the use of this software.
//% Permission is granted to anyone to use this software for any purpose,
//% including commercial applications, and to alter it and redistribute it
//% freely, subject to the following restrictions:
//% 1. The origin of this software must not be misrepresented; you must not
//% claim that you wrote the original software. If you use this software
//% in a product, an acknowledgment in the product documentation would be
//% appreciated but is not required.
//% 2. Altered source versions must be plainly marked as such, and must not be
//% misrepresented as being the original software.
//% 3. This notice may not be removed or altered from any source distribution.
//% Mark Adler madler@alumni.caltech.edu
//% BEGIN CODE DERIVED FROM puff.{c,h}
#define MAXBITS 15
#define MAXLCODES 286
#define MAXDCODES 30
#define MAXCODES (MAXLCODES + MAXDCODES)
#define FIXLCODES 288
struct puff_state {
unsigned char* out;
unsigned long outlen;
unsigned long outcnt;
const unsigned char* in;
unsigned long inlen;
unsigned long incnt;
int bitbuf;
int bitcnt;
jmp_buf env;
};
static int puff_bits(struct puff_state* s, int need)
{
long val = s->bitbuf;
while (s->bitcnt < need) {
if (s->incnt == s->inlen)
longjmp(s->env, 1);
val |= (long)(s->in[s->incnt++]) << s->bitcnt;
s->bitcnt += 8;
}
s->bitbuf = (int)(val >> need);
s->bitcnt -= need;
return (int)(val & ((1L << need) - 1));
}
static int puff_stored(struct puff_state* s)
{
s->bitbuf = 0;
s->bitcnt = 0;
if (s->incnt + 4 > s->inlen)
return 2;
unsigned len = s->in[s->incnt++];
len |= s->in[s->incnt++] << 8;
if (s->in[s->incnt++] != (~len & 0xff) ||
s->in[s->incnt++] != ((~len >> 8) & 0xff))
return -2;
if (s->incnt + len > s->inlen)
return 2;
if (s->outcnt + len > s->outlen)
return 1;
for (; len--; s->outcnt++, s->incnt++) {
if (s->in[s->incnt])
s->out[s->outcnt] = s->in[s->incnt];
}
return 0;
}
struct puff_huffman {
short* count;
short* symbol;
};
static int puff_decode(struct puff_state* s, const struct puff_huffman* h)
{
int first = 0;
int index = 0;
int bitbuf = s->bitbuf;
int left = s->bitcnt;
int code = first = index = 0;
int len = 1;
short* next = h->count + 1;
while (1) {
while (left--) {
code |= bitbuf & 1;
bitbuf >>= 1;
int count = *next++;
if (code - count < first) {
s->bitbuf = bitbuf;
s->bitcnt = (s->bitcnt - len) & 7;
return h->symbol[index + (code - first)];
}
index += count;
first += count;
first <<= 1;
code <<= 1;
len++;
}
left = (MAXBITS + 1) - len;
if (left == 0)
break;
if (s->incnt == s->inlen)
longjmp(s->env, 1);
bitbuf = s->in[s->incnt++];
if (left > 8)
left = 8;
}
return -10;
}
static int puff_construct(struct puff_huffman* h, const short* length, int n)
{
int len;
for (len = 0; len <= MAXBITS; len++)
h->count[len] = 0;
int symbol;
for (symbol = 0; symbol < n; symbol++)
(h->count[length[symbol]])++;
if (h->count[0] == n)
return 0;
int left = 1;
for (len = 1; len <= MAXBITS; len++) {
left <<= 1;
left -= h->count[len];
if (left < 0)
return left;
}
short offs[MAXBITS + 1];
offs[1] = 0;
for (len = 1; len < MAXBITS; len++)
offs[len + 1] = offs[len] + h->count[len];
for (symbol = 0; symbol < n; symbol++)
if (length[symbol] != 0)
h->symbol[offs[length[symbol]]++] = symbol;
return left;
}
static int puff_codes(struct puff_state* s,
const struct puff_huffman* lencode,
const struct puff_huffman* distcode)
{
static const short lens[29] = {
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
static const short lext[29] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
static const short dists[30] = {
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577};
static const short dext[30] = {
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13};
int symbol;
do {
symbol = puff_decode(s, lencode);
if (symbol < 0)
return symbol;
if (symbol < 256) {
if (s->outcnt == s->outlen)
return 1;
if (symbol)
s->out[s->outcnt] = symbol;
s->outcnt++;
} else if (symbol > 256) {
symbol -= 257;
if (symbol >= 29)
return -10;
int len = lens[symbol] + puff_bits(s, lext[symbol]);
symbol = puff_decode(s, distcode);
if (symbol < 0)
return symbol;
unsigned dist = dists[symbol] + puff_bits(s, dext[symbol]);
if (dist > s->outcnt)
return -11;
if (s->outcnt + len > s->outlen)
return 1;
while (len--) {
if (dist <= s->outcnt && s->out[s->outcnt - dist])
s->out[s->outcnt] = s->out[s->outcnt - dist];
s->outcnt++;
}
}
} while (symbol != 256);
return 0;
}
static int puff_fixed(struct puff_state* s)
{
static int virgin = 1;
static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
static struct puff_huffman lencode, distcode;
if (virgin) {
lencode.count = lencnt;
lencode.symbol = lensym;
distcode.count = distcnt;
distcode.symbol = distsym;
short lengths[FIXLCODES];
int symbol;
for (symbol = 0; symbol < 144; symbol++)
lengths[symbol] = 8;
for (; symbol < 256; symbol++)
lengths[symbol] = 9;
for (; symbol < 280; symbol++)
lengths[symbol] = 7;
for (; symbol < FIXLCODES; symbol++)
lengths[symbol] = 8;
puff_construct(&lencode, lengths, FIXLCODES);
for (symbol = 0; symbol < MAXDCODES; symbol++)
lengths[symbol] = 5;
puff_construct(&distcode, lengths, MAXDCODES);
virgin = 0;
}
return puff_codes(s, &lencode, &distcode);
}
static int puff_dynamic(struct puff_state* s)
{
static const short order[19] =
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
int nlen = puff_bits(s, 5) + 257;
int ndist = puff_bits(s, 5) + 1;
int ncode = puff_bits(s, 4) + 4;
if (nlen > MAXLCODES || ndist > MAXDCODES)
return -3;
short lengths[MAXCODES];
int index;
for (index = 0; index < ncode; index++)
lengths[order[index]] = puff_bits(s, 3);
for (; index < 19; index++)
lengths[order[index]] = 0;
short lencnt[MAXBITS + 1], lensym[MAXLCODES];
struct puff_huffman lencode = {lencnt, lensym};
int err = puff_construct(&lencode, lengths, 19);
if (err != 0)
return -4;
index = 0;
while (index < nlen + ndist) {
int symbol;
int len;
symbol = puff_decode(s, &lencode);
if (symbol < 0)
return symbol;
if (symbol < 16)
lengths[index++] = symbol;
else {
len = 0;
if (symbol == 16) {
if (index == 0)
return -5;
len = lengths[index - 1];
symbol = 3 + puff_bits(s, 2);
} else if (symbol == 17)
symbol = 3 + puff_bits(s, 3);
else
symbol = 11 + puff_bits(s, 7);
if (index + symbol > nlen + ndist)
return -6;
while (symbol--)
lengths[index++] = len;
}
}
if (lengths[256] == 0)
return -9;
err = puff_construct(&lencode, lengths, nlen);
if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
return -7;
short distcnt[MAXBITS + 1], distsym[MAXDCODES];
struct puff_huffman distcode = {distcnt, distsym};
err = puff_construct(&distcode, lengths + nlen, ndist);
if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
return -8;
return puff_codes(s, &lencode, &distcode);
}
static int puff(
unsigned char* dest,
unsigned long* destlen,
const unsigned char* source,
unsigned long sourcelen)
{
struct puff_state s = {
.out = dest,
.outlen = *destlen,
.outcnt = 0,
.in = source,
.inlen = sourcelen,
.incnt = 0,
.bitbuf = 0,
.bitcnt = 0,
};
int err;
if (setjmp(s.env) != 0)
err = 2;
else {
int last;
do {
last = puff_bits(&s, 1);
int type = puff_bits(&s, 2);
err = type == 0 ? puff_stored(&s) : (type == 1 ? puff_fixed(&s) : (type == 2 ? puff_dynamic(&s) : -1));
if (err != 0)
break;
} while (!last);
}
*destlen = s.outcnt;
return err;
}
//% END CODE DERIVED FROM puff.{c,h}
#define ZLIB_HEADER_WIDTH 2
static int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd)
{
if (sourcelen < ZLIB_HEADER_WIDTH)
return 0;
source += ZLIB_HEADER_WIDTH;
sourcelen -= ZLIB_HEADER_WIDTH;
const unsigned long max_destlen = 132 << 20;
void* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
if (ret == MAP_FAILED)
return -1;
unsigned char* dest = (unsigned char*)ret;
unsigned long destlen = max_destlen;
int err = puff(dest, &destlen, source, sourcelen);
if (err) {
munmap(dest, max_destlen);
errno = -err;
return -1;
}
if (write(dest_fd, dest, destlen) != (ssize_t)destlen) {
munmap(dest, max_destlen);
return -1;
}
return munmap(dest, max_destlen);
}
static int setup_loop_device(unsigned char* data, unsigned long size, const char* loopname, int* loopfd_p)
{
int err = 0, loopfd = -1;
int memfd = syscall(__NR_memfd_create, "syzkaller", 0);
if (memfd == -1) {
err = errno;
goto error;
}
if (puff_zlib_to_file(data, size, memfd)) {
err = errno;
goto error_close_memfd;
}
loopfd = open(loopname, O_RDWR);
if (loopfd == -1) {
err = errno;
goto error_close_memfd;
}
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
if (errno != EBUSY) {
err = errno;
goto error_close_loop;
}
ioctl(loopfd, LOOP_CLR_FD, 0);
usleep(1000);
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
err = errno;
goto error_close_loop;
}
}
close(memfd);
*loopfd_p = loopfd;
return 0;
error_close_loop:
close(loopfd);
error_close_memfd:
close(memfd);
error:
errno = err;
return -1;
}
static void reset_loop_device(const char* loopname)
{
int loopfd = open(loopname, O_RDWR);
if (loopfd == -1) {
return;
}
if (ioctl(loopfd, LOOP_CLR_FD, 0)) {
}
close(loopfd);
}
static long syz_mount_image(
volatile long fsarg,
volatile long dir,
volatile long flags,
volatile long optsarg,
volatile long change_dir,
volatile unsigned long size,
volatile long image)
{
unsigned char* data = (unsigned char*)image;
int res = -1, err = 0, need_loop_device = !!size;
char* mount_opts = (char*)optsarg;
char* target = (char*)dir;
char* fs = (char*)fsarg;
char* source = NULL;
char loopname[64];
if (need_loop_device) {
int loopfd;
memset(loopname, 0, sizeof(loopname));
snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
if (setup_loop_device(data, size, loopname, &loopfd) == -1)
return -1;
close(loopfd);
source = loopname;
}
mkdir(target, 0777);
char opts[256];
memset(opts, 0, sizeof(opts));
if (strlen(mount_opts) > (sizeof(opts) - 32)) {
}
strncpy(opts, mount_opts, sizeof(opts) - 32);
if (strcmp(fs, "iso9660") == 0) {
flags |= MS_RDONLY;
} else if (strncmp(fs, "ext", 3) == 0) {
bool has_remount_ro = false;
char* remount_ro_start = strstr(opts, "errors=remount-ro");
if (remount_ro_start != NULL) {
char after = *(remount_ro_start + strlen("errors=remount-ro"));
char before = remount_ro_start == opts ? '\0' : *(remount_ro_start - 1);
has_remount_ro = ((before == '\0' || before == ',') && (after == '\0' || after == ','));
}
if (strstr(opts, "errors=panic") || !has_remount_ro)
strcat(opts, ",errors=continue");
} else if (strcmp(fs, "xfs") == 0) {
strcat(opts, ",nouuid");
} else if (strncmp(fs, "gfs2", 4) == 0 && (strstr(opts, "errors=panic") || strstr(opts, "debug"))) {
strcat(opts, ",errors=withdraw");
}
res = mount(source, target, fs, flags, opts);
if (res == -1) {
err = errno;
goto error_clear_loop;
}
res = open(target, O_RDONLY | O_DIRECTORY);
if (res == -1) {
err = errno;
goto error_clear_loop;
}
if (change_dir) {
res = chdir(target);
if (res == -1) {
err = errno;
}
}
error_clear_loop:
if (need_loop_device)
reset_loop_device(loopname);
errno = err;
return res;
}
uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
const char* reason;
(void)reason;
intptr_t res = 0;
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {}
// syz_mount_image$ntfs3 arguments: [
// fs: ptr[in, buffer] {
// buffer: {6e 74 66 73 33 00} (length 0x6)
// }
// dir: ptr[in, buffer] {
// buffer: {2e 2f 66 69 6c 65 30 00} (length 0x8)
// }
// flags: mount_flags = 0x8 (8 bytes)
// opts: ptr[inout, array[ANYUNION]] {
// array[ANYUNION] {
// union ANYUNION {
// ANYBLOB: buffer: {73 70 61 72 73 65 2c 73 70 61 72 73 65 2c 6e 6f 68 69 64 64 65 6e 2c 61 63 6c 2c 73 70 61 72 73 65 2c 64 69 73 63 61 72 64 2c 75 69 64 3d} (length 0x2e)
// }
// union ANYUNION {
// ANYRESHEX: ANYRES64 (resource)
// }
// union ANYUNION {
// ANYBLOB: buffer: {2c 69 6f 63 68 61 72 73 65 74 3d 63 70 34 33 37 2c 69 6f 63 68 61 72 73 65 74 3d 63 70 38 36 32 2c 69 6f 63 68 61 72 73 65 74 3d 63 70 38 36 35 2c 6e 6f 68 69 64 64 65 6e 2c 69 6f 63 68 61 72 73 65 74 3d 63 70 38 36 35 2c 68 69 64 65 5f 64 6f 74 5f 66 69 6c 65 73 2c 00 c5 e0 d3 02 c4 c4 d0 49 92 84 f5 fc 25 59 c4 52 59 09 7b 92 82 2e 84 c6 75 9a 16 19 01 ff b0 ee 41 b1 94 36 b5 1a bf 9d 24 06 9b 42 f7 d1 6d c2 54 7f ee cf c8 bd 5a 7f 55 19 20 3d 28 5c b8 34 2b 78 03 1f da 17 1d e1 f8 c9 a0 21 ec eb 4b 1c 26 e0 38 a5 1a a1 ac bf b3 f9 30 bb fa eb e6 d3 43 20 c9 e6 9a 1f 5f d0 92 58 6b e9 e1 64 8d 2c 3d 29 a3 99 d6 f1 5a 62 75 bc 76 ad 79 05 eb 8d fd 54 02 32 cf ec 68 11 39 53 55 1f b2 69 b7 b0 f7 f3 53 5c 12 41 20 e2 a2 84 c6 52 71 c7 79} (length 0xf9)
// }
// }
// }
// chdir: int8 = 0x4 (1 bytes)
// size: len = 0x1f771 (8 bytes)
// img: ptr[in, buffer] {
// buffer: (compressed buffer with length 0x1f771)
// }
// ]
// returns fd_dir
memcpy((void*)0x200000000040, "ntfs3\000", 6);
memcpy((void*)0x200000000080, "./file0\000", 8);
memcpy((void*)0x200000000400, "sparse,sparse,nohidden,acl,sparse,discard,uid=", 46);
sprintf((char*)0x20000000042e, "0x%016llx", (long long)0);
memcpy((void*)0x200000000440, "... [truncated large byte array] ...", 249);
memcpy((void*)0x200000020940, "... [truncated large byte array] ...", 128881);
syz_mount_image(/*fs=*/0x200000000040, /*dir=*/0x200000000080, /*flags=MS_NOEXEC*/8, /*opts=*/0x200000000400, /*chdir=*/4, /*size=*/0x1f771, /*img=*/0x200000020940);
// openat$cgroup_ro arguments: [
// fd: fd_cgroup (resource)
// file: ptr[in, buffer] {
// buffer: {63 70 75 61 63 63 74 2e 75 73 61 67 65 5f 73 79 73 00} (length 0x12)
// }
// flags: const = 0x275a (4 bytes)
// mode: const = 0x0 (2 bytes)
// ]
// returns fd
memcpy((void*)0x200000000040, "cpuacct.usage_sys\000", 18);
res = syscall(__NR_openat, /*fd=*/0xffffff9c, /*file=*/0x200000000040ul, /*flags=*/0x275a, /*mode=*/0);
if (res != -1)
r[0] = res;
// ioctl$FS_IOC_FIEMAP arguments: [
// fd: fd (resource)
// cmd: const = 0xc020660b (4 bytes)
// v: ptr[in, fiemap] {
// fiemap {
// start: int64 = 0xfff (8 bytes)
// len: int64 = 0x2 (8 bytes)
// flags: fiemap_flags = 0x1 (4 bytes)
// mapped: int32 = 0xa (4 bytes)
// count: len = 0x4 (4 bytes)
// reserved: const = 0x0 (4 bytes)
// extent: array[fiemap_extent] {
// fiemap_extent {
// fe_logical: int64 = 0x6bd (8 bytes)
// fe_physical: int64 = 0x6 (8 bytes)
// fe_length: int64 = 0xf5 (8 bytes)
// fe_reserved64: buffer: {00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// fe_flags: fiemap_extent_flags = 0x80 (4 bytes)
// fe_reserved: buffer: {00 00 00 00 00 00 00 00 00 00 00 00} (length 0xc)
// }
// fiemap_extent {
// fe_logical: int64 = 0x80000000 (8 bytes)
// fe_physical: int64 = 0x8 (8 bytes)
// fe_length: int64 = 0x8 (8 bytes)
// fe_reserved64: buffer: {00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// fe_flags: fiemap_extent_flags = 0x200 (4 bytes)
// fe_reserved: buffer: {00 00 00 00 00 00 00 00 00 00 00 00} (length 0xc)
// }
// fiemap_extent {
// fe_logical: int64 = 0x7 (8 bytes)
// fe_physical: int64 = 0x400000000000 (8 bytes)
// fe_length: int64 = 0x9 (8 bytes)
// fe_reserved64: buffer: {00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// fe_flags: fiemap_extent_flags = 0x1800 (4 bytes)
// fe_reserved: buffer: {00 00 00 00 00 00 00 00 00 00 00 00} (length 0xc)
// }
// fiemap_extent {
// fe_logical: int64 = 0x8 (8 bytes)
// fe_physical: int64 = 0x401 (8 bytes)
// fe_length: int64 = 0x8 (8 bytes)
// fe_reserved64: buffer: {00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// fe_flags: fiemap_extent_flags = 0x0 (4 bytes)
// fe_reserved: buffer: {00 00 00 00 00 00 00 00 00 00 00 00} (length 0xc)
// }
// }
// }
// }
// ]
*(uint64_t*)0x200000000840 = 0xfff;
*(uint64_t*)0x200000000848 = 2;
*(uint32_t*)0x200000000850 = 1;
*(uint32_t*)0x200000000854 = 0xa;
*(uint32_t*)0x200000000858 = 4;
*(uint32_t*)0x20000000085c = 0;
*(uint64_t*)0x200000000860 = 0x6bd;
*(uint64_t*)0x200000000868 = 6;
*(uint64_t*)0x200000000870 = 0xf5;
memset((void*)0x200000000878, 0, 16);
*(uint32_t*)0x200000000888 = 0x80;
memset((void*)0x20000000088c, 0, 12);
*(uint64_t*)0x200000000898 = 0x80000000;
*(uint64_t*)0x2000000008a0 = 8;
*(uint64_t*)0x2000000008a8 = 8;
memset((void*)0x2000000008b0, 0, 16);
*(uint32_t*)0x2000000008c0 = 0x200;
memset((void*)0x2000000008c4, 0, 12);
*(uint64_t*)0x2000000008d0 = 7;
*(uint64_t*)0x2000000008d8 = 0x400000000000;
*(uint64_t*)0x2000000008e0 = 9;
memset((void*)0x2000000008e8, 0, 16);
*(uint32_t*)0x2000000008f8 = 0x1800;
memset((void*)0x2000000008fc, 0, 12);
*(uint64_t*)0x200000000908 = 8;
*(uint64_t*)0x200000000910 = 0x401;
*(uint64_t*)0x200000000918 = 8;
memset((void*)0x200000000920, 0, 16);
*(uint32_t*)0x200000000930 = 0;
memset((void*)0x200000000934, 0, 12);
syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0xc020660b, /*v=*/0x200000000840ul);
// write$UHID_INPUT arguments: [
// fd: fd_uhid (resource)
// data: ptr[in, uhid_req[UHID_INPUT, uhid_input_req]] {
// uhid_req[UHID_INPUT, uhid_input_req] {
// type: const = 0x8 (4 bytes)
// data: uhid_input_req {
// data: buffer: {7f 96 54 d6 36 ab 18 b7 93 8a 28 04 50 5c 72 e9 99 4c a2 24 04 fc 20 33 34 cc 21 ed 3d 6a 77 6f d1 2d 13 f9 60 2b 29 80 f9 83 c3 1a 5d 1e 43 1d b7 78 09 9c e3 af 3f b2 0e 1e e1 f4 fd b7 7c bb 36 15 49 82 a9 3c 19 82 5d 6f d2 73 ab 1e b5 bc d4 7a da d5 0d e8 a6 79 14 86 e4 82 e2 9e cc 94 28 49 21 f3 3b 94 1c fc 10 00 c9 78 1d 9a 82 8c 5e c7 a2 c7 7b 4e 62 4a 5a a0 e9 e3 97 82 ba d7 33 ed a8 1b a4 7e 1c 61 16 e4 17 0e 65 87 dd 62 10 a5 7a be 91 f1 f8 0c 4e 31 13 9d 8b 73 fe 35 ac 1f 99 ea 82 dd 6a a9 c9 aa 67 de 88 ae 3e 14 10 20 e1 a8 76 bb c4 49 d2 d8 43 aa 7e 6d 90 b9 48 b7 e2 87 70 e6 ac 71 01 0c 63 f1 7e 90 fd 20 80 6a 9f 8d 9f 41 8e e3 af 74 aa c6 4b 04 a2 7c 4f 5e 36 26 ca 2d a5 46 c7 9d 24 ac ad d1 1e 8d 27 2a 22 fc 54 07 8f d5 e6 44 75 99 36 68 98 0a 9f 95 af f9 64 de e6 74 35 6a f4 92 b8 37 7a 75 9d 8c cf 1a cc b9 a1 8e f7 ad 16 f4 38 dd e6 9c d0 20 d7 15 52 b0 81 06 88 c8 82 a2 6a 22 b2 3f 4b 35 47 1b 08 b3 79 19 3d b1 cd 79 34 a4 04 9f f1 b0 0d 97 95 cd a6 e7 39 51 64 1d 5e 23 65 c2 4f ac d5 af d0 9e d1 d0 96 d7 58 b4 fe f6 6f e1 aa 22 39 5d 67 b7 e1 db 62 3d 4a 60 a7 dc 93 89 3d 6c 4a 91 df 79 53 5a 85 58 68 c5 dc 00 33 d5 c4 28 cd 25 b8 5c 5d eb 6e 81 06 85 53 bc 84 ce ad 4d 1e ba 8a a5 7e 2b 35 4a 68 99 e4 4a cb d3 83 44 91 21 9b 3e 23 1c d5 5d 82 f1 61 77 4a 68 9e fe 19 7c c1 93 ac 01 24 c6 77 38 a0 a1 d5 f1 6a 67 68 c2 c2 ba 73 86 c8 c9 5c a0 8c 55 11 7f 34 4f 5a 2b ca 0d 09 e7 9e a3 fc 49 49 1f 2c 7a dc 51 3c 27 79 c1 bf 62 b1 a8 64 3d 23 e9 e8 b2 ae 41 d4 a5 9f 1b 82 b8 2e 09 2b 36 eb 85 1b 84 56 da 87 1b 40 57 ae c3 25 a9 d4 cc ca fd e6 1f 2a bc 85 e3 ca be ab b8 56 f6 ff bf e2 3d 69 21 9e c8 fa e6 be b5 4a be 78 70 db ae 82 3d 49 80 6a 96 7a 1c 7f 25 29 99 80 4f 10 67 45 f2 04 90 bb 33 47 b5 93 21 dc 69 76 55 67 ab cb d8 9d e0 4d 89 62 21 70 00 5d f5 87 1e d0 fb 72 34 5a 11 da 07 40 60 d7 d4 ee 2e 43 7f 71 a4 57 23 fb 6b 02 de 56 06 7e 54 f5 4c 52 d1 0f 78 74 a1 3c bf b3 bd 65 ce 54 f9 d6 71 9e a2 10 e0 cf 79 e4 e2 15 77 36 ec 07 ac 59 15 68 2a b8 1b ce d6 65 c1 e7 2f ab 8d 8c fe 50 9d e0 f2 1f e3 74 b9 57 b3 79 fd 59 18 06 1e 21 c2 e9 69 85 cc 13 54 b2 de 85 9b 0f 1a 46 3a b0 46 83 b1 25 3e da 67 1c 23 53 b5 c2 08 ac a6 52 f5 41 9f fc 49 49 a7 fa 90 9b 95 65 3f 42 d9 73 90 c4 00 b4 a1 c3 08 b1 1e 73 e9 a0 6d 3b 16 4d 33 61 e7 55 84 d7 0e 6b c6 1d 57 0a 7e 0c 7d a3 30 f6 43 19 4c 18 93 fc d6 48 9f ac 60 5e ea d6 1b 53 df f1 8c af 52 6e cc cc 9b bd 91 46 bc 3c 3b b6 76 77 69 5e 6f dd aa b0 81 78 6e 90 84 01 4e 60 f5 c0 3a e5 a9 08 77 26 b0 5e 17 40 2c d2 fb b8 0d 77 3b 8a 41 47 0b 1f 90 1a 8c 2b 2d 57 45 01 81 f4 fc 5b c5 3c 7c b3 dc 03 2b 84 56 74 92 60 7c b0 88 32 ec a9 f7 9d a9 21 0d 19 78 63 e5 db 5a 74 a9 82 3d c0 cc 8b d9 f3 a9 b6 ff 5a 7d 15 d4 74 7a 9b 26 e0 88 f4 fa d9 6d 81 cd 12 14 22 6b 1c 45 85 d4 18 d5 93 22 0f cb b9 ad 94 92 66 cc 48 16 3e 34 98 b4 6e bc df 7b 2b 5e cf e6 75 39 a6 1e d9 e3 9b 02 d5 b3 5a c0 d0 e7 fa 83 00 34 ca 2d a8 a7 dd f0 4b cf 2c ee 93 99 94 36 9f eb 77 02 3e 0e 3d e0 4b 21 db 7a 64 0a 92 c1 77 48 24 50 05 cd 75 a7 de ba 4f f0 e4 c1 04 a9 db 2d 9a 98 ec 8e db 35 62 05 0a 3b ac 5f 32 22 90 e3 d8 b6 fb 21 77 0a c4 36 d4 cb 12 b9 7f c8 f7 6d 7b b9 ee ed 85 66 3e b0 62 6f 1a d1 71 9e e4 b0 7f 7d e2 c1 d1 a3 1c 27 c6 87 9f 4f a3 db df b2 bf c0 89 8b ea ba fb ec a9 f1 30 50 e6 b2 f6 c4 32 e4 23 cd 5c b6 b8 fa 56 fe 32 c3 e5 01 04 e4 44 62 c0 a5 c6 9d e6 a7 ac 5a e3 d9 f0 7c ee d6 4d bf fa 42 e4 66 38 38 bf cd e9 2f 0f cb 89 5f 3b 93 c5 9b 0e 48 c0 98 90 df c3 64 36 db 56 b7 08 f6 e7 cb bd 2a 63 05 f5 73 ce e0 99 db cd 26 3c b9 6d 9f b6 9c bc 3c b0 6d 8f 5e 37 89 69 8a 17 e7 1d 22 b4 66 5f f5 44 7f cc 17 a3 1b b1 36 c8 bb 4b 98 45 73 bc af 1c b6 50 19 8c 12 66 e6 dd fd 42 d4 4f 9d e0 2c b9 d9 15 c5 33 4c 55 0f ac 3f ce e5 67 90 ae b0 9d 81 e7 69 0a 32 d8 b0 cc 47 7b 23 f1 52 57 82 0d e2 27 be 1f fa ec 2f 63 f3 26 6b 8f 5d d7 89 47 dc ee 35 5f e5 9b fb 10 0e 52 44 42 55 32 bb 1d 11 5a cd 21 1b 8c 16 b0 ec 0a ae 00 fc a5 d4 51 1a 05 c3 ff 02 7a 1c ac 56 21 0a 10 d8 1c 01 b9 0e 15 6c c7 b3 3d e0 fa c8 25 dc 51 6d 39 81 66 09 60 13 e0 68 db 93 54 83 c9 3b a9 5d a3 9b 5a e4 08 7d 84 47 9a 4c 48 09 f2 8f 93 79 0d c2 79 63 7b d6 f3 dc 44 1d 31 5c f6 bd 7b 0e 3d 92 07 0a 45 ba f4 44 5c e0 63 fd 12 69 0e b0 02 f5 ca 06 8a 25 6b c5 41 00 c9 9a 02 a3 46 be ca 39 07 21 63 c4 b2 97 d1 17 f1 ed 9f ef 42 e3 db c1 1d 36 a0 a0 db 52 e8 44 61 c6 fb b4 aa d6 2c d6 c8 dc 9a e6 a3 39 0a 5e 87 73 ac 59 9e 67 43 62 20 c8 d5 41 a9 03 97 62 bf fa a7 f4 90 e3 1d dd bc 36 2f b4 ff 68 6c da 90 5f 3b 02 a1 db 76 d4 d5 70 d9 70 43 49 21 ca 8a 47 65 af 6d 5c 8b 88 1e 1f 4f fa 7e 2d 9e f5 f5 51 1b 94 f8 84 74 67 4e c7 90 bb 51 86 c7 34 46 a2 27 bf 1f fd 19 b6 05 73 3a bd 1b d4 1e 42 1a ea f2 ed 46 17 08 8c 7c ee f8 54 51 22 50 56 43 59 93 e8 9e 4b cc d2 c2 e4 b3 9a f9 9f ee f1 1f ea 64 5e eb 5c f9 f7 7b 1e 19 a7 2d 3e fb 61 31 00 96 9b 84 30 27 89 71 4b ca 65 bc bc 96 76 2b 40 12 a5 70 0c 62 ae d7 06 43 3b 9f 14 2b 73 02 44 2b 6a 99 58 b0 e2 8e 8b 1c fa 9e eb 4a c0 d7 1f 49 7b 23 ba bf 9f 02 21 dc b6 58 d9 f4 db 5d 45 be e3 0d 2a d7 c9 7d 6a 56 2e 01 4a 77 01 c1 53 25 ec 5d 42 ab 73 2b 37 71 4a 77 a9 5c 03 fb 15 bb fb a6 fa de 32 bf 50 f9 85 a1 df 36 2c a7 21 6c c1 52 90 7d d9 31 ac b5 8a 63 92 0f 58 1e 82 b5 90 c0 d6 a0 03 30 09 f8 e5 0c 32 63 d3 f5 85 96 b6 3d 50 7c ad bc 80 9a 66 90 56 1f 74 d0 77 2b f9 2d 04 e0 6c 47 a3 50 72 4b 10 6f 5e 83 f7 e7 1c 4b 2a 98 3b f5 ad 7d 86 84 e7 b8 b5 dc 12 73 d0 fa 58 79 b8 e6 1b de 33 d6 02 bc 8f f0 91 3b 6d 32 dc ac 36 6d 56 8d c7 cf 82 bb fc 40 5c be 41 8a 26 44 c2 65 92 b3 2c a1 a6 32 fc 95 12 3e fb 78 4c fb 69 53 a9 4e be cc d2 4f ba 38 9a 0e 56 b0 43 df 07 d9 a2 dd 38 a1 19 6e 5e 55 57 6b 25 f8 5c b9 6f 65 60 80 2a 4a 58 b7 a6 85 7e 84 54 fa a2 c8 80 bf 32 d4 64 56 2b 2b dc 5f 0d f2 2b 66 3f 2c 01 fc 94 4f 1c fd 19 08 f6 17 f8 29 5a 54 40 bb 79 ae 17 8e a4 6a 95 ba ee a4 83 22 10 51 46 ac 3e d2 de 7d 37 96 dd dd cc 84 8a 8e cf 4a 00 dd 05 57 33 b4 f5 92 11 f5 a4 0d ee a4 4e 74 b3 bc 57 95 3b 26 ed 61 e6 fd 67 88 9e df e8 d0 90 23 85 e3 76 66 aa ce c0 72 73 56 30 ec c4 41 c3 cc 6b 09 bb 2f 63 aa 4e 33 2c 6d f7 28 dc 74 07 8a 83 ce 20 45 4d fd 61 6d 11 62 70 66 6d dc 09 c5 fe a2 e8 44 2b c4 34 55 d0 25 7f ac 92 f3 78 00 61 17 8f 94 20 bf 8e 46 3f 29 89 6c 12 38 3d bb 9a 81 bc 5c 87 37 6e 64 7c 8a 79 86 cb 51 4f b9 69 6d 9c 0a 8d 30 3c 5c 4b 5b 7c 5f 60 1c 01 fa 19 32 3e 02 f6 75 c3 71 bc 44 fb c1 ac 57 04 d4 1a 89 a2 a4 cc ec 6a c8 44 0c 53 2f 07 da 25 aa 2d ce 6a 5d 2e be 69 4e b4 01 7d 17 8b 22 12 13 bf e2 a0 1d 9c fe 68 9b d1 90 77 6b ca 6c 03 2f 44 6e b8 86 25 87 a7 82 6e 35 f3 f6 91 76 32 12 ee e6 af 2e 49 bb eb 0a 27 e0 7c 57 14 b7 4e 37 37 98 c7 be bc e2 65 f7 eb ef 3a 1e a6 40 78 cf 1e 8a 9d 43 3a f3 2c 53 09 0c 97 2f fe db ad af b5 0b 9a 6e 54 0a bd 84 f8 e9 38 58 3e a7 25 95 4b e3 b2 36 c5 d8 ac a7 d4 86 d2 19 02 a2 90 2f 25 a7 c0 2d be 83 c3 9b d0 b8 15 13 f9 ef 19 8c 49 d5 60 e9 30 ae 22 4f f4 7f 92 e4 85 1e 1f 7a b5 bb 40 6a bc f6 59 65 69 26 1e 6b 0c 67 bb 3b 85 4e 9c 6d e6 0b fb 60 fc f2 92 41 ff 23 71 51 31 0e cd 19 f8 b2 cf e7 64 c1 df 1a 2d e9 d8 40 ec a4 7a a1 69 ba 9a 41 59 01 20 4e c3 1c cd fd 76 e9 08 02 9a e3 4f b1 2d c2 86 75 8c 64 fd 6d 42 bc 82 b1 4e 07 e4 21 f4 b4 2b 18 0c d6 ef 40 ca c8 06 29 28 b4 a4 20 a4 57 7f 24 29 5f 54 de 90 48 ac 9d 34 30 7b f9 3e 46 3c ea 49 67 cf 48 80 16 6f 68 ed 1e b9 65 db 2e 4f b9 f5 f0 b1 c6 95 d6 21 e4 27 cc b9 a3 18 80 73 ee 6f de 72 9c 66 98 34 6e fa 1c 0b a6 43 c1 ef d2 08 58 96 55 11 da 75 00 60 d5 51 c4 4c 43 5a 5f 16 03 fa e7 35 7e 0b c7 8e 92 aa d3 d8 87 90 ec 2a a1 a4 2d 6f e7 e0 ff c5 7f 35 99 e4 06 db 63 be 7d d3 26 92 df 32 ce 33 de e0 a2 be cd b0 2d 6e 43 5e 09 de 3d 35 64 97 54 3d b2 3f 53 da 25 64 3f 9c 58 5e 27 52 97 80 0d 8b ee d4 7f 0e 62 2f 86 fc 25 d2 e8 70 36 fd ce eb fe 72 57 cb 6d e0 c0 24 12 d1 c0 75 8a cf cd 08 62 e9 9a d1 7a 11 8f 46 f6 35 a8 74 77 e8 b8 25 42 3d 94 ad a3 5b f0 b5 44 4a a7 d3 de 4b b7 ee c7 ae 51 29 fc c2 cb a6 51 cc 97 2f 55 00 fc 51 61 14 9d 29 f4 52 96 2a fb 10 2a 01 ae 76 82 5c b4 47 74 60 be 0b 85 d7 50 58 59 5c 27 e9 b7 fa e3 49 2e c3 92 5c 67 1b ee 5f 4c a5 34 d5 a2 94 f7 83 d6 cc 07 3c 99 21 39 b6 1d 21 fd 98 29 7b 04 c0 57 8d af d5 f7 eb ca f8 d4 d9 18 5a ea 3d 76 e8 13 42 1f 45 73 b3 8c 25 09 3c 01 5a 65 e4 4f b2 97 f0 f6 ac 2d 02 c4 23 7b 37 a3 bf ca 24 06 c5 c9 5a e5 81 28 16 ba ca d5 9b a7 c6 f7 2d 7c 64 4f f2 5b 59 2e d1 e8 9b 27 6e 05 86 6c 01 a4 ce d7 fc 6d d9 f1 90 c2 0d 42 0d 7c 8a 1f e9 08 83 3a 24 c5 e5 bd 7a 95 a2 a6 fb f1 47 fc 4b 29 a1 79 71 81 66 dd 0f ba e2 fc 6b 8c 8a ac 61 94 fa 6b af 0d 3e dc 36 b2 31 6c 56 c4 41 ba 53 e3 e7 aa af 0a 14 05 56 6f f5 84 f7 3a 63 7b 74 dd e9 bc b4 d4 1d a2 be 6c 9d f5 d5 33 fb ac 54 f5 fb 52 a8 a7 93 75 7c fe 19 aa 90 04 8c 6d 07 e3 47 41 36 ae 1b e2 45 5b 0d 0d 02 eb 4b 59 61 ba 88 32 09 35 5c 0d d2 af 4a ad 98 e7 b9 71 e3 58 a7 d9 b5 5f e1 7c d6 09 5f 25 73 55 d9 b9 9e 5e a5 28 48 f1 7b 35 a8 07 92 d9 ed 0f ef 6f e3 ee f9 a3 24 90 24 09 96 98 23 be 20 bb e0 e8 db a9 c7 47 cd 1a 14 d3 64 2d 87 7b 86 27 1f 3f 0c 32 2a 14 2c 4f f6 35 b3 7d 54 2c 32 65 b5 fe 85 89 a7 32 bb 1a 55 01 0b 93 0d d0 19 6c d4 3a c3 63 4c 01 b4 a4 4c 51 71 97 d0 3a 3d 89 c6 7f 5c 09 aa b4 09 e8 4c 0a f4 66 bf bd 0c 96 d2 40 10 1a 25 42 c6 6b 4b 4b 8e f6 5b 41 b0 07 99 95 c5 2c c9 72 0d 2c 1d 7c 12 8c 6f 17 a6 5c c7 98 c1 98 6c fb d8 88 84 60 c5 44 38 ed c4 f9 1f 35 80 39 1c 8b 57 d9 ae e2 09 a5 9a 11 6c 1c 44 77 54 37 e9 c3 0e 6d 87 e8 2c e8 4e 28 53 2b 19 44 1e 32 ab 9a ea 22 17 7b ac 9d aa d2 5a 6c 88 39 5e 93 48 d6 78 0d e6 30 cd db 26 6c 41 10 11 17 5b db 62 55 a3 65 35 18 08 18 44 7d 43 ff ba 37 58 d3 11 53 9f e9 f6 81 1f a4 70 bf 37 67 b4 c2 d4 cd f3 78 54 c7 ee 28 73 0b b1 d3 9d 5c 0d ff fc db f3 53 cc a3 e1 30 79 f3 ae 66 b8 39 c7 dd 36 91 40 22 a0 e7 5b ca 5b 62 2f 52 14 20 b7 32 49 ef 47 f0 3c 1f b0 3e cf 75 57 88 2a fc aa 7c f4 54 a6 8a d2 37 d4 ce 86 0b d6 b1 53 1c 1c af e2 cf b7 6b c4 18 82 71 ef 6b df b3 04 ee 0e 69 32 46 3a 19 09 f0 3d 6e 8a 27 b5 f1 37 d6 b3 42 84 1d 61 38 63 df df 37 d5 ec 3a 98 d6 67 81 0f b6 f8 2d 67 62 0b de fe d8 b3 ff 98 42 0a 6c 7e e5 77 c3 ba 68 b9 5a 20 40 36 08 a7 ba 65 26 ec 9e 86 62 c6 e1 5a b0 9b 1a 90 19 d4 95 8a f0 4c b2 e4 89 0e e6 b1 07 7f ca a5 cc 08 17 f3 88 46 1b 23 0f e6 31 e7 5f 18 ab 39 2a 5c a5 de 4a 02 4c a1 6d d0 5f cf df 92 11 4e 43 a5 c4 a1 69 d4 62 ff 0d ba 57 de ea f5 ea af d8 92 f8 cc bd 72 ac 56 47 11 62 e1 41 6b ca 39 85 9b 41 84 ba 0d 1b 3f 7e c0 5d b4 ef 4c f0 14 28 67 fa 9b e3 28 a0 be 8a a7 4c 71 6a ad 94 11 00 86 07 98 08 61 f4 f7 2e 9b fa 60 19 5e 2f 93 9d 3f 6a 44 a6 ce c0 7d d3 76 d1 bc ca a1 26 68 6f 31 3d 5f 79 18 ec d1 21 50 26 98 2c 82 ed 19 22 ef 70 e3 6e 8e d5 9b 2d 5c ea b3 b4 aa d7 e5 30 49 06 2d d5 ba 0e 87 f7 00 5c 3f 4d 2b 78 82 45 cd c2 f3 5e f2 57 2b ea 5e a9 2d fa d4 06 ad e6 d5 ad 18 be 8e eb 4c 65 2e 52 77 b2 44 64 5c 68 c0 c0 f5 a6 8d 42 e0 0d 59 b7 59 41 91 7b 2c df 31 fd f8 09 f2 07 8c a9 7f d5 be ba 65 b3 4e 06 21 13 8e a0 e9 4f eb 87 16 6b 2d ac 22 32 eb ca 57 5e 5c 0a 4d 56 5d 99 92 f7 33 bb fb e6 8a 63 d9 9e e9 33 98 60 40 65 d5 51 7c 33 ed 0e 06 7b db 64 3e 73 10 2f 16 13 7a fd 7d 4b f2 1e 80 65 ea 02 8c 39 2a 6d ce fb e6 42 dc 3f b0 3a 23 9d 9c 8b 17 02 3e ac c8 e1 9f ea 11 c3 4a 10 64 4a f1 b7 86 fc 0f 45 04 03 8c 2e e5 9c 1b 35 3f 3d 7b 93 13 df 02 5b 4b 58 74 ca 63 ec 16 4a 3f e3 5b f3 90 d2 66 f5 3d cd a6 a8 e1 90 e6 3a 56 ff df 4f 7c 5c 02 aa 22 d3 76 db 06 d4 d2 b9 6b e5 b3 31 f8 97 d1 ec fd 25 c1 3a 1c 19 4c 26 5d d9 5a 57 24 a6 43 5b c8 13 82 24 d9 db 28 b6 89 b9 ce a5 13 2c d1 96 01 db c4 a4 3e 70 c7 1e 27 e8 fd 06 89 d0 94 84 97 4e 8a 46 05 f8 55 37 35 ff fa f5 65 4a 08 7e 32 3c a1 4e 02 b6 81 b9 bb e5 92 bd 6b 71 9a e2 e8 6b df 91 8b 27 c7 9d 52 dd 33 4d 1a a7 eb c1 bf f7 6e 97 57 2f aa d0 92 01 0a 10 22 f7 d3 30 89 04 91 07 a8 9c 36 4a e7 dd 02 2d 11 9e 8f 6a b7 95 fd 71 d7 6a 90 e8 20 23 39 40 1f f9 e9 91 8e a8 c8 e1 2f 7b 0b a1 0d 9e bd e5 d1 bc 59 88 f2 d0 7b 34 57 9d 8c 28 26 28 20 4f 29 78 d8 b0 cf 95 dc 41 f3 77 5a 40 53 f8 33 26 7c 64 b4 23 36 d7 c8 50 f2 91 8e f0 dd 6d 62 e4 3f cc 17 32 54 eb 34 74 8e fd 47 54 60 9c e2 5a fd 64 8e e5 a8 fc 5c 64 34 66 03 f8 25 85 92 d6 7b 96 13 e8 f7 ac 0d ef 09 58 f1 34 36 58 1d 72 9e 0b 3e 06 27 38 eb 06 b2 11 6a be 83 75 29 69 0a 61 4f c5 d3 f5 3b 4d 46 02 e5 70 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00} (length 0x1000)
// size: len = 0x1000 (2 bytes)
// }
// }
// }
// len: len = 0x1006 (8 bytes)
// ]
*(uint32_t*)0x200000010140 = 8;
memcpy((void*)0x200000010144, "... [truncated large byte array] ...", 4096);
*(uint16_t*)0x200000011144 = 0x1000;
syscall(__NR_write, /*fd=*/r[0], /*data=*/0x200000010140ul, /*len=*/0x1006ul);
// mmap arguments: [
// addr: VMA[0x400000]
// len: len = 0x400000 (8 bytes)
// prot: mmap_prot = 0x1 (8 bytes)
// flags: mmap_flags = 0x10012 (8 bytes)
// fd: fd (resource)
// offset: intptr = 0x0 (8 bytes)
// ]
syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x400000ul, /*prot=PROT_READ*/1ul, /*flags=MAP_NONBLOCK|MAP_FIXED|MAP_PRIVATE*/0x10012ul, /*fd=*/r[0], /*offset=*/0ul);
// symlinkat arguments: [
// old: ptr[in, buffer] {
// buffer: {13 13 77 c5 fc 35 d4 14 54 d5 d4 1d 29 ad 1a 60 29 59 81 46 e6 be 16 6e 41 ad 0d bd 40 54 03 3c 9f 33 bb da 82 24 a2 f3 d7 72 e7 63 6e 48 b3 3c bf 70 83 72 e8 f1 b9 93 3e c5 12 77 43 be 22 06 20 9e f0 2d f9 cb f2 f6 e8 80 d3 38 2f 00} (length 0x4e)
// }
// newfd: fd_dir (resource)
// new: ptr[in, buffer] {
// buffer: {2e 2f 66 69 6c 65 30 00} (length 0x8)
// }
// ]
memcpy((void*)0x200000001040, "... [truncated large byte array] ...", 78);
memcpy((void*)0x200000000000, "./file0\000", 8);
syscall(__NR_symlinkat, /*old=*/0x200000001040ul, /*newfd=*/0xffffff9c, /*new=*/0x200000000000ul);
// syz_mount_image$ntfs3 arguments: [
// fs: ptr[in, buffer] {
// buffer: {6e 74 66 73 33 00} (length 0x6)
// }
// dir: ptr[in, buffer] {
// buffer: {2e 2f 66 69 6c 65 30 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 00} (length 0xfe)
// }
// flags: mount_flags = 0x2010c10 (8 bytes)
// opts: ptr[inout, array[ANYUNION]] {
// array[ANYUNION] {
// }
// }
// chdir: int8 = 0x1 (1 bytes)
// size: len = 0x1f757 (8 bytes)
// img: ptr[in, buffer] {
// buffer: (compressed buffer with length 0x1f757)
// }
// ]
// returns fd_dir
memcpy((void*)0x200000000080, "ntfs3\000", 6);
memcpy((void*)0x200000000500, "... [truncated large byte array] ...", 254);
memcpy((void*)0x20000001fd80, "... [truncated large byte array] ...", 128855);
syz_mount_image(/*fs=*/0x200000000080, /*dir=*/0x200000000500, /*flags=MS_LAZYTIME|MS_POSIXACL|MS_SYNCHRONOUS|MS_NODIRATIME|MS_NOATIME*/0x2010c10, /*opts=*/0x200000000380, /*chdir=*/1, /*size=*/0x1f757, /*img=*/0x20000001fd80);
// openat$cgroup_ro arguments: [
// fd: fd_cgroup (resource)
// file: ptr[in, buffer] {
// buffer: {63 70 75 73 65 74 2e 65 66 66 65 63 74 69 76 65 5f 63 70 75 73 00} (length 0x16)
// }
// flags: const = 0x275a (4 bytes)
// mode: const = 0x0 (2 bytes)
// ]
// returns fd
memcpy((void*)0x200000000040, "cpuset.effective_cpus\000", 22);
res = syscall(__NR_openat, /*fd=*/0xffffff9c, /*file=*/0x200000000040ul, /*flags=*/0x275a, /*mode=*/0);
if (res != -1)
r[1] = res;
// ioctl$EXT4_IOC_MOVE_EXT arguments: [
// fd: fd (resource)
// cmd: const = 0x40305829 (4 bytes)
// arg: ptr[in, move_extent] {
// move_extent {
// reserved: const = 0x17c04 (4 bytes)
// donor_fd: fd (resource)
// orig_start: int64 = 0x5 (8 bytes)
// donor_start: int64 = 0x100000001 (8 bytes)
// len: int64 = 0x0 (8 bytes)
// moved_len: int64 = 0x0 (8 bytes)
// }
// }
// ]
*(uint32_t*)0x200000000080 = 0x17c04;
*(uint32_t*)0x200000000084 = -1;
*(uint64_t*)0x200000000088 = 5;
*(uint64_t*)0x200000000090 = 0x100000001;
*(uint64_t*)0x200000000098 = 0;
*(uint64_t*)0x2000000000a0 = 0;
syscall(__NR_ioctl, /*fd=*/r[1], /*cmd=*/0x40305829, /*arg=*/0x200000000080ul);
return 0;
}
]
|
| 2/1 |
2026/05/15 19:28 |
action |
kernel-checkouter |
1m
Results: map[KernelSrc:/app/workdir/cache/src/bf3dba30652dffc3c24bbc566206d91cf02e4974]
|
| 3/1 |
2026/05/15 19:30 |
action |
kernel-builder |
34m
Results: map[KernelObj:/app/workdir/cache/build/2e3b7e19d0251905e55e99f1427a34445d145d0f]
|
| 4/1 |
2026/05/15 20:05 |
action |
codesearch-prepare |
24m
Results: map[Index:codesearch-index]
|
| 5/1 |
2026/05/15 20:30 |
agent |
expert |
5m
Model:
Results: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:true UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
Instruction:
You are an experienced Linux kernel security engineer. Your task is to analyze given kernel bug report
and determine its security impact based on the following dimensions.
Use the provided tools to examine the source code, check for capability checks (e.g., capable(), ns_capable()),
and understand the nature of the bug. Analyze the given kernel build and configuration.
You can check the kernel config by grepping ".config" file; you can check kernel cmdline by greeping
".config" file for "CONFIG_CMDLINE=". Assume sysctl parameters have default values.
But analyze for the corresponding production build w/o debugging tools enabled (like KASAN, KMSAN, UBSAN).
Don't make assumptions; verify them with source code access. Try different strategies when analyzing the bug:
- think of ways in which the vulnerable code is unreachable
- or the other way around: try to come up with different ideas of how an unprivileged user can reach the bug
If still unsure err on the side of the bug being non-exploitable/not-accessible.
In the final reply, provide a reasoning for your assessment.
Analysis dimensions:
* Exploitable:
Determine if the bug can result in memory corruption or elevated privileges.
Memory safety issues are almost always exploitable (KASAN or UBSAN reports for use-after-free, out-of-bounds;
refcounting issues, corrupted lists, etc). When kernel is crashing on a completly wild pointer access
(e.g. user-space address, or non-canonical address, but not on NULL or address corresponding to KASAN shadow
for NULL address), including both data accesses and control tranfers, that's also usually implies possibility
of exploitation. Such reports usually say "unable to handle kernel paging request".
Uses of uninitialized values detected by KMSAN may be exploitable b/c attacker frequently can affect uninit
values with spraying techniques. However, for these exploitabability depends on how exactly the uninit value
is used in the code, and what it affects.
Think of what happens after the bug is triggered. Some bugs cause kernel panic and halt execution,
they are harder to exploit. For example, BUG reports halts the kernel. However, WARNING reports don't halt
execution in production builds. Debug bug detection tools (like KASAN, KMSAN, KCSAN, UBSAN) are also not enabled
in production builds, so attacker can freely exploit these bugs w/o being detected by these tools.
If you see an integer overflow, think how the overflowed value used later (if it's used as allocation size,
or an array index). If you see an out-of-bounds read, think if it's followed by an out-of-bounds write as well.
Some KCSAN data-races may be exploitable by skilled attackers as well. Think what data structures got corrupted
as the result of data races and how. However, note that kernel has lots of "benign" data races that don't lead
to any runtime misbehavior at all.
* Denial Of Service:
Determine if the bug can result in denial-of-service. Most bugs can, since they cause system crash,
hangs, deadlocks, or resource leaks. This is mostly applicable to WARNING bugs that won't cause system crash
in production. For these think what will be consequences of the violation of the kernel assumptions flagged
by the WARNING. In some cases the unexpected condition is also properly handled by the normal control flow
(e.g. with "if (WARN_ON(...))"), these won't cause denial-of-service. If the condition is not handled,
then it may or may not cause denial-of-service.
* Accessible From Unprivileged Processes:
Determine if the bug can be reached from a typical (non-root) user process that does NOT have any special capabilities
(like CAP_SYS_ADMIN, CAP_NET_ADMIN, CAP_NET_RAW, CAP_PERFMON) or access to device nodes restricted to root.
Assume that unprivileged_bpf_disabled=1, that is eBPF loading is not accessible. However, cBPF (classical BPF)
is still accessible to non-root processes.
Assume that user namespaces are not accessible, that is, the process cannot get the mentioned capabilities even
within a new user namespace (checked by ns_capable() function in the kernel sources).
* Accessible From User Namespaces:
Determine if the bug can be reached within a user-namespace where the process has all capabilities
(including CAP_SYS_ADMIN, CAP_NET_ADMIN, CAP_NET_RAW, CAP_PERFMON). Such capabilities are checked with ns_capable()
function in the kernel sources.
* VM Guest Trigger:
Determine if the bug can be triggered from the context of a typical KVM guest (e.g., set up by a QEMU VMM).
Consider accesses to standard Linux host paravirtualized features (virtio-blk, virtio-net, etc.),
and handling of VM exits in the KVM code.
* VM Host Trigger in The Confidetial Computing Context:
Determine if the bug can be triggered in a confidential computing guest kernel from the context of a KVM host.
Consider access to standard Linux guest paravirtualized features (virtio-blk, virtio-net, etc.).
* Ethernet Network Trigger:
Determine if the bug can be triggered by processing ingress network Ethernet traffic, either directly (network stack)
or via drivers exposed to network data.
* Other Remote Trigger:
Determine if the bug can be triggered by processing remote traffic other than Ethernet (Wifi, Bluetooth, NFC, etc).
* Peripheral Trigger:
Determine if the bug can be triggered via an untrusted peripheral device that can be physically plugged
into a system, such as a USB device or a niche hardware driver handling external hardware inputs.
This is particularly important for mobile and desktop environments where users can plug in unknown devices.
* Malicious Filesystem Trigger:
Determine if the bug can be triggered by the kernel mounting and parsing a malicious filesystem image.
This is highly critical for Desktop and Mobile environments where external media or downloaded images
might be auto-mounted.
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt:
The kernel bug report is:
======================================================
WARNING: possible circular locking dependency detected
6.17.0-rc1-syzkaller-g8f5ae30d69d7 #0 Not tainted
------------------------------------------------------
syz.3.855/8482 is trying to acquire lock:
ffff0000f5573468 (&ni->ni_lock#3/5){+.+.}-{4:4}, at: ni_lock fs/ntfs3/ntfs_fs.h:1113 [inline]
ffff0000f5573468 (&ni->ni_lock#3/5){+.+.}-{4:4}, at: ntfs_fallocate+0x450/0xdd4 fs/ntfs3/file.c:561
but task is already holding lock:
ffff0000f55738a0 (mapping.invalidate_lock#3){++++}-{4:4}, at: filemap_invalidate_lock include/linux/fs.h:924 [inline]
ffff0000f55738a0 (mapping.invalidate_lock#3){++++}-{4:4}, at: ntfs_fallocate+0x324/0xdd4 fs/ntfs3/file.c:546
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #2 (mapping.invalidate_lock#3){++++}-{4:4}:
down_read+0x58/0x2f8 kernel/locking/rwsem.c:1537
filemap_invalidate_lock_shared include/linux/fs.h:934 [inline]
filemap_fault+0x3fc/0x1280 mm/filemap.c:3433
__do_fault+0x1fc/0x4cc mm/memory.c:5152
do_read_fault mm/memory.c:5573 [inline]
do_fault mm/memory.c:5707 [inline]
do_pte_missing mm/memory.c:4234 [inline]
handle_pte_fault mm/memory.c:6052 [inline]
__handle_mm_fault mm/memory.c:6195 [inline]
handle_mm_fault+0x2c90/0x4d34 mm/memory.c:6364
do_page_fault+0x57c/0x13cc arch/arm64/mm/fault.c:696
do_translation_fault+0xc4/0x114 arch/arm64/mm/fault.c:789
do_mem_abort+0x70/0x194 arch/arm64/mm/fault.c:929
el1_abort+0x3c/0x5c arch/arm64/kernel/entry-common.c:481
el1h_64_sync_handler+0x50/0xfc arch/arm64/kernel/entry-common.c:597
el1h_64_sync+0x6c/0x70 arch/arm64/kernel/entry.S:591
__uaccess_mask_ptr arch/arm64/include/asm/uaccess.h:-1 [inline]
do_strncpy_from_user lib/strncpy_from_user.c:41 [inline]
strncpy_from_user+0x198/0x370 lib/strncpy_from_user.c:149
getname_flags+0xe8/0x470 fs/namei.c:157
getname include/linux/fs.h:2918 [inline]
__do_sys_symlinkat fs/namei.c:4772 [inline]
__se_sys_symlinkat fs/namei.c:4769 [inline]
__arm64_sys_symlinkat+0x7c/0xb4 fs/namei.c:4769
__invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49
el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:132
do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151
el0_svc+0x58/0x180 arch/arm64/kernel/entry-common.c:879
el0t_64_sync_handler+0x84/0x12c arch/arm64/kernel/entry-common.c:898
el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:596
-> #1 (&mm->mmap_lock){++++}-{4:4}:
__might_fault+0xc4/0x124 mm/memory.c:6958
_inline_copy_to_user include/linux/uaccess.h:192 [inline]
copy_to_user include/linux/uaccess.h:223 [inline]
fiemap_fill_next_extent+0x17c/0x3f0 fs/ioctl.c:145
ni_fiemap+0x2e8/0x9ec fs/ntfs3/frecord.c:1896
ntfs_fiemap+0x10c/0x188 fs/ntfs3/file.c:1326
ioctl_fiemap fs/ioctl.c:220 [inline]
do_vfs_ioctl+0x1140/0x1834 fs/ioctl.c:532
__do_sys_ioctl fs/ioctl.c:596 [inline]
__se_sys_ioctl fs/ioctl.c:584 [inline]
__arm64_sys_ioctl+0xe4/0x1c4 fs/ioctl.c:584
__invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49
el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:132
do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151
el0_svc+0x58/0x180 arch/arm64/kernel/entry-common.c:879
el0t_64_sync_handler+0x84/0x12c arch/arm64/kernel/entry-common.c:898
el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:596
-> #0 (&ni->ni_lock#3/5){+.+.}-{4:4}:
check_prev_add kernel/locking/lockdep.c:3165 [inline]
check_prevs_add kernel/locking/lockdep.c:3284 [inline]
validate_chain kernel/locking/lockdep.c:3908 [inline]
__lock_acquire+0x1774/0x30a4 kernel/locking/lockdep.c:5237
lock_acquire+0x14c/0x2e0 kernel/locking/lockdep.c:5868
__mutex_lock_common+0x1d0/0x24ac kernel/locking/mutex.c:598
__mutex_lock kernel/locking/mutex.c:760 [inline]
mutex_lock_nested+0x2c/0x38 kernel/locking/mutex.c:812
ni_lock fs/ntfs3/ntfs_fs.h:1113 [inline]
ntfs_fallocate+0x450/0xdd4 fs/ntfs3/file.c:561
vfs_fallocate+0x52c/0x668 fs/open.c:342
ioctl_preallocate fs/ioctl.c:290 [inline]
file_ioctl+0x584/0x75c fs/ioctl.c:-1
do_vfs_ioctl+0xa10/0x1834 fs/ioctl.c:577
__do_sys_ioctl fs/ioctl.c:596 [inline]
__se_sys_ioctl fs/ioctl.c:584 [inline]
__arm64_sys_ioctl+0xe4/0x1c4 fs/ioctl.c:584
__invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49
el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:132
do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151
el0_svc+0x58/0x180 arch/arm64/kernel/entry-common.c:879
el0t_64_sync_handler+0x84/0x12c arch/arm64/kernel/entry-common.c:898
el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:596
other info that might help us debug this:
Chain exists of:
&ni->ni_lock#3/5 --> &mm->mmap_lock --> mapping.invalidate_lock#3
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(mapping.invalidate_lock#3);
lock(&mm->mmap_lock);
lock(mapping.invalidate_lock#3);
lock(&ni->ni_lock#3/5);
*** DEADLOCK ***
3 locks held by syz.3.855/8482:
#0: ffff0000dd148428 (sb_writers#11){.+.+}-{0:0}, at: file_start_write include/linux/fs.h:3107 [inline]
#0: ffff0000dd148428 (sb_writers#11){.+.+}-{0:0}, at: vfs_fallocate+0x4d0/0x668 fs/open.c:341
#1: ffff0000f5573700 (&sb->s_type->i_mutex_key#20){+.+.}-{4:4}, at: inode_lock include/linux/fs.h:869 [inline]
#1: ffff0000f5573700 (&sb->s_type->i_mutex_key#20){+.+.}-{4:4}, at: ntfs_fallocate+0x270/0xdd4 fs/ntfs3/file.c:532
#2: ffff0000f55738a0 (mapping.invalidate_lock#3){++++}-{4:4}, at: filemap_invalidate_lock include/linux/fs.h:924 [inline]
#2: ffff0000f55738a0 (mapping.invalidate_lock#3){++++}-{4:4}, at: ntfs_fallocate+0x324/0xdd4 fs/ntfs3/file.c:546
stack backtrace:
CPU: 1 UID: 0 PID: 8482 Comm: syz.3.855 Not tainted 6.17.0-rc1-syzkaller-g8f5ae30d69d7 #0 PREEMPT
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 06/30/2025
Call trace:
show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:499 (C)
__dump_stack+0x30/0x40 lib/dump_stack.c:94
dump_stack_lvl+0xd8/0x12c lib/dump_stack.c:120
dump_stack+0x1c/0x28 lib/dump_stack.c:129
print_circular_bug+0x324/0x32c kernel/locking/lockdep.c:2043
check_noncircular+0x154/0x174 kernel/locking/lockdep.c:2175
check_prev_add kernel/locking/lockdep.c:3165 [inline]
check_prevs_add kernel/locking/lockdep.c:3284 [inline]
validate_chain kernel/locking/lockdep.c:3908 [inline]
__lock_acquire+0x1774/0x30a4 kernel/locking/lockdep.c:5237
lock_acquire+0x14c/0x2e0 kernel/locking/lockdep.c:5868
__mutex_lock_common+0x1d0/0x24ac kernel/locking/mutex.c:598
__mutex_lock kernel/locking/mutex.c:760 [inline]
mutex_lock_nested+0x2c/0x38 kernel/locking/mutex.c:812
ni_lock fs/ntfs3/ntfs_fs.h:1113 [inline]
ntfs_fallocate+0x450/0xdd4 fs/ntfs3/file.c:561
vfs_fallocate+0x52c/0x668 fs/open.c:342
ioctl_preallocate fs/ioctl.c:290 [inline]
file_ioctl+0x584/0x75c fs/ioctl.c:-1
do_vfs_ioctl+0xa10/0x1834 fs/ioctl.c:577
__do_sys_ioctl fs/ioctl.c:596 [inline]
__se_sys_ioctl fs/ioctl.c:584 [inline]
__arm64_sys_ioctl+0xe4/0x1c4 fs/ioctl.c:584
__invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49
el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:132
do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151
el0_svc+0x58/0x180 arch/arm64/kernel/entry-common.c:879
el0t_64_sync_handler+0x84/0x12c arch/arm64/kernel/entry-common.c:898
el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:596
It is reproducible with the followint program.
Keep in mind that it may lack the precise threading, sandboxing, and some arguments of a working reproducer.
But it should give an idea of the involved syscalls.
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <setjmp.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/loop.h>
#ifndef __NR_memfd_create
#define __NR_memfd_create 319
#endif
static unsigned long long procid;
//% This code is derived from puff.{c,h}, found in the zlib development. The
//% original files come with the following copyright notice:
//% Copyright (C) 2002-2013 Mark Adler, all rights reserved
//% version 2.3, 21 Jan 2013
//% This software is provided 'as-is', without any express or implied
//% warranty. In no event will the author be held liable for any damages
//% arising from the use of this software.
//% Permission is granted to anyone to use this software for any purpose,
//% including commercial applications, and to alter it and redistribute it
//% freely, subject to the following restrictions:
//% 1. The origin of this software must not be misrepresented; you must not
//% claim that you wrote the original software. If you use this software
//% in a product, an acknowledgment in the product documentation would be
//% appreciated but is not required.
//% 2. Altered source versions must be plainly marked as such, and must not be
//% misrepresented as being the original software.
//% 3. This notice may not be removed or altered from any source distribution.
//% Mark Adler madler@alumni.caltech.edu
//% BEGIN CODE DERIVED FROM puff.{c,h}
#define MAXBITS 15
#define MAXLCODES 286
#define MAXDCODES 30
#define MAXCODES (MAXLCODES + MAXDCODES)
#define FIXLCODES 288
struct puff_state {
unsigned char* out;
unsigned long outlen;
unsigned long outcnt;
const unsigned char* in;
unsigned long inlen;
unsigned long incnt;
int bitbuf;
int bitcnt;
jmp_buf env;
};
static int puff_bits(struct puff_state* s, int need)
{
long val = s->bitbuf;
while (s->bitcnt < need) {
if (s->incnt == s->inlen)
longjmp(s->env, 1);
val |= (long)(s->in[s->incnt++]) << s->bitcnt;
s->bitcnt += 8;
}
s->bitbuf = (int)(val >> need);
s->bitcnt -= need;
return (int)(val & ((1L << need) - 1));
}
static int puff_stored(struct puff_state* s)
{
s->bitbuf = 0;
s->bitcnt = 0;
if (s->incnt + 4 > s->inlen)
return 2;
unsigned len = s->in[s->incnt++];
len |= s->in[s->incnt++] << 8;
if (s->in[s->incnt++] != (~len & 0xff) ||
s->in[s->incnt++] != ((~len >> 8) & 0xff))
return -2;
if (s->incnt + len > s->inlen)
return 2;
if (s->outcnt + len > s->outlen)
return 1;
for (; len--; s->outcnt++, s->incnt++) {
if (s->in[s->incnt])
s->out[s->outcnt] = s->in[s->incnt];
}
return 0;
}
struct puff_huffman {
short* count;
short* symbol;
};
static int puff_decode(struct puff_state* s, const struct puff_huffman* h)
{
int first = 0;
int index = 0;
int bitbuf = s->bitbuf;
int left = s->bitcnt;
int code = first = index = 0;
int len = 1;
short* next = h->count + 1;
while (1) {
while (left--) {
code |= bitbuf & 1;
bitbuf >>= 1;
int count = *next++;
if (code - count < first) {
s->bitbuf = bitbuf;
s->bitcnt = (s->bitcnt - len) & 7;
return h->symbol[index + (code - first)];
}
index += count;
first += count;
first <<= 1;
code <<= 1;
len++;
}
left = (MAXBITS + 1) - len;
if (left == 0)
break;
if (s->incnt == s->inlen)
longjmp(s->env, 1);
bitbuf = s->in[s->incnt++];
if (left > 8)
left = 8;
}
return -10;
}
static int puff_construct(struct puff_huffman* h, const short* length, int n)
{
int len;
for (len = 0; len <= MAXBITS; len++)
h->count[len] = 0;
int symbol;
for (symbol = 0; symbol < n; symbol++)
(h->count[length[symbol]])++;
if (h->count[0] == n)
return 0;
int left = 1;
for (len = 1; len <= MAXBITS; len++) {
left <<= 1;
left -= h->count[len];
if (left < 0)
return left;
}
short offs[MAXBITS + 1];
offs[1] = 0;
for (len = 1; len < MAXBITS; len++)
offs[len + 1] = offs[len] + h->count[len];
for (symbol = 0; symbol < n; symbol++)
if (length[symbol] != 0)
h->symbol[offs[length[symbol]]++] = symbol;
return left;
}
static int puff_codes(struct puff_state* s,
const struct puff_huffman* lencode,
const struct puff_huffman* distcode)
{
static const short lens[29] = {
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
static const short lext[29] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
static const short dists[30] = {
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577};
static const short dext[30] = {
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13};
int symbol;
do {
symbol = puff_decode(s, lencode);
if (symbol < 0)
return symbol;
if (symbol < 256) {
if (s->outcnt == s->outlen)
return 1;
if (symbol)
s->out[s->outcnt] = symbol;
s->outcnt++;
} else if (symbol > 256) {
symbol -= 257;
if (symbol >= 29)
return -10;
int len = lens[symbol] + puff_bits(s, lext[symbol]);
symbol = puff_decode(s, distcode);
if (symbol < 0)
return symbol;
unsigned dist = dists[symbol] + puff_bits(s, dext[symbol]);
if (dist > s->outcnt)
return -11;
if (s->outcnt + len > s->outlen)
return 1;
while (len--) {
if (dist <= s->outcnt && s->out[s->outcnt - dist])
s->out[s->outcnt] = s->out[s->outcnt - dist];
s->outcnt++;
}
}
} while (symbol != 256);
return 0;
}
static int puff_fixed(struct puff_state* s)
{
static int virgin = 1;
static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
static struct puff_huffman lencode, distcode;
if (virgin) {
lencode.count = lencnt;
lencode.symbol = lensym;
distcode.count = distcnt;
distcode.symbol = distsym;
short lengths[FIXLCODES];
int symbol;
for (symbol = 0; symbol < 144; symbol++)
lengths[symbol] = 8;
for (; symbol < 256; symbol++)
lengths[symbol] = 9;
for (; symbol < 280; symbol++)
lengths[symbol] = 7;
for (; symbol < FIXLCODES; symbol++)
lengths[symbol] = 8;
puff_construct(&lencode, lengths, FIXLCODES);
for (symbol = 0; symbol < MAXDCODES; symbol++)
lengths[symbol] = 5;
puff_construct(&distcode, lengths, MAXDCODES);
virgin = 0;
}
return puff_codes(s, &lencode, &distcode);
}
static int puff_dynamic(struct puff_state* s)
{
static const short order[19] =
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
int nlen = puff_bits(s, 5) + 257;
int ndist = puff_bits(s, 5) + 1;
int ncode = puff_bits(s, 4) + 4;
if (nlen > MAXLCODES || ndist > MAXDCODES)
return -3;
short lengths[MAXCODES];
int index;
for (index = 0; index < ncode; index++)
lengths[order[index]] = puff_bits(s, 3);
for (; index < 19; index++)
lengths[order[index]] = 0;
short lencnt[MAXBITS + 1], lensym[MAXLCODES];
struct puff_huffman lencode = {lencnt, lensym};
int err = puff_construct(&lencode, lengths, 19);
if (err != 0)
return -4;
index = 0;
while (index < nlen + ndist) {
int symbol;
int len;
symbol = puff_decode(s, &lencode);
if (symbol < 0)
return symbol;
if (symbol < 16)
lengths[index++] = symbol;
else {
len = 0;
if (symbol == 16) {
if (index == 0)
return -5;
len = lengths[index - 1];
symbol = 3 + puff_bits(s, 2);
} else if (symbol == 17)
symbol = 3 + puff_bits(s, 3);
else
symbol = 11 + puff_bits(s, 7);
if (index + symbol > nlen + ndist)
return -6;
while (symbol--)
lengths[index++] = len;
}
}
if (lengths[256] == 0)
return -9;
err = puff_construct(&lencode, lengths, nlen);
if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
return -7;
short distcnt[MAXBITS + 1], distsym[MAXDCODES];
struct puff_huffman distcode = {distcnt, distsym};
err = puff_construct(&distcode, lengths + nlen, ndist);
if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
return -8;
return puff_codes(s, &lencode, &distcode);
}
static int puff(
unsigned char* dest,
unsigned long* destlen,
const unsigned char* source,
unsigned long sourcelen)
{
struct puff_state s = {
.out = dest,
.outlen = *destlen,
.outcnt = 0,
.in = source,
.inlen = sourcelen,
.incnt = 0,
.bitbuf = 0,
.bitcnt = 0,
};
int err;
if (setjmp(s.env) != 0)
err = 2;
else {
int last;
do {
last = puff_bits(&s, 1);
int type = puff_bits(&s, 2);
err = type == 0 ? puff_stored(&s) : (type == 1 ? puff_fixed(&s) : (type == 2 ? puff_dynamic(&s) : -1));
if (err != 0)
break;
} while (!last);
}
*destlen = s.outcnt;
return err;
}
//% END CODE DERIVED FROM puff.{c,h}
#define ZLIB_HEADER_WIDTH 2
static int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd)
{
if (sourcelen < ZLIB_HEADER_WIDTH)
return 0;
source += ZLIB_HEADER_WIDTH;
sourcelen -= ZLIB_HEADER_WIDTH;
const unsigned long max_destlen = 132 << 20;
void* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
if (ret == MAP_FAILED)
return -1;
unsigned char* dest = (unsigned char*)ret;
unsigned long destlen = max_destlen;
int err = puff(dest, &destlen, source, sourcelen);
if (err) {
munmap(dest, max_destlen);
errno = -err;
return -1;
}
if (write(dest_fd, dest, destlen) != (ssize_t)destlen) {
munmap(dest, max_destlen);
return -1;
}
return munmap(dest, max_destlen);
}
static int setup_loop_device(unsigned char* data, unsigned long size, const char* loopname, int* loopfd_p)
{
int err = 0, loopfd = -1;
int memfd = syscall(__NR_memfd_create, "syzkaller", 0);
if (memfd == -1) {
err = errno;
goto error;
}
if (puff_zlib_to_file(data, size, memfd)) {
err = errno;
goto error_close_memfd;
}
loopfd = open(loopname, O_RDWR);
if (loopfd == -1) {
err = errno;
goto error_close_memfd;
}
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
if (errno != EBUSY) {
err = errno;
goto error_close_loop;
}
ioctl(loopfd, LOOP_CLR_FD, 0);
usleep(1000);
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
err = errno;
goto error_close_loop;
}
}
close(memfd);
*loopfd_p = loopfd;
return 0;
error_close_loop:
close(loopfd);
error_close_memfd:
close(memfd);
error:
errno = err;
return -1;
}
static void reset_loop_device(const char* loopname)
{
int loopfd = open(loopname, O_RDWR);
if (loopfd == -1) {
return;
}
if (ioctl(loopfd, LOOP_CLR_FD, 0)) {
}
close(loopfd);
}
static long syz_mount_image(
volatile long fsarg,
volatile long dir,
volatile long flags,
volatile long optsarg,
volatile long change_dir,
volatile unsigned long size,
volatile long image)
{
unsigned char* data = (unsigned char*)image;
int res = -1, err = 0, need_loop_device = !!size;
char* mount_opts = (char*)optsarg;
char* target = (char*)dir;
char* fs = (char*)fsarg;
char* source = NULL;
char loopname[64];
if (need_loop_device) {
int loopfd;
memset(loopname, 0, sizeof(loopname));
snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
if (setup_loop_device(data, size, loopname, &loopfd) == -1)
return -1;
close(loopfd);
source = loopname;
}
mkdir(target, 0777);
char opts[256];
memset(opts, 0, sizeof(opts));
if (strlen(mount_opts) > (sizeof(opts) - 32)) {
}
strncpy(opts, mount_opts, sizeof(opts) - 32);
if (strcmp(fs, "iso9660") == 0) {
flags |= MS_RDONLY;
} else if (strncmp(fs, "ext", 3) == 0) {
bool has_remount_ro = false;
char* remount_ro_start = strstr(opts, "errors=remount-ro");
if (remount_ro_start != NULL) {
char after = *(remount_ro_start + strlen("errors=remount-ro"));
char before = remount_ro_start == opts ? '\0' : *(remount_ro_start - 1);
has_remount_ro = ((before == '\0' || before == ',') && (after == '\0' || after == ','));
}
if (strstr(opts, "errors=panic") || !has_remount_ro)
strcat(opts, ",errors=continue");
} else if (strcmp(fs, "xfs") == 0) {
strcat(opts, ",nouuid");
} else if (strncmp(fs, "gfs2", 4) == 0 && (strstr(opts, "errors=panic") || strstr(opts, "debug"))) {
strcat(opts, ",errors=withdraw");
}
res = mount(source, target, fs, flags, opts);
if (res == -1) {
err = errno;
goto error_clear_loop;
}
res = open(target, O_RDONLY | O_DIRECTORY);
if (res == -1) {
err = errno;
goto error_clear_loop;
}
if (change_dir) {
res = chdir(target);
if (res == -1) {
err = errno;
}
}
error_clear_loop:
if (need_loop_device)
reset_loop_device(loopname);
errno = err;
return res;
}
uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
const char* reason;
(void)reason;
intptr_t res = 0;
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {}
// syz_mount_image$ntfs3 arguments: [
// fs: ptr[in, buffer] {
// buffer: {6e 74 66 73 33 00} (length 0x6)
// }
// dir: ptr[in, buffer] {
// buffer: {2e 2f 66 69 6c 65 30 00} (length 0x8)
// }
// flags: mount_flags = 0x8 (8 bytes)
// opts: ptr[inout, array[ANYUNION]] {
// array[ANYUNION] {
// union ANYUNION {
// ANYBLOB: buffer: {73 70 61 72 73 65 2c 73 70 61 72 73 65 2c 6e 6f 68 69 64 64 65 6e 2c 61 63 6c 2c 73 70 61 72 73 65 2c 64 69 73 63 61 72 64 2c 75 69 64 3d} (length 0x2e)
// }
// union ANYUNION {
// ANYRESHEX: ANYRES64 (resource)
// }
// union ANYUNION {
// ANYBLOB: buffer: {2c 69 6f 63 68 61 72 73 65 74 3d 63 70 34 33 37 2c 69 6f 63 68 61 72 73 65 74 3d 63 70 38 36 32 2c 69 6f 63 68 61 72 73 65 74 3d 63 70 38 36 35 2c 6e 6f 68 69 64 64 65 6e 2c 69 6f 63 68 61 72 73 65 74 3d 63 70 38 36 35 2c 68 69 64 65 5f 64 6f 74 5f 66 69 6c 65 73 2c 00 c5 e0 d3 02 c4 c4 d0 49 92 84 f5 fc 25 59 c4 52 59 09 7b 92 82 2e 84 c6 75 9a 16 19 01 ff b0 ee 41 b1 94 36 b5 1a bf 9d 24 06 9b 42 f7 d1 6d c2 54 7f ee cf c8 bd 5a 7f 55 19 20 3d 28 5c b8 34 2b 78 03 1f da 17 1d e1 f8 c9 a0 21 ec eb 4b 1c 26 e0 38 a5 1a a1 ac bf b3 f9 30 bb fa eb e6 d3 43 20 c9 e6 9a 1f 5f d0 92 58 6b e9 e1 64 8d 2c 3d 29 a3 99 d6 f1 5a 62 75 bc 76 ad 79 05 eb 8d fd 54 02 32 cf ec 68 11 39 53 55 1f b2 69 b7 b0 f7 f3 53 5c 12 41 20 e2 a2 84 c6 52 71 c7 79} (length 0xf9)
// }
// }
// }
// chdir: int8 = 0x4 (1 bytes)
// size: len = 0x1f771 (8 bytes)
// img: ptr[in, buffer] {
// buffer: (compressed buffer with length 0x1f771)
// }
// ]
// returns fd_dir
memcpy((void*)0x200000000040, "ntfs3\000", 6);
memcpy((void*)0x200000000080, "./file0\000", 8);
memcpy((void*)0x200000000400, "sparse,sparse,nohidden,acl,sparse,discard,uid=", 46);
sprintf((char*)0x20000000042e, "0x%016llx", (long long)0);
memcpy((void*)0x200000000440, "... [truncated large byte array] ...", 249);
memcpy((void*)0x200000020940, "... [truncated large byte array] ...", 128881);
syz_mount_image(/*fs=*/0x200000000040, /*dir=*/0x200000000080, /*flags=MS_NOEXEC*/8, /*opts=*/0x200000000400, /*chdir=*/4, /*size=*/0x1f771, /*img=*/0x200000020940);
// openat$cgroup_ro arguments: [
// fd: fd_cgroup (resource)
// file: ptr[in, buffer] {
// buffer: {63 70 75 61 63 63 74 2e 75 73 61 67 65 5f 73 79 73 00} (length 0x12)
// }
// flags: const = 0x275a (4 bytes)
// mode: const = 0x0 (2 bytes)
// ]
// returns fd
memcpy((void*)0x200000000040, "cpuacct.usage_sys\000", 18);
res = syscall(__NR_openat, /*fd=*/0xffffff9c, /*file=*/0x200000000040ul, /*flags=*/0x275a, /*mode=*/0);
if (res != -1)
r[0] = res;
// ioctl$FS_IOC_FIEMAP arguments: [
// fd: fd (resource)
// cmd: const = 0xc020660b (4 bytes)
// v: ptr[in, fiemap] {
// fiemap {
// start: int64 = 0xfff (8 bytes)
// len: int64 = 0x2 (8 bytes)
// flags: fiemap_flags = 0x1 (4 bytes)
// mapped: int32 = 0xa (4 bytes)
// count: len = 0x4 (4 bytes)
// reserved: const = 0x0 (4 bytes)
// extent: array[fiemap_extent] {
// fiemap_extent {
// fe_logical: int64 = 0x6bd (8 bytes)
// fe_physical: int64 = 0x6 (8 bytes)
// fe_length: int64 = 0xf5 (8 bytes)
// fe_reserved64: buffer: {00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// fe_flags: fiemap_extent_flags = 0x80 (4 bytes)
// fe_reserved: buffer: {00 00 00 00 00 00 00 00 00 00 00 00} (length 0xc)
// }
// fiemap_extent {
// fe_logical: int64 = 0x80000000 (8 bytes)
// fe_physical: int64 = 0x8 (8 bytes)
// fe_length: int64 = 0x8 (8 bytes)
// fe_reserved64: buffer: {00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// fe_flags: fiemap_extent_flags = 0x200 (4 bytes)
// fe_reserved: buffer: {00 00 00 00 00 00 00 00 00 00 00 00} (length 0xc)
// }
// fiemap_extent {
// fe_logical: int64 = 0x7 (8 bytes)
// fe_physical: int64 = 0x400000000000 (8 bytes)
// fe_length: int64 = 0x9 (8 bytes)
// fe_reserved64: buffer: {00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// fe_flags: fiemap_extent_flags = 0x1800 (4 bytes)
// fe_reserved: buffer: {00 00 00 00 00 00 00 00 00 00 00 00} (length 0xc)
// }
// fiemap_extent {
// fe_logical: int64 = 0x8 (8 bytes)
// fe_physical: int64 = 0x401 (8 bytes)
// fe_length: int64 = 0x8 (8 bytes)
// fe_reserved64: buffer: {00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// fe_flags: fiemap_extent_flags = 0x0 (4 bytes)
// fe_reserved: buffer: {00 00 00 00 00 00 00 00 00 00 00 00} (length 0xc)
// }
// }
// }
// }
// ]
*(uint64_t*)0x200000000840 = 0xfff;
*(uint64_t*)0x200000000848 = 2;
*(uint32_t*)0x200000000850 = 1;
*(uint32_t*)0x200000000854 = 0xa;
*(uint32_t*)0x200000000858 = 4;
*(uint32_t*)0x20000000085c = 0;
*(uint64_t*)0x200000000860 = 0x6bd;
*(uint64_t*)0x200000000868 = 6;
*(uint64_t*)0x200000000870 = 0xf5;
memset((void*)0x200000000878, 0, 16);
*(uint32_t*)0x200000000888 = 0x80;
memset((void*)0x20000000088c, 0, 12);
*(uint64_t*)0x200000000898 = 0x80000000;
*(uint64_t*)0x2000000008a0 = 8;
*(uint64_t*)0x2000000008a8 = 8;
memset((void*)0x2000000008b0, 0, 16);
*(uint32_t*)0x2000000008c0 = 0x200;
memset((void*)0x2000000008c4, 0, 12);
*(uint64_t*)0x2000000008d0 = 7;
*(uint64_t*)0x2000000008d8 = 0x400000000000;
*(uint64_t*)0x2000000008e0 = 9;
memset((void*)0x2000000008e8, 0, 16);
*(uint32_t*)0x2000000008f8 = 0x1800;
memset((void*)0x2000000008fc, 0, 12);
*(uint64_t*)0x200000000908 = 8;
*(uint64_t*)0x200000000910 = 0x401;
*(uint64_t*)0x200000000918 = 8;
memset((void*)0x200000000920, 0, 16);
*(uint32_t*)0x200000000930 = 0;
memset((void*)0x200000000934, 0, 12);
syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0xc020660b, /*v=*/0x200000000840ul);
// write$UHID_INPUT arguments: [
// fd: fd_uhid (resource)
// data: ptr[in, uhid_req[UHID_INPUT, uhid_input_req]] {
// uhid_req[UHID_INPUT, uhid_input_req] {
// type: const = 0x8 (4 bytes)
// data: uhid_input_req {
// data: buffer: {7f 96 54 d6 36 ab 18 b7 93 8a 28 04 50 5c 72 e9 99 4c a2 24 04 fc 20 33 34 cc 21 ed 3d 6a 77 6f d1 2d 13 f9 60 2b 29 80 f9 83 c3 1a 5d 1e 43 1d b7 78 09 9c e3 af 3f b2 0e 1e e1 f4 fd b7 7c bb 36 15 49 82 a9 3c 19 82 5d 6f d2 73 ab 1e b5 bc d4 7a da d5 0d e8 a6 79 14 86 e4 82 e2 9e cc 94 28 49 21 f3 3b 94 1c fc 10 00 c9 78 1d 9a 82 8c 5e c7 a2 c7 7b 4e 62 4a 5a a0 e9 e3 97 82 ba d7 33 ed a8 1b a4 7e 1c 61 16 e4 17 0e 65 87 dd 62 10 a5 7a be 91 f1 f8 0c 4e 31 13 9d 8b 73 fe 35 ac 1f 99 ea 82 dd 6a a9 c9 aa 67 de 88 ae 3e 14 10 20 e1 a8 76 bb c4 49 d2 d8 43 aa 7e 6d 90 b9 48 b7 e2 87 70 e6 ac 71 01 0c 63 f1 7e 90 fd 20 80 6a 9f 8d 9f 41 8e e3 af 74 aa c6 4b 04 a2 7c 4f 5e 36 26 ca 2d a5 46 c7 9d 24 ac ad d1 1e 8d 27 2a 22 fc 54 07 8f d5 e6 44 75 99 36 68 98 0a 9f 95 af f9 64 de e6 74 35 6a f4 92 b8 37 7a 75 9d 8c cf 1a cc b9 a1 8e f7 ad 16 f4 38 dd e6 9c d0 20 d7 15 52 b0 81 06 88 c8 82 a2 6a 22 b2 3f 4b 35 47 1b 08 b3 79 19 3d b1 cd 79 34 a4 04 9f f1 b0 0d 97 95 cd a6 e7 39 51 64 1d 5e 23 65 c2 4f ac d5 af d0 9e d1 d0 96 d7 58 b4 fe f6 6f e1 aa 22 39 5d 67 b7 e1 db 62 3d 4a 60 a7 dc 93 89 3d 6c 4a 91 df 79 53 5a 85 58 68 c5 dc 00 33 d5 c4 28 cd 25 b8 5c 5d eb 6e 81 06 85 53 bc 84 ce ad 4d 1e ba 8a a5 7e 2b 35 4a 68 99 e4 4a cb d3 83 44 91 21 9b 3e 23 1c d5 5d 82 f1 61 77 4a 68 9e fe 19 7c c1 93 ac 01 24 c6 77 38 a0 a1 d5 f1 6a 67 68 c2 c2 ba 73 86 c8 c9 5c a0 8c 55 11 7f 34 4f 5a 2b ca 0d 09 e7 9e a3 fc 49 49 1f 2c 7a dc 51 3c 27 79 c1 bf 62 b1 a8 64 3d 23 e9 e8 b2 ae 41 d4 a5 9f 1b 82 b8 2e 09 2b 36 eb 85 1b 84 56 da 87 1b 40 57 ae c3 25 a9 d4 cc ca fd e6 1f 2a bc 85 e3 ca be ab b8 56 f6 ff bf e2 3d 69 21 9e c8 fa e6 be b5 4a be 78 70 db ae 82 3d 49 80 6a 96 7a 1c 7f 25 29 99 80 4f 10 67 45 f2 04 90 bb 33 47 b5 93 21 dc 69 76 55 67 ab cb d8 9d e0 4d 89 62 21 70 00 5d f5 87 1e d0 fb 72 34 5a 11 da 07 40 60 d7 d4 ee 2e 43 7f 71 a4 57 23 fb 6b 02 de 56 06 7e 54 f5 4c 52 d1 0f 78 74 a1 3c bf b3 bd 65 ce 54 f9 d6 71 9e a2 10 e0 cf 79 e4 e2 15 77 36 ec 07 ac 59 15 68 2a b8 1b ce d6 65 c1 e7 2f ab 8d 8c fe 50 9d e0 f2 1f e3 74 b9 57 b3 79 fd 59 18 06 1e 21 c2 e9 69 85 cc 13 54 b2 de 85 9b 0f 1a 46 3a b0 46 83 b1 25 3e da 67 1c 23 53 b5 c2 08 ac a6 52 f5 41 9f fc 49 49 a7 fa 90 9b 95 65 3f 42 d9 73 90 c4 00 b4 a1 c3 08 b1 1e 73 e9 a0 6d 3b 16 4d 33 61 e7 55 84 d7 0e 6b c6 1d 57 0a 7e 0c 7d a3 30 f6 43 19 4c 18 93 fc d6 48 9f ac 60 5e ea d6 1b 53 df f1 8c af 52 6e cc cc 9b bd 91 46 bc 3c 3b b6 76 77 69 5e 6f dd aa b0 81 78 6e 90 84 01 4e 60 f5 c0 3a e5 a9 08 77 26 b0 5e 17 40 2c d2 fb b8 0d 77 3b 8a 41 47 0b 1f 90 1a 8c 2b 2d 57 45 01 81 f4 fc 5b c5 3c 7c b3 dc 03 2b 84 56 74 92 60 7c b0 88 32 ec a9 f7 9d a9 21 0d 19 78 63 e5 db 5a 74 a9 82 3d c0 cc 8b d9 f3 a9 b6 ff 5a 7d 15 d4 74 7a 9b 26 e0 88 f4 fa d9 6d 81 cd 12 14 22 6b 1c 45 85 d4 18 d5 93 22 0f cb b9 ad 94 92 66 cc 48 16 3e 34 98 b4 6e bc df 7b 2b 5e cf e6 75 39 a6 1e d9 e3 9b 02 d5 b3 5a c0 d0 e7 fa 83 00 34 ca 2d a8 a7 dd f0 4b cf 2c ee 93 99 94 36 9f eb 77 02 3e 0e 3d e0 4b 21 db 7a 64 0a 92 c1 77 48 24 50 05 cd 75 a7 de ba 4f f0 e4 c1 04 a9 db 2d 9a 98 ec 8e db 35 62 05 0a 3b ac 5f 32 22 90 e3 d8 b6 fb 21 77 0a c4 36 d4 cb 12 b9 7f c8 f7 6d 7b b9 ee ed 85 66 3e b0 62 6f 1a d1 71 9e e4 b0 7f 7d e2 c1 d1 a3 1c 27 c6 87 9f 4f a3 db df b2 bf c0 89 8b ea ba fb ec a9 f1 30 50 e6 b2 f6 c4 32 e4 23 cd 5c b6 b8 fa 56 fe 32 c3 e5 01 04 e4 44 62 c0 a5 c6 9d e6 a7 ac 5a e3 d9 f0 7c ee d6 4d bf fa 42 e4 66 38 38 bf cd e9 2f 0f cb 89 5f 3b 93 c5 9b 0e 48 c0 98 90 df c3 64 36 db 56 b7 08 f6 e7 cb bd 2a 63 05 f5 73 ce e0 99 db cd 26 3c b9 6d 9f b6 9c bc 3c b0 6d 8f 5e 37 89 69 8a 17 e7 1d 22 b4 66 5f f5 44 7f cc 17 a3 1b b1 36 c8 bb 4b 98 45 73 bc af 1c b6 50 19 8c 12 66 e6 dd fd 42 d4 4f 9d e0 2c b9 d9 15 c5 33 4c 55 0f ac 3f ce e5 67 90 ae b0 9d 81 e7 69 0a 32 d8 b0 cc 47 7b 23 f1 52 57 82 0d e2 27 be 1f fa ec 2f 63 f3 26 6b 8f 5d d7 89 47 dc ee 35 5f e5 9b fb 10 0e 52 44 42 55 32 bb 1d 11 5a cd 21 1b 8c 16 b0 ec 0a ae 00 fc a5 d4 51 1a 05 c3 ff 02 7a 1c ac 56 21 0a 10 d8 1c 01 b9 0e 15 6c c7 b3 3d e0 fa c8 25 dc 51 6d 39 81 66 09 60 13 e0 68 db 93 54 83 c9 3b a9 5d a3 9b 5a e4 08 7d 84 47 9a 4c 48 09 f2 8f 93 79 0d c2 79 63 7b d6 f3 dc 44 1d 31 5c f6 bd 7b 0e 3d 92 07 0a 45 ba f4 44 5c e0 63 fd 12 69 0e b0 02 f5 ca 06 8a 25 6b c5 41 00 c9 9a 02 a3 46 be ca 39 07 21 63 c4 b2 97 d1 17 f1 ed 9f ef 42 e3 db c1 1d 36 a0 a0 db 52 e8 44 61 c6 fb b4 aa d6 2c d6 c8 dc 9a e6 a3 39 0a 5e 87 73 ac 59 9e 67 43 62 20 c8 d5 41 a9 03 97 62 bf fa a7 f4 90 e3 1d dd bc 36 2f b4 ff 68 6c da 90 5f 3b 02 a1 db 76 d4 d5 70 d9 70 43 49 21 ca 8a 47 65 af 6d 5c 8b 88 1e 1f 4f fa 7e 2d 9e f5 f5 51 1b 94 f8 84 74 67 4e c7 90 bb 51 86 c7 34 46 a2 27 bf 1f fd 19 b6 05 73 3a bd 1b d4 1e 42 1a ea f2 ed 46 17 08 8c 7c ee f8 54 51 22 50 56 43 59 93 e8 9e 4b cc d2 c2 e4 b3 9a f9 9f ee f1 1f ea 64 5e eb 5c f9 f7 7b 1e 19 a7 2d 3e fb 61 31 00 96 9b 84 30 27 89 71 4b ca 65 bc bc 96 76 2b 40 12 a5 70 0c 62 ae d7 06 43 3b 9f 14 2b 73 02 44 2b 6a 99 58 b0 e2 8e 8b 1c fa 9e eb 4a c0 d7 1f 49 7b 23 ba bf 9f 02 21 dc b6 58 d9 f4 db 5d 45 be e3 0d 2a d7 c9 7d 6a 56 2e 01 4a 77 01 c1 53 25 ec 5d 42 ab 73 2b 37 71 4a 77 a9 5c 03 fb 15 bb fb a6 fa de 32 bf 50 f9 85 a1 df 36 2c a7 21 6c c1 52 90 7d d9 31 ac b5 8a 63 92 0f 58 1e 82 b5 90 c0 d6 a0 03 30 09 f8 e5 0c 32 63 d3 f5 85 96 b6 3d 50 7c ad bc 80 9a 66 90 56 1f 74 d0 77 2b f9 2d 04 e0 6c 47 a3 50 72 4b 10 6f 5e 83 f7 e7 1c 4b 2a 98 3b f5 ad 7d 86 84 e7 b8 b5 dc 12 73 d0 fa 58 79 b8 e6 1b de 33 d6 02 bc 8f f0 91 3b 6d 32 dc ac 36 6d 56 8d c7 cf 82 bb fc 40 5c be 41 8a 26 44 c2 65 92 b3 2c a1 a6 32 fc 95 12 3e fb 78 4c fb 69 53 a9 4e be cc d2 4f ba 38 9a 0e 56 b0 43 df 07 d9 a2 dd 38 a1 19 6e 5e 55 57 6b 25 f8 5c b9 6f 65 60 80 2a 4a 58 b7 a6 85 7e 84 54 fa a2 c8 80 bf 32 d4 64 56 2b 2b dc 5f 0d f2 2b 66 3f 2c 01 fc 94 4f 1c fd 19 08 f6 17 f8 29 5a 54 40 bb 79 ae 17 8e a4 6a 95 ba ee a4 83 22 10 51 46 ac 3e d2 de 7d 37 96 dd dd cc 84 8a 8e cf 4a 00 dd 05 57 33 b4 f5 92 11 f5 a4 0d ee a4 4e 74 b3 bc 57 95 3b 26 ed 61 e6 fd 67 88 9e df e8 d0 90 23 85 e3 76 66 aa ce c0 72 73 56 30 ec c4 41 c3 cc 6b 09 bb 2f 63 aa 4e 33 2c 6d f7 28 dc 74 07 8a 83 ce 20 45 4d fd 61 6d 11 62 70 66 6d dc 09 c5 fe a2 e8 44 2b c4 34 55 d0 25 7f ac 92 f3 78 00 61 17 8f 94 20 bf 8e 46 3f 29 89 6c 12 38 3d bb 9a 81 bc 5c 87 37 6e 64 7c 8a 79 86 cb 51 4f b9 69 6d 9c 0a 8d 30 3c 5c 4b 5b 7c 5f 60 1c 01 fa 19 32 3e 02 f6 75 c3 71 bc 44 fb c1 ac 57 04 d4 1a 89 a2 a4 cc ec 6a c8 44 0c 53 2f 07 da 25 aa 2d ce 6a 5d 2e be 69 4e b4 01 7d 17 8b 22 12 13 bf e2 a0 1d 9c fe 68 9b d1 90 77 6b ca 6c 03 2f 44 6e b8 86 25 87 a7 82 6e 35 f3 f6 91 76 32 12 ee e6 af 2e 49 bb eb 0a 27 e0 7c 57 14 b7 4e 37 37 98 c7 be bc e2 65 f7 eb ef 3a 1e a6 40 78 cf 1e 8a 9d 43 3a f3 2c 53 09 0c 97 2f fe db ad af b5 0b 9a 6e 54 0a bd 84 f8 e9 38 58 3e a7 25 95 4b e3 b2 36 c5 d8 ac a7 d4 86 d2 19 02 a2 90 2f 25 a7 c0 2d be 83 c3 9b d0 b8 15 13 f9 ef 19 8c 49 d5 60 e9 30 ae 22 4f f4 7f 92 e4 85 1e 1f 7a b5 bb 40 6a bc f6 59 65 69 26 1e 6b 0c 67 bb 3b 85 4e 9c 6d e6 0b fb 60 fc f2 92 41 ff 23 71 51 31 0e cd 19 f8 b2 cf e7 64 c1 df 1a 2d e9 d8 40 ec a4 7a a1 69 ba 9a 41 59 01 20 4e c3 1c cd fd 76 e9 08 02 9a e3 4f b1 2d c2 86 75 8c 64 fd 6d 42 bc 82 b1 4e 07 e4 21 f4 b4 2b 18 0c d6 ef 40 ca c8 06 29 28 b4 a4 20 a4 57 7f 24 29 5f 54 de 90 48 ac 9d 34 30 7b f9 3e 46 3c ea 49 67 cf 48 80 16 6f 68 ed 1e b9 65 db 2e 4f b9 f5 f0 b1 c6 95 d6 21 e4 27 cc b9 a3 18 80 73 ee 6f de 72 9c 66 98 34 6e fa 1c 0b a6 43 c1 ef d2 08 58 96 55 11 da 75 00 60 d5 51 c4 4c 43 5a 5f 16 03 fa e7 35 7e 0b c7 8e 92 aa d3 d8 87 90 ec 2a a1 a4 2d 6f e7 e0 ff c5 7f 35 99 e4 06 db 63 be 7d d3 26 92 df 32 ce 33 de e0 a2 be cd b0 2d 6e 43 5e 09 de 3d 35 64 97 54 3d b2 3f 53 da 25 64 3f 9c 58 5e 27 52 97 80 0d 8b ee d4 7f 0e 62 2f 86 fc 25 d2 e8 70 36 fd ce eb fe 72 57 cb 6d e0 c0 24 12 d1 c0 75 8a cf cd 08 62 e9 9a d1 7a 11 8f 46 f6 35 a8 74 77 e8 b8 25 42 3d 94 ad a3 5b f0 b5 44 4a a7 d3 de 4b b7 ee c7 ae 51 29 fc c2 cb a6 51 cc 97 2f 55 00 fc 51 61 14 9d 29 f4 52 96 2a fb 10 2a 01 ae 76 82 5c b4 47 74 60 be 0b 85 d7 50 58 59 5c 27 e9 b7 fa e3 49 2e c3 92 5c 67 1b ee 5f 4c a5 34 d5 a2 94 f7 83 d6 cc 07 3c 99 21 39 b6 1d 21 fd 98 29 7b 04 c0 57 8d af d5 f7 eb ca f8 d4 d9 18 5a ea 3d 76 e8 13 42 1f 45 73 b3 8c 25 09 3c 01 5a 65 e4 4f b2 97 f0 f6 ac 2d 02 c4 23 7b 37 a3 bf ca 24 06 c5 c9 5a e5 81 28 16 ba ca d5 9b a7 c6 f7 2d 7c 64 4f f2 5b 59 2e d1 e8 9b 27 6e 05 86 6c 01 a4 ce d7 fc 6d d9 f1 90 c2 0d 42 0d 7c 8a 1f e9 08 83 3a 24 c5 e5 bd 7a 95 a2 a6 fb f1 47 fc 4b 29 a1 79 71 81 66 dd 0f ba e2 fc 6b 8c 8a ac 61 94 fa 6b af 0d 3e dc 36 b2 31 6c 56 c4 41 ba 53 e3 e7 aa af 0a 14 05 56 6f f5 84 f7 3a 63 7b 74 dd e9 bc b4 d4 1d a2 be 6c 9d f5 d5 33 fb ac 54 f5 fb 52 a8 a7 93 75 7c fe 19 aa 90 04 8c 6d 07 e3 47 41 36 ae 1b e2 45 5b 0d 0d 02 eb 4b 59 61 ba 88 32 09 35 5c 0d d2 af 4a ad 98 e7 b9 71 e3 58 a7 d9 b5 5f e1 7c d6 09 5f 25 73 55 d9 b9 9e 5e a5 28 48 f1 7b 35 a8 07 92 d9 ed 0f ef 6f e3 ee f9 a3 24 90 24 09 96 98 23 be 20 bb e0 e8 db a9 c7 47 cd 1a 14 d3 64 2d 87 7b 86 27 1f 3f 0c 32 2a 14 2c 4f f6 35 b3 7d 54 2c 32 65 b5 fe 85 89 a7 32 bb 1a 55 01 0b 93 0d d0 19 6c d4 3a c3 63 4c 01 b4 a4 4c 51 71 97 d0 3a 3d 89 c6 7f 5c 09 aa b4 09 e8 4c 0a f4 66 bf bd 0c 96 d2 40 10 1a 25 42 c6 6b 4b 4b 8e f6 5b 41 b0 07 99 95 c5 2c c9 72 0d 2c 1d 7c 12 8c 6f 17 a6 5c c7 98 c1 98 6c fb d8 88 84 60 c5 44 38 ed c4 f9 1f 35 80 39 1c 8b 57 d9 ae e2 09 a5 9a 11 6c 1c 44 77 54 37 e9 c3 0e 6d 87 e8 2c e8 4e 28 53 2b 19 44 1e 32 ab 9a ea 22 17 7b ac 9d aa d2 5a 6c 88 39 5e 93 48 d6 78 0d e6 30 cd db 26 6c 41 10 11 17 5b db 62 55 a3 65 35 18 08 18 44 7d 43 ff ba 37 58 d3 11 53 9f e9 f6 81 1f a4 70 bf 37 67 b4 c2 d4 cd f3 78 54 c7 ee 28 73 0b b1 d3 9d 5c 0d ff fc db f3 53 cc a3 e1 30 79 f3 ae 66 b8 39 c7 dd 36 91 40 22 a0 e7 5b ca 5b 62 2f 52 14 20 b7 32 49 ef 47 f0 3c 1f b0 3e cf 75 57 88 2a fc aa 7c f4 54 a6 8a d2 37 d4 ce 86 0b d6 b1 53 1c 1c af e2 cf b7 6b c4 18 82 71 ef 6b df b3 04 ee 0e 69 32 46 3a 19 09 f0 3d 6e 8a 27 b5 f1 37 d6 b3 42 84 1d 61 38 63 df df 37 d5 ec 3a 98 d6 67 81 0f b6 f8 2d 67 62 0b de fe d8 b3 ff 98 42 0a 6c 7e e5 77 c3 ba 68 b9 5a 20 40 36 08 a7 ba 65 26 ec 9e 86 62 c6 e1 5a b0 9b 1a 90 19 d4 95 8a f0 4c b2 e4 89 0e e6 b1 07 7f ca a5 cc 08 17 f3 88 46 1b 23 0f e6 31 e7 5f 18 ab 39 2a 5c a5 de 4a 02 4c a1 6d d0 5f cf df 92 11 4e 43 a5 c4 a1 69 d4 62 ff 0d ba 57 de ea f5 ea af d8 92 f8 cc bd 72 ac 56 47 11 62 e1 41 6b ca 39 85 9b 41 84 ba 0d 1b 3f 7e c0 5d b4 ef 4c f0 14 28 67 fa 9b e3 28 a0 be 8a a7 4c 71 6a ad 94 11 00 86 07 98 08 61 f4 f7 2e 9b fa 60 19 5e 2f 93 9d 3f 6a 44 a6 ce c0 7d d3 76 d1 bc ca a1 26 68 6f 31 3d 5f 79 18 ec d1 21 50 26 98 2c 82 ed 19 22 ef 70 e3 6e 8e d5 9b 2d 5c ea b3 b4 aa d7 e5 30 49 06 2d d5 ba 0e 87 f7 00 5c 3f 4d 2b 78 82 45 cd c2 f3 5e f2 57 2b ea 5e a9 2d fa d4 06 ad e6 d5 ad 18 be 8e eb 4c 65 2e 52 77 b2 44 64 5c 68 c0 c0 f5 a6 8d 42 e0 0d 59 b7 59 41 91 7b 2c df 31 fd f8 09 f2 07 8c a9 7f d5 be ba 65 b3 4e 06 21 13 8e a0 e9 4f eb 87 16 6b 2d ac 22 32 eb ca 57 5e 5c 0a 4d 56 5d 99 92 f7 33 bb fb e6 8a 63 d9 9e e9 33 98 60 40 65 d5 51 7c 33 ed 0e 06 7b db 64 3e 73 10 2f 16 13 7a fd 7d 4b f2 1e 80 65 ea 02 8c 39 2a 6d ce fb e6 42 dc 3f b0 3a 23 9d 9c 8b 17 02 3e ac c8 e1 9f ea 11 c3 4a 10 64 4a f1 b7 86 fc 0f 45 04 03 8c 2e e5 9c 1b 35 3f 3d 7b 93 13 df 02 5b 4b 58 74 ca 63 ec 16 4a 3f e3 5b f3 90 d2 66 f5 3d cd a6 a8 e1 90 e6 3a 56 ff df 4f 7c 5c 02 aa 22 d3 76 db 06 d4 d2 b9 6b e5 b3 31 f8 97 d1 ec fd 25 c1 3a 1c 19 4c 26 5d d9 5a 57 24 a6 43 5b c8 13 82 24 d9 db 28 b6 89 b9 ce a5 13 2c d1 96 01 db c4 a4 3e 70 c7 1e 27 e8 fd 06 89 d0 94 84 97 4e 8a 46 05 f8 55 37 35 ff fa f5 65 4a 08 7e 32 3c a1 4e 02 b6 81 b9 bb e5 92 bd 6b 71 9a e2 e8 6b df 91 8b 27 c7 9d 52 dd 33 4d 1a a7 eb c1 bf f7 6e 97 57 2f aa d0 92 01 0a 10 22 f7 d3 30 89 04 91 07 a8 9c 36 4a e7 dd 02 2d 11 9e 8f 6a b7 95 fd 71 d7 6a 90 e8 20 23 39 40 1f f9 e9 91 8e a8 c8 e1 2f 7b 0b a1 0d 9e bd e5 d1 bc 59 88 f2 d0 7b 34 57 9d 8c 28 26 28 20 4f 29 78 d8 b0 cf 95 dc 41 f3 77 5a 40 53 f8 33 26 7c 64 b4 23 36 d7 c8 50 f2 91 8e f0 dd 6d 62 e4 3f cc 17 32 54 eb 34 74 8e fd 47 54 60 9c e2 5a fd 64 8e e5 a8 fc 5c 64 34 66 03 f8 25 85 92 d6 7b 96 13 e8 f7 ac 0d ef 09 58 f1 34 36 58 1d 72 9e 0b 3e 06 27 38 eb 06 b2 11 6a be 83 75 29 69 0a 61 4f c5 d3 f5 3b 4d 46 02 e5 70 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00} (length 0x1000)
// size: len = 0x1000 (2 bytes)
// }
// }
// }
// len: len = 0x1006 (8 bytes)
// ]
*(uint32_t*)0x200000010140 = 8;
memcpy((void*)0x200000010144, "... [truncated large byte array] ...", 4096);
*(uint16_t*)0x200000011144 = 0x1000;
syscall(__NR_write, /*fd=*/r[0], /*data=*/0x200000010140ul, /*len=*/0x1006ul);
// mmap arguments: [
// addr: VMA[0x400000]
// len: len = 0x400000 (8 bytes)
// prot: mmap_prot = 0x1 (8 bytes)
// flags: mmap_flags = 0x10012 (8 bytes)
// fd: fd (resource)
// offset: intptr = 0x0 (8 bytes)
// ]
syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x400000ul, /*prot=PROT_READ*/1ul, /*flags=MAP_NONBLOCK|MAP_FIXED|MAP_PRIVATE*/0x10012ul, /*fd=*/r[0], /*offset=*/0ul);
// symlinkat arguments: [
// old: ptr[in, buffer] {
// buffer: {13 13 77 c5 fc 35 d4 14 54 d5 d4 1d 29 ad 1a 60 29 59 81 46 e6 be 16 6e 41 ad 0d bd 40 54 03 3c 9f 33 bb da 82 24 a2 f3 d7 72 e7 63 6e 48 b3 3c bf 70 83 72 e8 f1 b9 93 3e c5 12 77 43 be 22 06 20 9e f0 2d f9 cb f2 f6 e8 80 d3 38 2f 00} (length 0x4e)
// }
// newfd: fd_dir (resource)
// new: ptr[in, buffer] {
// buffer: {2e 2f 66 69 6c 65 30 00} (length 0x8)
// }
// ]
memcpy((void*)0x200000001040, "... [truncated large byte array] ...", 78);
memcpy((void*)0x200000000000, "./file0\000", 8);
syscall(__NR_symlinkat, /*old=*/0x200000001040ul, /*newfd=*/0xffffff9c, /*new=*/0x200000000000ul);
// syz_mount_image$ntfs3 arguments: [
// fs: ptr[in, buffer] {
// buffer: {6e 74 66 73 33 00} (length 0x6)
// }
// dir: ptr[in, buffer] {
// buffer: {2e 2f 66 69 6c 65 30 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 00} (length 0xfe)
// }
// flags: mount_flags = 0x2010c10 (8 bytes)
// opts: ptr[inout, array[ANYUNION]] {
// array[ANYUNION] {
// }
// }
// chdir: int8 = 0x1 (1 bytes)
// size: len = 0x1f757 (8 bytes)
// img: ptr[in, buffer] {
// buffer: (compressed buffer with length 0x1f757)
// }
// ]
// returns fd_dir
memcpy((void*)0x200000000080, "ntfs3\000", 6);
memcpy((void*)0x200000000500, "... [truncated large byte array] ...", 254);
memcpy((void*)0x20000001fd80, "... [truncated large byte array] ...", 128855);
syz_mount_image(/*fs=*/0x200000000080, /*dir=*/0x200000000500, /*flags=MS_LAZYTIME|MS_POSIXACL|MS_SYNCHRONOUS|MS_NODIRATIME|MS_NOATIME*/0x2010c10, /*opts=*/0x200000000380, /*chdir=*/1, /*size=*/0x1f757, /*img=*/0x20000001fd80);
// openat$cgroup_ro arguments: [
// fd: fd_cgroup (resource)
// file: ptr[in, buffer] {
// buffer: {63 70 75 73 65 74 2e 65 66 66 65 63 74 69 76 65 5f 63 70 75 73 00} (length 0x16)
// }
// flags: const = 0x275a (4 bytes)
// mode: const = 0x0 (2 bytes)
// ]
// returns fd
memcpy((void*)0x200000000040, "cpuset.effective_cpus\000", 22);
res = syscall(__NR_openat, /*fd=*/0xffffff9c, /*file=*/0x200000000040ul, /*flags=*/0x275a, /*mode=*/0);
if (res != -1)
r[1] = res;
// ioctl$EXT4_IOC_MOVE_EXT arguments: [
// fd: fd (resource)
// cmd: const = 0x40305829 (4 bytes)
// arg: ptr[in, move_extent] {
// move_extent {
// reserved: const = 0x17c04 (4 bytes)
// donor_fd: fd (resource)
// orig_start: int64 = 0x5 (8 bytes)
// donor_start: int64 = 0x100000001 (8 bytes)
// len: int64 = 0x0 (8 bytes)
// moved_len: int64 = 0x0 (8 bytes)
// }
// }
// ]
*(uint32_t*)0x200000000080 = 0x17c04;
*(uint32_t*)0x200000000084 = -1;
*(uint64_t*)0x200000000088 = 5;
*(uint64_t*)0x200000000090 = 0x100000001;
*(uint64_t*)0x200000000098 = 0;
*(uint64_t*)0x2000000000a0 = 0;
syscall(__NR_ioctl, /*fd=*/r[1], /*cmd=*/0x40305829, /*arg=*/0x200000000080ul);
return 0;
}
Reply: **Bug Analysis:**
The bug report indicates a possible circular locking dependency (AB-BA deadlock) in the `ntfs3` filesystem involving `ni->ni_lock` and `mapping->invalidate_lock`.
By examining the source code, we can trace the exact deadlock scenario:
1. **Thread 1 (`fallocate`)**: An unprivileged user calls `fallocate(fd, FALLOC_FL_PUNCH_HOLE, ...)` on an `ntfs3` file. The `ntfs_fallocate` function first acquires `mapping->invalidate_lock` for write (exclusive) via `filemap_invalidate_lock(mapping)`. It then proceeds to call `attr_punch_hole`, which attempts to acquire `ni->ni_lock` via `ni_lock(ni)`.
2. **Thread 2 (`ioctl FIEMAP`)**: Concurrently, the user calls `ioctl(fd, FS_IOC_FIEMAP, ...)` on the same file. The user provides a `fieinfo` buffer that is `mmap`ed to the same file (or another file that would cause a page fault). The `ntfs_fiemap` function first acquires `ni->ni_lock`. It then calls `ni_fiemap` -> `fiemap_fill_next_extent`, which uses `copy_to_user()` to write the extent data to the user-provided buffer.
3. **Page Fault**: The `copy_to_user()` call triggers a page fault on the user buffer. The page fault handler (`do_page_fault`) acquires the `mm->mmap_lock` for read, and then calls `filemap_fault`, which attempts to acquire `mapping->invalidate_lock` for read (shared).
**Deadlock:**
- Thread 1 holds `mapping->invalidate_lock` and is blocked waiting for `ni->ni_lock`.
- Thread 2 holds `ni->ni_lock` and is blocked in the page fault handler waiting for `mapping->invalidate_lock`.
**Security Impact Assessment:**
* **Exploitable:** False. This is a pure locking issue (deadlock) and does not lead to memory corruption, use-after-free, or any other condition that could be exploited for privilege escalation or arbitrary code execution.
* **Denial Of Service:** True. The deadlock will cause the involved threads to hang indefinitely in the uninterruptible sleep (`D`) state. Because Thread 2 also holds `mmap_lock` (read) while blocked, any other thread in the same process attempting to modify the memory map (e.g., `mmap`, `munmap`, `mprotect`, or even thread exit) will also hang forever. Furthermore, the `ntfs3` inode locks are held, preventing any other processes from accessing the file.
* **Accessible From Unprivileged Processes:** True. The bug can be triggered by any unprivileged user who has read and write access to a file on an `ntfs3` filesystem. Standard desktop Linux environments often auto-mount NTFS-formatted USB drives and grant the logged-in user full read/write access to the files, making this easily reachable.
* **Accessible From User Namespaces:** False. The `ntfs3` filesystem does not have the `FS_USERNS_MOUNT` flag, meaning an unprivileged user cannot mount an `ntfs3` image inside a user namespace to trigger this. It requires the filesystem to be already mounted by the system (e.g., via admin or auto-mounting).
* **Malicious Filesystem / Peripheral Trigger:** False. The bug is a logical flaw in the syscall handling of the filesystem driver. It does not require a maliciously crafted filesystem image or a malicious USB device to exploit; it works perfectly on a completely normal, benign `ntfs3` filesystem.
* **Remote / Network / VM Triggers:** False. The bug is triggered via local system calls and is not exposed to network traffic or virtualization boundaries.
|
| 6/2 |
2026/05/15 20:30 |
llm |
expert |
1m
Model:
Tokens:
input: 30827
output: 44
thoughts: 1547
Thoughts: **Analyzing a Potential Circular Lock Dependency in ntfs3**
Okay, so I'm looking at a warning related to a potential circular lock dependency within the `ntfs3` filesystem. It seems like the core issue revolves around three locks: `&ni->ni_lock`, `&mm->mmap_lock`, and `mapping.invalidate_lock`. The trace suggests the dependency chain is forming, where `mapping.invalidate_lock` is taken, then a fault occurs, potentially leading to taking `&mm->mmap_lock`, which in turn leads to taking `&ni->ni_lock`.
Specifically, the trace shows that `mapping.invalidate_lock` is acquired within `filemap_fault`, which is ultimately triggered by something like `strncpy_from_user` and then `getname_flags`, eventually traced back to `__arm64_sys_symlinkat`, which uses these functions to resolve a path. Then, we see `&mm->mmap_lock` held within `fiemap_fill_next_extent` and called by `ntfs_fiemap`, which gets triggered by the `ioctl_fiemap` system call. The third lock, `&ni->ni_lock`, is held within `ntfs_fallocate` called by `vfs_fallocate` and invoked by the `ioctl_preallocate` or other calls to `file_ioctl` in userspace.
The deadlock scenario described involves one CPU holding `mapping.invalidate_lock` and `&ni->ni_lock`, while another CPU holds `&mm->mmap_lock` and then attempts to acquire `mapping.invalidate_lock`. That's a classic circular dependency. Looking at the report more closely, `ntfs_fallocate` *does* take `mapping.invalidate_lock` and then `ni_lock` in this order. That part is clear now.
But the trace is confusing - `ntfs_fiemap` takes `ni_lock`, then it calls `fiemap_fill_next_extent`, which *might* take `&mm->mmap_lock` if a page fault occurs. That's a critical path to examine. Let me check `ntfs_fiemap` to ensure this suspected order is correct. Let me also investigate `ni_fiemap`.
The provided trace also mentions syz.3.855/8482 holding `sb_writers`, `&sb->s_type->i_mutex_key`, and `mapping.invalidate_lock` when `ntfs_fallocate` is called, which could indicate a concurrent access issue. Let's delve into these functions directly to verify the lock acquisition order and the exact execution paths that lead to the potential deadlock.
|
| 7/2 |
2026/05/15 20:31 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/ntfs3/file.c IncludeLines:true Name:ntfs_fiemap]
Results: map[SourceCode:1307: /*
1308: * ntfs_fiemap - inode_operations::fiemap
1309: */
1310: int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
1311: __u64 start, __u64 len)
1312: {
1313: int err;
1314: struct ntfs_inode *ni = ntfs_i(inode);
1315:
1316: /* Avoid any operation if inode is bad. */
1317: if (unlikely(is_bad_ni(ni)))
1318: return -EINVAL;
1319:
1320: err = fiemap_prep(inode, fieinfo, start, &len, ~FIEMAP_FLAG_XATTR);
1321: if (err)
1322: return err;
1323:
1324: ni_lock(ni);
1325:
1326: err = ni_fiemap(ni, fieinfo, start, len);
1327:
1328: ni_unlock(ni);
1329:
1330: return err;
1331: }
SourceFile:fs/ntfs3/file.c]
|
| 8/2 |
2026/05/15 20:31 |
llm |
expert |
0m
Model:
Tokens:
input: 33382
output: 43
thoughts: 577
Thoughts: **Analyzing a Potential Deadlock in the NTFS Filesystem**
Okay, let's break this down. It seems we have a potential circular locking dependency lurking in the NTFS code, and I need to figure out if it can lead to a deadlock.
First, I see that the `ntfs_fiemap` function acquires the `ni_lock` (presumably a node or inode lock) and then calls `ni_fiemap`. Inside `ni_fiemap`, we have `fiemap_fill_next_extent`, and this function does a `copy_to_user` operation, which means it has to take the `mmap_lock`. So, the sequence is `ni_lock` -> `mmap_lock`.
Now, `ntfs_fallocate` grabs `mapping.invalidate_lock` and *then* the `ni_lock`. So the sequence is `mapping.invalidate_lock` -> `ni_lock`.
And we know the `mmap_lock` has to come before `mapping.invalidate_lock` because a page fault takes the `mmap_lock` and then `filemap_fault` uses `mapping.invalidate_lock`.
So we have:
`ni_lock` -> `mmap_lock`
`mmap_lock` -> `mapping.invalidate_lock`
`mapping.invalidate_lock` -> `ni_lock`
That's a textbook circular dependency, isn't it? The question now is whether this can actually lead to a deadlock.
Let's imagine a scenario:
* **Thread 1:** `ntfs_fiemap` is running. It acquires `ni_lock` and then faults on user memory. This fault operation attempts to grab `mmap_lock` (or is waiting for it).
* **Thread 2:** A page fault happens. This thread acquires `mmap_lock` and then calls `filemap_fault`, which attempts to grab `mapping.invalidate_lock` (or is waiting for it).
* **Thread 3:** `ntfs_fallocate` is called. It acquires `mapping.invalidate_lock` and then tries to take `ni_lock`.
Boom. Deadlock. Thread 1 holds `ni_lock` and waits for `mmap_lock`. Thread 2 holds `mmap_lock` and waits for `mapping.invalidate_lock`. Thread 3 holds `mapping.invalidate_lock` and waits for `ni_lock`. Classic.
Wait, let's step back a second. Thread 1 and 2 are grabbing `mmap_lock` and it is an `rwsem`. So multiple readers can hold the lock at the same time.
But, if there is a writer waiting for `mmap_lock` (e.g. mmap, mprotect), then readers will block.
Or if Thread 1 faults on user memory, it takes `mmap_lock` for read.
Thread 3 takes `mapping.invalidate_lock` for write (in `ntfs_fallocate`).
Thread 2 takes `mmap_lock` for read, then takes `mapping.invalidate_lock` for read (in `filemap_fault`).
Okay, let's go check `ntfs_fallocate` and be certain. This looks like a serious potential problem that needs to be resolved.
|
| 9/2 |
2026/05/15 20:31 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/ntfs3/file.c IncludeLines:true Name:ntfs_fallocate]
Results: map[SourceCode: 483: /*
484: * ntfs_fallocate - file_operations::ntfs_fallocate
485: *
486: * Preallocate space for a file. This implements ntfs's fallocate file
487: * operation, which gets called from sys_fallocate system call. User
488: * space requests 'len' bytes at 'vbo'. If FALLOC_FL_KEEP_SIZE is set
489: * we just allocate clusters without zeroing them out. Otherwise we
490: * allocate and zero out clusters via an expanding truncate.
491: */
492: static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
493: {
494: struct inode *inode = file_inode(file);
495: struct address_space *mapping = inode->i_mapping;
496: struct super_block *sb = inode->i_sb;
497: struct ntfs_sb_info *sbi = sb->s_fs_info;
498: struct ntfs_inode *ni = ntfs_i(inode);
499: loff_t end = vbo + len;
500: loff_t vbo_down = round_down(vbo, max_t(unsigned long,
501: sbi->cluster_size, PAGE_SIZE));
502: bool is_supported_holes = is_sparsed(ni) || is_compressed(ni);
503: loff_t i_size, new_size;
504: bool map_locked;
505: int err;
506:
507: /* No support for dir. */
508: if (!S_ISREG(inode->i_mode))
509: return -EOPNOTSUPP;
510:
511: /*
512: * vfs_fallocate checks all possible combinations of mode.
513: * Do additional checks here before ntfs_set_state(dirty).
514: */
515: if (mode & FALLOC_FL_PUNCH_HOLE) {
516: if (!is_supported_holes)
517: return -EOPNOTSUPP;
518: } else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
519: } else if (mode & FALLOC_FL_INSERT_RANGE) {
520: if (!is_supported_holes)
521: return -EOPNOTSUPP;
522: } else if (mode &
523: ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
524: FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE)) {
525: ntfs_inode_warn(inode, "fallocate(0x%x) is not supported",
526: mode);
527: return -EOPNOTSUPP;
528: }
529:
530: ntfs_set_state(sbi, NTFS_DIRTY_DIRTY);
531:
532: inode_lock(inode);
533: i_size = inode->i_size;
534: new_size = max(end, i_size);
535: map_locked = false;
536:
537: if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) {
538: /* Should never be here, see ntfs_file_open. */
539: err = -EOPNOTSUPP;
540: goto out;
541: }
542:
543: if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE |
544: FALLOC_FL_INSERT_RANGE)) {
545: inode_dio_wait(inode);
546: filemap_invalidate_lock(mapping);
547: map_locked = true;
548: }
549:
550: if (mode & FALLOC_FL_PUNCH_HOLE) {
551: u32 frame_size;
552: loff_t mask, vbo_a, end_a, tmp;
553:
554: err = filemap_write_and_wait_range(mapping, vbo_down,
555: LLONG_MAX);
556: if (err)
557: goto out;
558:
559: truncate_pagecache(inode, vbo_down);
560:
561: ni_lock(ni);
562: err = attr_punch_hole(ni, vbo, len, &frame_size);
563: ni_unlock(ni);
564: if (!err)
565: goto ok;
566:
567: if (err != E_NTFS_NOTALIGNED)
568: goto out;
569:
570: /* Process not aligned punch. */
571: err = 0;
572: mask = frame_size - 1;
573: vbo_a = (vbo + mask) & ~mask;
574: end_a = end & ~mask;
575:
576: tmp = min(vbo_a, end);
577: if (tmp > vbo) {
578: err = ntfs_zero_range(inode, vbo, tmp);
579: if (err)
580: goto out;
581: }
582:
583: if (vbo < end_a && end_a < end) {
584: err = ntfs_zero_range(inode, end_a, end);
585: if (err)
586: goto out;
587: }
588:
589: /* Aligned punch_hole */
590: if (end_a > vbo_a) {
591: ni_lock(ni);
592: err = attr_punch_hole(ni, vbo_a, end_a - vbo_a, NULL);
593: ni_unlock(ni);
594: if (err)
595: goto out;
596: }
597: } else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
598: /*
599: * Write tail of the last page before removed range since
600: * it will get removed from the page cache below.
601: */
602: err = filemap_write_and_wait_range(mapping, vbo_down, vbo);
603: if (err)
604: goto out;
605:
606: /*
607: * Write data that will be shifted to preserve them
608: * when discarding page cache below.
609: */
610: err = filemap_write_and_wait_range(mapping, end, LLONG_MAX);
611: if (err)
612: goto out;
613:
614: truncate_pagecache(inode, vbo_down);
615:
616: ni_lock(ni);
617: err = attr_collapse_range(ni, vbo, len);
618: ni_unlock(ni);
619: if (err)
620: goto out;
621: } else if (mode & FALLOC_FL_INSERT_RANGE) {
622: /* Check new size. */
623: err = inode_newsize_ok(inode, new_size);
624: if (err)
625: goto out;
626:
627: /* Write out all dirty pages. */
628: err = filemap_write_and_wait_range(mapping, vbo_down,
629: LLONG_MAX);
630: if (err)
631: goto out;
632: truncate_pagecache(inode, vbo_down);
633:
634: ni_lock(ni);
635: err = attr_insert_range(ni, vbo, len);
636: ni_unlock(ni);
637: if (err)
638: goto out;
639: } else {
640: /* Check new size. */
641: u8 cluster_bits = sbi->cluster_bits;
642:
643: /* Be sure file is non resident. */
644: if (is_resident(ni)) {
645: ni_lock(ni);
646: err = attr_force_nonresident(ni);
647: ni_unlock(ni);
648: if (err)
649: goto out;
650: }
651:
652: /* generic/213: expected -ENOSPC instead of -EFBIG. */
653: if (!is_supported_holes) {
654: loff_t to_alloc = new_size - inode_get_bytes(inode);
655:
656: if (to_alloc > 0 &&
657: (to_alloc >> cluster_bits) >
658: wnd_zeroes(&sbi->used.bitmap)) {
659: err = -ENOSPC;
660: goto out;
661: }
662: }
663:
664: err = inode_newsize_ok(inode, new_size);
665: if (err)
666: goto out;
667:
668: if (new_size > i_size) {
669: /*
670: * Allocate clusters, do not change 'valid' size.
671: */
672: err = ntfs_set_size(inode, new_size);
673: if (err)
674: goto out;
675: }
676:
677: if (is_supported_holes) {
678: CLST vcn = vbo >> cluster_bits;
679: CLST cend = bytes_to_cluster(sbi, end);
680: CLST cend_v = bytes_to_cluster(sbi, ni->i_valid);
681: CLST lcn, clen;
682: bool new;
683:
684: if (cend_v > cend)
685: cend_v = cend;
686:
687: /*
688: * Allocate and zero new clusters.
689: * Zeroing these clusters may be too long.
690: */
691: for (; vcn < cend_v; vcn += clen) {
692: err = attr_data_get_block(ni, vcn, cend_v - vcn,
693: &lcn, &clen, &new,
694: true);
695: if (err)
696: goto out;
697: }
698: /*
699: * Allocate but not zero new clusters.
700: */
701: for (; vcn < cend; vcn += clen) {
702: err = attr_data_get_block(ni, vcn, cend - vcn,
703: &lcn, &clen, &new,
704: false);
705: if (err)
706: goto out;
707: }
708: }
709:
710: if (mode & FALLOC_FL_KEEP_SIZE) {
711: ni_lock(ni);
712: /* True - Keep preallocated. */
713: err = attr_set_size(ni, ATTR_DATA, NULL, 0,
714: &ni->file.run, i_size, &ni->i_valid,
715: true, NULL);
716: ni_unlock(ni);
717: if (err)
718: goto out;
719: } else if (new_size > i_size) {
720: i_size_write(inode, new_size);
721: }
722: }
723:
724: ok:
725: err = file_modified(file);
726: if (err)
727: goto out;
728:
729: out:
730: if (map_locked)
731: filemap_invalidate_unlock(mapping);
732:
733: if (!err) {
734: inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
735: mark_inode_dirty(inode);
736: }
737:
738: inode_unlock(inode);
739: return err;
740: }
SourceFile:fs/ntfs3/file.c]
|
| 10/2 |
2026/05/15 20:31 |
llm |
expert |
0m
Model:
Tokens:
input: 38521
output: 44
thoughts: 973
Thoughts: **Analyzing a Potential Deadlock in the ntfs3 Filesystem**
Okay, so I'm looking at a potential deadlock scenario within the `ntfs3` filesystem driver. The core of the problem lies in the locking order when handling operations like `fallocate` (specifically punch hole and similar functions) and `fiemap`. My analysis points to a circular dependency in the acquisition of locks.
Here's how it breaks down: `ntfs_fallocate`, when dealing with `FALLOC_FL_PUNCH_HOLE` (or related flags), takes `filemap_invalidate_lock` *before* acquiring the `ni_lock`. Simultaneously, `ntfs_fiemap` calls `ni_lock` and then inside the `ni_fiemap` function, it uses a user-space buffer, which leads to a page fault. This page fault then tries to acquire `mmap_lock` and subsequently `filemap_invalidate_lock`.
Specifically, the deadlock occurs due to the following locking sequence:
* **Thread 1 (ntfs_fiemap):** `ni_lock` -> Page Fault -> `mmap_lock`
* **Thread 2 (Page Fault):** `mmap_lock` -> `filemap_invalidate_lock`
* **Thread 3 (ntfs_fallocate):** `filemap_invalidate_lock` -> `ni_lock`
This clearly presents a circular lock acquisition pattern, a classic recipe for a deadlock.
The next question is, can an unprivileged user actually trigger this? `fallocate` and `ioctl(FS_IOC_FIEMAP)` are available to unprivileged users, provided they have the correct permissions on a file. The filesystem in question is `ntfs3`. Crucially, it is not user-namespaced by default, which initially led me down a slightly misleading path (thinking about syzbot, but realizing it runs as root anyway within a VM).
However, if the system administrator mounts an `ntfs3` filesystem (e.g., a USB stick), then any user who has read and write access to files on that filesystem *can* trigger this deadlock by calling `fallocate` and `fiemap` concurrently on the same file. I need read access for `fiemap`, and write access for `fallocate`. I'm starting to think this could be fairly common. USB drives are often mounted with relaxed permissions, and the access rights are usually granted to the user.
So, let me categorize this:
* **Exploitable:** No, it's a DoS, not code execution.
* **Denial of Service:** Yes.
* **Accessible From Unprivileged Processes:** Yes, if the filesystem is mounted and the user has read/write access to a file.
* **Accessible From User Namespaces:** No, `ntfs3` is not usually user-namespaced.
* **VM Guest Trigger:** No, it's not directly virtualization related.
* **VM Host Trigger (Confidential Computing):** No.
* **Ethernet Network Trigger:** No.
* **Other Remote Trigger:** No.
* **Peripheral Trigger:** Yes, a USB drive being mounted would be a likely vector. Importantly, it doesn't need a *malicious* filesystem image, it just needs standard `ntfs3` concurrent operations.
Essentially, this is a local denial-of-service vulnerability. My current assessment is that concurrent `fallocate` and `fiemap` calls on a common `ntfs3` filesystem with the appropriate permissions can trigger this deadlock, leading to a system freeze. I should double check that `ntfs3` still can't be mounted in a user namespace to be sure.
|
| 11/2 |
2026/05/15 20:31 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/ntfs3/super.c IncludeLines:true Name:ntfs_fs_type]
Results: map[SourceCode:1820: // clang-format off
1821: static struct file_system_type ntfs_fs_type = {
1822: .owner = THIS_MODULE,
1823: .name = "ntfs3",
1824: .init_fs_context = ntfs_init_fs_context,
1825: .parameters = ntfs_fs_parameters,
1826: .kill_sb = ntfs3_kill_sb,
1827: .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
1828: };
SourceFile:fs/ntfs3/super.c]
|
| 12/2 |
2026/05/15 20:31 |
llm |
expert |
0m
Model:
Tokens:
input: 40544
output: 46
thoughts: 1533
Thoughts: **Analyzing a Potential NTFS3 Filesystem Deadlock**
Okay, so here's the situation as I see it. It looks like an unprivileged user can't directly trigger a mount in a user namespace because `FS_USERNS_MOUNT` isn't set. But, and this is the key, if they have write access to a file on an already mounted `ntfs3` filesystem, things get interesting. We're talking about a bug triggered through standard filesystem operations, not anything exotic, so it is "Accessible From Unprivileged Processes". The initial thought was that this hinges specifically on the `ntfs3` filesystem.
I need to dive deeper into the locking dependencies. `ntfs_fiemap`, the first thread, takes `ni_lock(ni)`. It then calls `ni_fiemap` and ultimately calls `fiemap_fill_next_extent`, which writes to user space. If this user space address isn't mapped, it triggers a page fault. And that `copy_to_user` function can also trigger a page fault, requiring `mmap_lock` (read).
Now, here's where it gets interesting: a second thread might trigger a normal page fault on a file mapping. This thread grabs `mmap_lock` (read) and calls `filemap_fault`, which then wants `mapping.invalidate_lock` (read). A third thread, using `ntfs_fallocate`, takes `mapping.invalidate_lock` (write) and *also* wants `ni_lock(ni)`.
Can this lead to a deadlock? Let's trace it. Thread 3, the `fallocate` operation, holds `mapping.invalidate_lock` (write). It then tries to take `ni_lock` and blocks because Thread 1, the `fiemap` operation, is already holding it. Thread 1 is stuck on `ni_lock`. Thread 1 has `mmap_lock` read, and the user space address requires a page fault, and this wants to take `mmap_lock` (read). If no writer is waiting on `mmap_lock`, this is all good, but we see a deadlock report in lockdep.
Ok, so it's a circular dependency: `ni_lock` -> `mmap_lock`, `mmap_lock` -> `mapping.invalidate_lock`, and `mapping.invalidate_lock` -> `ni_lock`.
Let's assume Thread 1 takes `ni_lock` and then tries `mmap_lock` (read). If a writer is waiting for `mmap_lock`, like `mprotect`, Thread 1 is blocked to prevent writer starvation. Now Thread 1 is blocked on `mmap_lock`. Thread 2 holds `mmap_lock` (read), and tries `mapping.invalidate_lock`. Thread 3 holds `mapping.invalidate_lock` (write) so Thread 2 blocks. Thread 3 holds `mapping.invalidate_lock`, and is blocked by Thread 1 on `ni_lock`. Thread 1 holds `ni_lock`, and is blocked on `mmap_lock` because Thread 4 is waiting for `mmap_lock` (write). *Yes*, a classic read-write lock deadlock! Four threads are involved in the deadlock, or three threads if Thread 2 takes `mmap_lock` for write.
This confirms it. Deadlock, potentially leading to a Denial of Service.
Can an unprivileged user actually trigger this? Let's break down the scenario:
1. **Thread 1:** `fiemap` on an `ntfs3` file, with the user buffer pointing to a swapped-out or unmapped page.
2. **Thread 2:** Page fault on an `ntfs3` file (same or different, but the same file given `mapping.invalidate_lock` is per-inode?).
3. **Thread 3:** `fallocate` on *the same* `ntfs3` file.
4. **Thread 4:** `mprotect` or `mmap` on the user buffer used by Thread 1.
The critical thing is *all* these operations are available to an unprivileged user who has read/write access to an `ntfs3` file.
Now, are `ntfs3` filesystems commonly accessible to unprivileged users? On desktop systems, yes. USB drives formatted as NTFS are automatically mounted, giving the logged-in user read/write access through the mount options. This is a very real DoS vulnerability in a desktop environment. Servers, maybe not as much, but if NTFS is mounted and accessible, the vulnerability is the same.
Are there other entry points to this?
|
| 13/2 |
2026/05/15 20:32 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/ntfs3/file.c IncludeLines:true Name:ntfs_file_read_iter]
Results: map[SourceCode: 847: /*
848: * ntfs_file_read_iter - file_operations::read_iter
849: */
850: static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
851: {
852: struct file *file = iocb->ki_filp;
853: struct inode *inode = file_inode(file);
854: struct ntfs_inode *ni = ntfs_i(inode);
855: ssize_t err;
856:
857: err = check_read_restriction(inode);
858: if (err)
859: return err;
860:
861: if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) {
862: ntfs_inode_warn(inode, "direct i/o + compressed not supported");
863: return -EOPNOTSUPP;
864: }
865:
866: return generic_file_read_iter(iocb, iter);
867: }
SourceFile:fs/ntfs3/file.c]
|
| 14/2 |
2026/05/15 20:32 |
llm |
expert |
1m
Model:
Tokens:
input: 43505
output: 46
thoughts: 32
Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue:
**File Iteration Lock Considerations**
Alright, let's see... the `ntfs_file_read_iter` function, right? It seems I've got a note about it not taking the `ni_lock`. That's interesting. Usually, when dealing with file systems, you're constantly juggling concurrency and locking. The absence of the lock suggests some clever design here. Perhaps it leverages some other mechanism for safe iteration – maybe read-copy-update, some sort of per-file-object locking, or relies on the underlying block device's inherent locking. I'll need to dig into the implementation details a bit to see *how* it manages concurrency without the `ni_lock`.
Now, that brings me to `ntfs_file_write_iter`. If the read function doesn't use the primary lock, it's vital to know if the write function does. Obviously, writes are much more complex because they involve modifications to the underlying data and metadata. *I'd expect* `ntfs_file_write_iter` *would* need to acquire the `ni_lock` (or some similar, possibly more granular, lock) to ensure data integrity. If it doesn't, that's potentially a serious race condition vulnerability that should be investigated thoroughly. A write without a lock implies a completely different concurrency model, so I should see how this fits into the wider filesystem design. It's possible, though unlikely, it uses an optimistic concurrency control scheme, but that would need extremely careful design.
|
| 15/2 |
2026/05/15 20:33 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/ntfs3/file.c IncludeLines:true Name:ntfs_file_write_iter]
Results: map[SourceCode:1177: /*
1178: * ntfs_file_write_iter - file_operations::write_iter
1179: */
1180: static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
1181: {
1182: struct file *file = iocb->ki_filp;
1183: struct inode *inode = file_inode(file);
1184: struct ntfs_inode *ni = ntfs_i(inode);
1185: ssize_t ret;
1186: int err;
1187:
1188: if (!inode_trylock(inode)) {
1189: if (iocb->ki_flags & IOCB_NOWAIT)
1190: return -EAGAIN;
1191: inode_lock(inode);
1192: }
1193:
1194: ret = check_write_restriction(inode);
1195: if (ret)
1196: goto out;
1197:
1198: if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) {
1199: ntfs_inode_warn(inode, "direct i/o + compressed not supported");
1200: ret = -EOPNOTSUPP;
1201: goto out;
1202: }
1203:
1204: ret = generic_write_checks(iocb, from);
1205: if (ret <= 0)
1206: goto out;
1207:
1208: err = file_modified(iocb->ki_filp);
1209: if (err) {
1210: ret = err;
1211: goto out;
1212: }
1213:
1214: if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) {
1215: /* Should never be here, see ntfs_file_open(). */
1216: ret = -EOPNOTSUPP;
1217: goto out;
1218: }
1219:
1220: ret = ntfs_extend(inode, iocb->ki_pos, ret, file);
1221: if (ret)
1222: goto out;
1223:
1224: ret = is_compressed(ni) ? ntfs_compress_write(iocb, from) :
1225: __generic_file_write_iter(iocb, from);
1226:
1227: out:
1228: inode_unlock(inode);
1229:
1230: if (ret > 0)
1231: ret = generic_write_sync(iocb, ret);
1232:
1233: return ret;
1234: }
SourceFile:fs/ntfs3/file.c]
|
| 16/2 |
2026/05/15 20:33 |
llm |
expert |
0m
Model:
Tokens:
input: 44770
output: 42
thoughts: 35
Thoughts: Here's my summary, as though I'm thinking through this process:
**Diving into the NTFS Write Iteration**
Okay, so `ntfs_file_write_iter` is the function we're concerned with, and it's calling `ntfs_extend`. That's the key. I know `ntfs_extend` is where the allocation and potentially the metadata manipulations happen. Since we're dealing with writes, I need to keep in mind that `ntfs_extend` *might* try to acquire `ni_lock`. That's a critical point for understanding potential contention. Therefore, my immediate focus is to dig into the implementation of `ntfs_extend` and confirm whether or not it's holding this lock and under what conditions. Understanding the lock's scope and when it's acquired will be the heart of my next steps.
|
| 17/2 |
2026/05/15 20:33 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/ntfs3/file.c IncludeLines:true Name:ntfs_extend]
Results: map[SourceCode: 343: static int ntfs_extend(struct inode *inode, loff_t pos, size_t count,
344: struct file *file)
345: {
346: struct ntfs_inode *ni = ntfs_i(inode);
347: struct address_space *mapping = inode->i_mapping;
348: loff_t end = pos + count;
349: bool extend_init = file && pos > ni->i_valid;
350: int err;
351:
352: if (end <= inode->i_size && !extend_init)
353: return 0;
354:
355: /* Mark rw ntfs as dirty. It will be cleared at umount. */
356: ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_DIRTY);
357:
358: if (end > inode->i_size) {
359: err = ntfs_set_size(inode, end);
360: if (err)
361: goto out;
362: }
363:
364: if (extend_init && !is_compressed(ni)) {
365: err = ntfs_extend_initialized_size(file, ni, ni->i_valid, pos);
366: if (err)
367: goto out;
368: } else {
369: err = 0;
370: }
371:
372: if (file && is_sparsed(ni)) {
373: /*
374: * This code optimizes large writes to sparse file.
375: * TODO: merge this fragment with fallocate fragment.
376: */
377: struct ntfs_sb_info *sbi = ni->mi.sbi;
378: CLST vcn = pos >> sbi->cluster_bits;
379: CLST cend = bytes_to_cluster(sbi, end);
380: CLST cend_v = bytes_to_cluster(sbi, ni->i_valid);
381: CLST lcn, clen;
382: bool new;
383:
384: if (cend_v > cend)
385: cend_v = cend;
386:
387: /*
388: * Allocate and zero new clusters.
389: * Zeroing these clusters may be too long.
390: */
391: for (; vcn < cend_v; vcn += clen) {
392: err = attr_data_get_block(ni, vcn, cend_v - vcn, &lcn,
393: &clen, &new, true);
394: if (err)
395: goto out;
396: }
397: /*
398: * Allocate but not zero new clusters.
399: */
400: for (; vcn < cend; vcn += clen) {
401: err = attr_data_get_block(ni, vcn, cend - vcn, &lcn,
402: &clen, &new, false);
403: if (err)
404: goto out;
405: }
406: }
407:
408: inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
409: mark_inode_dirty(inode);
410:
411: if (IS_SYNC(inode)) {
412: int err2;
413:
414: err = filemap_fdatawrite_range(mapping, pos, end - 1);
415: err2 = sync_mapping_buffers(mapping);
416: if (!err)
417: err = err2;
418: err2 = write_inode_now(inode, 1);
419: if (!err)
420: err = err2;
421: if (!err)
422: err = filemap_fdatawait_range(mapping, pos, end - 1);
423: }
424:
425: out:
426: return err;
427: }
SourceFile:fs/ntfs3/file.c]
|
| 18/2 |
2026/05/15 20:33 |
llm |
expert |
0m
Model:
Tokens:
input: 46295
output: 44
thoughts: 39
Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue:
**Investigating NTFS Volume Extension**
Right, `ntfs_extend`... that calls `ntfs_set_size` and `ntfs_extend_initialized_size`. Let's dig into this. I need to understand the mechanism here. Clearly, the goal is to expand the allocated space on an NTFS volume. The first function, `ntfs_set_size`, is obviously critical to actually making that happen, so let's check what that is doing. I'll need to know whether its handling logical or physical sector sizes, and if it interacts with the MFT directly, or another structure, such as the volume boot record (VBR). I want to see how the change is made persistent, too.
|
| 19/2 |
2026/05/15 20:33 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/ntfs3/file.c IncludeLines:true Name:ntfs_set_size]
Results: map[SourceCode: 840: int ntfs_set_size(struct inode *inode, u64 new_size)
841: {
842: struct super_block *sb = inode->i_sb;
843: struct ntfs_sb_info *sbi = sb->s_fs_info;
844: struct ntfs_inode *ni = ntfs_i(inode);
845: int err;
846:
847: /* Check for maximum file size. */
848: if (is_sparsed(ni) || is_compressed(ni)) {
849: if (new_size > sbi->maxbytes_sparse) {
850: err = -EFBIG;
851: goto out;
852: }
853: } else if (new_size > sbi->maxbytes) {
854: err = -EFBIG;
855: goto out;
856: }
857:
858: ni_lock(ni);
859: down_write(&ni->file.run_lock);
860:
861: err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, new_size,
862: &ni->i_valid, true, NULL);
863:
864: up_write(&ni->file.run_lock);
865: ni_unlock(ni);
866:
867: mark_inode_dirty(inode);
868:
869: out:
870: return err;
871: }
SourceFile:fs/ntfs3/inode.c]
|
| 20/2 |
2026/05/15 20:33 |
llm |
expert |
0m
Model:
Tokens:
input: 47046
output: 66
thoughts: 4857
Thoughts: **Analysis of Potential Deadlock in NTFS3 Filesystem**
Okay, let's break this down systematically. My initial impression is that we've got a classic locking issue within the `ntfs3` filesystem driver. I'm focusing on the interaction between file size manipulation and memory mapping, specifically how `ntfs_set_size` and `ntfs_file_write_iter` interact with the locking mechanisms. Right away, `ni_lock` (inode lock) is the primary point of concern. The critical point is that `ntfs_set_size` acquires `ni_lock` and releases it *before* calling `__generic_file_write_iter`. This introduces a potential race condition.
I start by checking `generic_file_write_iter`, then I'm looking at `mapping.invalidate_lock`. That's important! `__generic_file_write_iter` ends up calling `generic_perform_write`, which in turn calls `fault_in_iov_iter_readable`, and that acquires `mmap_lock`. Okay, so `__generic_file_write_iter` *does* take `mmap_lock`, but not `mapping.invalidate_lock`.
The crux of the matter appears to be where `ni_lock` and `mmap_lock` intersect. I note that `ntfs_fallocate` *does* take `mapping.invalidate_lock`, and *then* takes `ni_lock`. That's a key clue. I immediately see the potential for a deadlock here. `ntfs_fiemap` is the second critical point in the analysis.
Now, I'm trying to determine if this can be exploited by an unprivileged user. udisks2 on a standard desktop system mounts removable media like USB drives. This means a logged-in user can often read and write files on `ntfs3` filesystems without requiring root privileges. This is an important detail. If the user can run `fallocate` and `fiemap`, that's the trigger. This means it's definitely accessible to unprivileged processes. The question then is, does it require a crafted, malicious filesystem image? No, this isn't a *filesystem* vulnerability itself. It's a bug in how `ntfs3` handles locking for perfectly *valid* operations, so any NTFS filesystem should be susceptible. So no to the malicious trigger.
If it's just a local DoS, it means a local, unprivileged user can hang the machine. Does it become a privilege escalation vector? No, deadlocks are just DoS, so no.
I'm now looking at the criteria, and it's a DoS attack. It's accessible to unprivileged users, and it doesn't need to be triggered by a peripheral. I need to be exact here. Even if an NTFS drive is auto-mounted by the OS, it doesn't need a malicious filesystem to trigger it. So no to the peripheral trigger.
So, I need to verify how `fiemap` works, since I'm trying to reproduce this. To trigger it the unprivileged user needs read and write access. `fallocate` needs write access, which is the crucial point for the deadlock. Is `ntfs3` commonly used? Yes, it's the default NTFS driver since Linux 5.15. That makes it more accessible to more users. So yes, it is.
Time to confirm the locking order that makes the deadlock.
Thread 1:
- `ioctl(fd, FS_IOC_FIEMAP, ...)`
- Calls `ntfs_fiemap`
- `ntfs_fiemap` takes `ni_lock(ni)`
- Calls `ni_fiemap` -> `fiemap_fill_next_extent`
- `fiemap_fill_next_extent` calls `copy_to_user`
- `copy_to_user` faults, triggering `mmap_lock` (read)
Thread 2:
- `fallocate(fd, FALLOC_FL_PUNCH_HOLE, ...)`
- `vfs_fallocate` -> `ntfs_fallocate`
- `ntfs_fallocate` takes `filemap_invalidate_lock(mapping)` (write)
- Calls `ni_lock(ni)`
Thread 3:
- Page fault for a memory mapping that overlaps the file
The deadlock can occur if Thread 3 and Thread 1 use the *same file*. This happens when the user passes in `mmap`ed memory address to the `fieinfo` buffer. This guarantees the overlap. When `fiemap_fill_next_extent` attempts `copy_to_user` to that `mmap`ed
|
| 21/2 |
2026/05/15 20:34 |
tool |
set-results |
0m
Args: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:true UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
Results: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:true UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
|
| 22/2 |
2026/05/15 20:34 |
llm |
expert |
1m
Model:
Tokens:
input: 53058
output: 849
thoughts: 14
Thoughts: Here's your summary:
**Finalizing the Response**
Okay, the crucial data is in and the results are solidified. Now, it's time to craft the conclusive response. This is where I synthesize everything, weaving the evidence and analysis into a coherent and compelling narrative. I need to ensure the language is precise, the argumentation is airtight, and the conclusions are impeccably supported. It's about distilling complexity into clarity, presenting the findings in a way that's both insightful and readily understood, while adding value. This final piece is critical; it's the culmination of the entire process and needs to resonate with my audience. I will make sure this last piece has the maximum impact.
|
| 23/1 |
2026/05/15 20:35 |
action |
format-explanation |
0m
Results: map[Explanation:**Bug Analysis:**
The bug report indicates a possible circular locking dependency (AB-BA deadlock)
in the `ntfs3` filesystem involving `ni->ni_lock` and
`mapping->invalidate_lock`.
By examining the source code, we can trace the exact deadlock scenario:
1. **Thread 1 (`fallocate`)**: An unprivileged user calls `fallocate(fd,
FALLOC_FL_PUNCH_HOLE, ...)` on an `ntfs3` file. The `ntfs_fallocate` function
first acquires `mapping->invalidate_lock` for write (exclusive) via
`filemap_invalidate_lock(mapping)`. It then proceeds to call `attr_punch_hole`,
which attempts to acquire `ni->ni_lock` via `ni_lock(ni)`.
2. **Thread 2 (`ioctl FIEMAP`)**: Concurrently, the user calls `ioctl(fd,
FS_IOC_FIEMAP, ...)` on the same file. The user provides a `fieinfo` buffer that
is `mmap`ed to the same file (or another file that would cause a page fault).
The `ntfs_fiemap` function first acquires `ni->ni_lock`. It then calls
`ni_fiemap` -> `fiemap_fill_next_extent`, which uses `copy_to_user()` to write
the extent data to the user-provided buffer.
3. **Page Fault**: The `copy_to_user()` call triggers a page fault on the user
buffer. The page fault handler (`do_page_fault`) acquires the `mm->mmap_lock`
for read, and then calls `filemap_fault`, which attempts to acquire
`mapping->invalidate_lock` for read (shared).
**Deadlock:**
- Thread 1 holds `mapping->invalidate_lock` and is blocked waiting for
`ni->ni_lock`.
- Thread 2 holds `ni->ni_lock` and is blocked in the page fault handler waiting
for `mapping->invalidate_lock`.
**Security Impact Assessment:**
* **Exploitable:** False. This is a pure locking issue (deadlock) and does not
lead to memory corruption, use-after-free, or any other condition that could be
exploited for privilege escalation or arbitrary code execution.
* **Denial Of Service:** True. The deadlock will cause the involved threads to
hang indefinitely in the uninterruptible sleep (`D`) state. Because Thread 2
also holds `mmap_lock` (read) while blocked, any other thread in the same
process attempting to modify the memory map (e.g., `mmap`, `munmap`, `mprotect`,
or even thread exit) will also hang forever. Furthermore, the `ntfs3` inode
locks are held, preventing any other processes from accessing the file.
* **Accessible From Unprivileged Processes:** True. The bug can be triggered by
any unprivileged user who has read and write access to a file on an `ntfs3`
filesystem. Standard desktop Linux environments often auto-mount NTFS-formatted
USB drives and grant the logged-in user full read/write access to the files,
making this easily reachable.
* **Accessible From User Namespaces:** False. The `ntfs3` filesystem does not
have the `FS_USERNS_MOUNT` flag, meaning an unprivileged user cannot mount an
`ntfs3` image inside a user namespace to trigger this. It requires the
filesystem to be already mounted by the system (e.g., via admin or
auto-mounting).
* **Malicious Filesystem / Peripheral Trigger:** False. The bug is a logical
flaw in the syscall handling of the filesystem driver. It does not require a
maliciously crafted filesystem image or a malicious USB device to exploit; it
works perfectly on a completely normal, benign `ntfs3` filesystem.
* **Remote / Network / VM Triggers:** False. The bug is triggered via local
system calls and is not exposed to network traffic or virtualization boundaries.]
|