[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <03d7a29c7e1a8c5741680ea9bc83b4fb40358a25.camel@elektrobit.com>
Date: Tue, 12 Mar 2024 07:10:27 +0000
From: Weiß, Simone <Simone.Weiss@...ktrobit.com>
To: "miklos@...redi.hu" <miklos@...redi.hu>, "amir73il@...il.com"
<amir73il@...il.com>, "linux-unionfs@...r.kernel.org"
<linux-unionfs@...r.kernel.org>
CC: "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>
Subject: possible deadlock in ovl_llseek 27c1936af506
Dear Miklos and Amir,
For some experimentation, I have been running fuzzing campaigns and I
noticed a possible deadlock in ovl_llseek .
As there is a C reproducer, it could be bisected being introduced with:
commit 27c1936af5068b5367078a65df6a3d4de3e94e9a
Author: Miklos Szeredi <mszeredi@...hat.com>
Date: Mon Apr 12 12:00:37 2021 +0200
ovl: allow upperdir inside lowerdir
commit 708fa01597fa002599756bf56a96d0de1677375c upstream.
Commit 146d62e5a586 ("ovl: detect overlapping layers") made sure we don't
have overlapping layers, but it also broke the arguably valid use case of
mount -olowerdir=/,upperdir=/subdir,..
where upperdir overlaps lowerdir on the same filesystem. This has been
causing regressions.
Revert the check, but only for the specific case where upperdir and/or
workdir are subdirectories of lowerdir. Any other overlap (e.g. lowerdir
is subdirectory of upperdir, etc) case is crazy, so leave the check in
place for those.
Overlaps are detected at lookup time too, so reverting the mount time check
should be safe.
It was reproducible on v5.10.212 and a syz-crush check also found crashes on
v6.8-rc1.
The C reproducer is automatically generated by syzkaller and included below.
If you need any further information, just let me know.
Regards,
Simone
Log:
======================================================
WARNING: possible circular locking dependency detected
5.10.34-eb-corbos-standard-syzkaller #0 Not tainted
------------------------------------------------------
syz-executor175/7735 is trying to acquire lock:
ffff00000c54a0a0
(&ovl_i_lock_key[depth]){+.+.}-{3:3}, at: ovl_inode_lock
fs/overlayfs/overlayfs.h:362 [inline]
(&ovl_i_lock_key[depth]){+.+.}-{3:3}, at: ovl_llseek+0xec/0x194
fs/overlayfs/file.c:207
but task is already holding lock:
ffff00000c60eca0 (&sb->s_type->i_mutex_key#15/5){+.+.}-{3:3}, at:
inode_lock_nested include/linux/fs.h:809 [inline]
ffff00000c60eca0 (&sb->s_type->i_mutex_key#15/5){+.+.}-{3:3}, at:
lock_rename+0x10c/0x144 fs/namei.c:2772
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #2 (&sb->s_type->i_mutex_key#15/5
){+.+.}-{3:3}:
__lock_release kernel/locking/lockdep.c:5160 [inline]
lock_release+0x244/0x390 kernel/locking/lockdep.c:5464
up_write+0x4c/0x154 kernel/locking/rwsem.c:1609
inode_unlock include/linux/fs.h:779 [inline]
unlock_rename+0x28/0x60 fs/namei.c:2779
ovl_workdir_ok fs/overlayfs/super.c:915 [inline]
ovl_get_workdir fs/overlayfs/super.c:1405 [inline]
ovl_fill_super+0x62c/0x28d0 fs/overlayfs/super.c:1965
mount_nodev+0x70/0xf0 fs/super.c:1465
ovl_mount+0x3c/0x50 fs/overlayfs/super.c:2050
legacy_get_tree+0x34/0xb0 fs/fs_context.c:592
vfs_get_tree+0x34/0xe0 fs/super.c:1549
do_new_mount fs/namespace.c:2881 [inline]
path_mount+0xd50/0x1600 fs/namespace.c:3211
do_mount fs/namespace.c:3224 [inline]
__do_sys_mount fs/namespace.c:3432 [inline]
__se_sys_mount fs/namespace.c:3409 [inline]
__arm64_sys_mount+0x680/0x7d0 fs/namespace.c:3409
__invoke_syscall arch/arm64/kernel/syscall.c:36 [inline]
invoke_syscall arch/arm64/kernel/syscall.c:48 [inline]
el0_svc_common arch/arm64/kernel/syscall.c:158 [inline]
do_el0_svc+0xe0/0x340 arch/arm64/kernel/syscall.c:197
el0_svc+0x24/0x34 arch/arm64/kernel/entry-common.c:367
el0_sync_handler+0xec/0x210 arch/arm64/kernel/entry-common.c:383
el0_sync+0x17c/0x180 arch/arm64/kernel/entry.S:672
-> #1 (&type->s_vfs_rename_key){+.+.}-{3:3}:
lock_acquire+0x68/0x84 kernel/locking/lockdep.c:5417
__mutex_lock_common kernel/locking/mutex.c:959 [inline]
__mutex_lock+0x84/0x730 kernel/locking/mutex.c:1106
mutex_lock_nested+0x40/0x50 kernel/locking/mutex.c:1121
lock_rename+0x3c/0x144 fs/namei.c:2755
ovl_copy_up_workdir fs/overlayfs/copy_up.c:595 [inline]
ovl_do_copy_up fs/overlayfs/copy_up.c:746 [inline]
ovl_copy_up_one+0x434/0x12ec fs/overlayfs/copy_up.c:916
ovl_copy_up_flags+0x100/0x164 fs/overlayfs/copy_up.c:961
ovl_maybe_copy_up+0x104/0x14c fs/overlayfs/copy_up.c:993
ovl_open+0x4c/0x110 fs/overlayfs/file.c:154
do_dentry_open+0x2a0/0x5c0 fs/open.c:817
vfs_open+0x38/0x50 fs/open.c:931
do_open fs/namei.c:3243 [inline]
path_openat+0xc88/0x1050 fs/namei.c:3360
do_filp_open+0x8c/0x170 fs/namei.c:3387
do_sys_openat2+0xf4/0x240 fs/open.c:1172
__do_sys_openat2 fs/open.c:1227 [inline]
__se_sys_openat2 fs/open.c:1207 [inline]
__arm64_sys_openat2+0x304/0x410 fs/open.c:1207
__invoke_syscall arch/arm64/kernel/syscall.c:36 [inline]
invoke_syscall arch/arm64/kernel/syscall.c:48 [inline]
el0_svc_common arch/arm64/kernel/syscall.c:158 [inline]
do_el0_svc+0xe0/0x340 arch/arm64/kernel/syscall.c:197
el0_svc+0x24/0x34 arch/arm64/kernel/entry-common.c:367
el0_sync_handler+0xec/0x210 arch/arm64/kernel/entry-common.c:383
el0_sync+0x17c/0x180 arch/arm64/kernel/entry.S:672
-> #0 (&ovl_i_lock_key[depth]){+.+.}-{3:3}:
check_prev_add kernel/locking/lockdep.c:2869 [inline]
check_prevs_add kernel/locking/lockdep.c:2994 [inline]
validate_chain kernel/locking/lockdep.c:3609 [inline]
__lock_acquire+0x10ec/0x18a4 kernel/locking/lockdep.c:4834
lock_acquire.part.0+0xec/0x2e0 kernel/locking/lockdep.c:5444
lock_acquire+0x68/0x84 kernel/locking/lockdep.c:5417
__mutex_lock_common kernel/locking/mutex.c:959 [inline]
__mutex_lock+0x84/0x730 kernel/locking/mutex.c:1106
mutex_lock_nested+0x40/0x50 kernel/locking/mutex.c:1121
ovl_inode_lock fs/overlayfs/overlayfs.h:362 [inline]
ovl_llseek+0xec/0x194 fs/overlayfs/file.c:207
vfs_llseek+0x60/0x80 fs/read_write.c:300
ovl_copy_up_data+0x21c/0x390 fs/overlayfs/copy_up.c:199
ovl_copy_up_inode+0x258/0x2b4 fs/overlayfs/copy_up.c:507
ovl_copy_up_workdir fs/overlayfs/copy_up.c:609 [inline]
ovl_do_copy_up fs/overlayfs/copy_up.c:746 [inline]
ovl_copy_up_one+0x4cc/0x12ec fs/overlayfs/copy_up.c:916
ovl_copy_up_flags+0x100/0x164 fs/overlayfs/copy_up.c:961
ovl_maybe_copy_up+0x104/0x14c fs/overlayfs/copy_up.c:993
ovl_open+0x4c/0x110 fs/overlayfs/file.c:154
do_dentry_open+0x2a0/0x5c0 fs/open.c:817
vfs_open+0x38/0x50 fs/open.c:931
do_open fs/namei.c:3243 [inline]
path_openat+0xc88/0x1050 fs/namei.c:3360
do_filp_open+0x8c/0x170 fs/namei.c:3387
do_sys_openat2+0xf4/0x240 fs/open.c:1172
__do_sys_openat2 fs/open.c:1227 [inline]
__se_sys_openat2 fs/open.c:1207 [inline]
__arm64_sys_openat2+0x304/0x410 fs/open.c:1207
__invoke_syscall arch/arm64/kernel/syscall.c:36 [inline]
invoke_syscall arch/arm64/kernel/syscall.c:48 [inline]
el0_svc_common arch/arm64/kernel/syscall.c:158 [inline]
do_el0_svc+0xe0/0x340 arch/arm64/kernel/syscall.c:197
el0_svc+0x24/0x34 arch/arm64/kernel/entry-common.c:367
el0_sync_handler+0xec/0x210 arch/arm64/kernel/entry-common.c:383
el0_sync+0x17c/0x180 arch/arm64/kernel/entry.S:672
other info that might help us debug this:
Chain exists of:
&ovl_i_lock_key[depth] --> &type->s_vfs_rename_key --> &sb->s_type-
>i_mutex_key#15/5
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&sb->s_type->i_mutex_key#15/5);
lock(&type->s_vfs_rename_key);
lock(&sb->s_type->i_mutex_key#15/5);
lock(&ovl_i_lock_key[depth]);
*** DEADLOCK ***
5 locks held by syz-executor175/7735:
#0: ffff000005302438 (sb_writers#9){.+.+}-{0:0}, at: __sb_start_write
include/linux/fs.h:1594 [inline]
#0: ffff000005302438 (sb_writers#9){.+.+}-{0:0}, at: sb_start_write
include/linux/fs.h:1664 [inline]
#0: ffff000005302438 (sb_writers#9){.+.+}-{0:0}, at: mnt_want_write+0x24/0x80
fs/namespace.c:354
#1: ffff00000c54bcc0 (&ovl_i_lock_key[depth]#2){+.+.}-{3:3}, at:
ovl_inode_lock_interruptible fs/overlayfs/overlayfs.h:367 [inline]
#1: ffff00000c54bcc0 (&ovl_i_lock_key[depth]#2){+.+.}-{3:3}, at:
ovl_copy_up_start+0x34/0x160 fs/overlayfs/util.c:533
#2: ffff000005302720 (&type->s_vfs_rename_key){+.+.}-{3:3}, at:
lock_rename+0x3c/0x144 fs/namei.c:2755
#3: ffff000006711110 (&sb->s_type->i_mutex_key#15/1){+.+.}-{3:3}, at:
inode_lock_nested include/linux/fs.h:809 [inline]
#3: ffff000006711110 (&sb->s_type->i_mutex_key#15/1){+.+.}-{3:3}, at:
lock_rename+0xfc/0x144 fs/namei.c:2771
#4: ffff00000c60eca0 (&sb->s_type->i_mutex_key#15/5){+.+.}-{3:3}, at:
inode_lock_nested include/linux/fs.h:809 [inline]
#4: ffff00000c60eca0 (&sb->s_type->i_mutex_key#15/5){+.+.}-{3:3}, at:
lock_rename+0x10c/0x144 fs/namei.c:2772
stack backtrace:
CPU: 0 PID: 7735 Comm: syz-executor175 Not tainted 5.10.34-eb-corbos-standard-
syzkaller #0
Hardware name: linux,dummy-virt (DT)
Call trace:
dump_backtrace+0x0/0x2e0 arch/arm64/include/asm/atomic_ll_sc.h:222
show_stack+0x2c/0x40 arch/arm64/kernel/stacktrace.c:196
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x1d4/0x26c lib/dump_stack.c:118
print_circular_bug+0x1f8/0x200 kernel/locking/lockdep.c:1997
check_noncircular+0x100/0x114 kernel/locking/lockdep.c:2118
check_prev_add kernel/locking/lockdep.c:2869 [inline]
check_prevs_add kernel/locking/lockdep.c:2994 [inline]
validate_chain kernel/locking/lockdep.c:3609 [inline]
__lock_acquire+0x10ec/0x18a4 kernel/locking/lockdep.c:4834
lock_acquire.part.0+0xec/0x2e0 kernel/locking/lockdep.c:5444
lock_acquire+0x68/0x84 kernel/locking/lockdep.c:5417
__mutex_lock_common kernel/locking/mutex.c:959 [inline]
__mutex_lock+0x84/0x730 kernel/locking/mutex.c:1106
mutex_lock_nested+0x40/0x50 kernel/locking/mutex.c:1121
ovl_inode_lock fs/overlayfs/overlayfs.h:362 [inline]
ovl_llseek+0xec/0x194 fs/overlayfs/file.c:207
vfs_llseek+0x60/0x80 fs/read_write.c:300
ovl_copy_up_data+0x21c/0x390 fs/overlayfs/copy_up.c:199
ovl_copy_up_inode+0x258/0x2b4 fs/overlayfs/copy_up.c:507
ovl_copy_up_workdir fs/overlayfs/copy_up.c:609 [inline]
ovl_do_copy_up fs/overlayfs/copy_up.c:746 [inline]
ovl_copy_up_one+0x4cc/0x12ec fs/overlayfs/copy_up.c:916
ovl_copy_up_flags+0x100/0x164 fs/overlayfs/copy_up.c:961
ovl_maybe_copy_up+0x104/0x14c fs/overlayfs/copy_up.c:993
ovl_open+0x4c/0x110 fs/overlayfs/file.c:154
do_dentry_open+0x2a0/0x5c0 fs/open.c:817
vfs_open+0x38/0x50 fs/open.c:931
do_open fs/namei.c:3243 [inline]
path_openat+0xc88/0x1050 fs/namei.c:3360
do_filp_open+0x8c/0x170 fs/namei.c:3387
do_sys_openat2+0xf4/0x240 fs/open.c:1172
__do_sys_openat2 fs/open.c:1227 [inline]
__se_sys_openat2 fs/open.c:1207 [inline]
__arm64_sys_openat2+0x304/0x410 fs/open.c:1207
__invoke_syscall arch/arm64/kernel/syscall.c:36 [inline]
invoke_syscall arch/arm64/kernel/syscall.c:48 [inline]
el0_svc_common arch/arm64/kernel/syscall.c:158 [inline]
do_el0_svc+0xe0/0x340 arch/arm64/kernel/syscall.c:197
el0_svc+0x24/0x34 arch/arm64/kernel/entry-common.c:367
el0_sync_handler+0xec/0x210 arch/arm64/kernel/entry-common.c:383
el0_sync+0x17c/0x180 arch/arm64/kernel/entry.S:672
C Reproducer:
// https://None.appspot.com/bug?id=f10e9988ed129179c80858a403259185ef332f5d
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <linux/futex.h>
#ifndef __NR_chdir
#define __NR_chdir 49
#endif
#ifndef __NR_mkdirat
#define __NR_mkdirat 34
#endif
#ifndef __NR_mmap
#define __NR_mmap 222
#endif
#ifndef __NR_mount
#define __NR_mount 40
#endif
#ifndef __NR_openat
#define __NR_openat 56
#endif
#ifndef __NR_openat2
#define __NR_openat2 437
#endif
#ifndef __NR_write
#define __NR_write 64
#endif
static unsigned long long procid;
static void sleep_ms(uint64_t ms)
{
usleep(ms * 1000);
}
static uint64_t current_time_ms(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
exit(1);
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}
static void use_temporary_dir(void)
{
char tmpdir_template[] = "./syzkaller.XXXXXX";
char* tmpdir = mkdtemp(tmpdir_template);
if (!tmpdir)
exit(1);
if (chmod(tmpdir, 0777))
exit(1);
if (chdir(tmpdir))
exit(1);
}
static void thread_start(void* (*fn)(void*), void* arg)
{
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 128 << 10);
int i = 0;
for (; i < 100; i++) {
if (pthread_create(&th, &attr, fn, arg) == 0) {
pthread_attr_destroy(&attr);
return;
}
if (errno == EAGAIN) {
usleep(50);
continue;
}
break;
}
exit(1);
}
typedef struct {
int state;
} event_t;
static void event_init(event_t* ev)
{
ev->state = 0;
}
static void event_reset(event_t* ev)
{
ev->state = 0;
}
static void event_set(event_t* ev)
{
if (ev->state)
exit(1);
__atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
}
static void event_wait(event_t* ev)
{
while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
}
static int event_isset(event_t* ev)
{
return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
}
static int event_timedwait(event_t* ev, uint64_t timeout)
{
uint64_t start = current_time_ms();
uint64_t now = start;
for (;;) {
uint64_t remain = timeout - (now - start);
struct timespec ts;
ts.tv_sec = remain / 1000;
ts.tv_nsec = (remain % 1000) * 1000 * 1000;
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
return 1;
now = current_time_ms();
if (now - start > timeout)
return 0;
}
}
static bool write_file(const char* file, const char* what, ...)
{
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
int err = errno;
close(fd);
errno = err;
return false;
}
close(fd);
return true;
}
#define FS_IOC_SETFLAGS _IOW('f', 2, long)
static void remove_dir(const char* dir)
{
int iter = 0;
DIR* dp = 0;
retry:
while (umount2(dir, MNT_DETACH | UMOUNT_NOFOLLOW) == 0) {
}
dp = opendir(dir);
if (dp == NULL) {
if (errno == EMFILE) {
exit(1);
}
exit(1);
}
struct dirent* ep = 0;
while ((ep = readdir(dp))) {
if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
continue;
char filename[FILENAME_MAX];
snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
while (umount2(filename, MNT_DETACH | UMOUNT_NOFOLLOW) == 0) {
}
struct stat st;
if (lstat(filename, &st))
exit(1);
if (S_ISDIR(st.st_mode)) {
remove_dir(filename);
continue;
}
int i;
for (i = 0;; i++) {
if (unlink(filename) == 0)
break;
if (errno == EPERM) {
int fd = open(filename, O_RDONLY);
if (fd != -1) {
long flags = 0;
if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) {
}
close(fd);
continue;
}
}
if (errno == EROFS) {
break;
}
if (errno != EBUSY || i > 100)
exit(1);
if (umount2(filename, MNT_DETACH | UMOUNT_NOFOLLOW))
exit(1);
}
}
closedir(dp);
for (int i = 0;; i++) {
if (rmdir(dir) == 0)
break;
if (i < 100) {
if (errno == EPERM) {
int fd = open(dir, O_RDONLY);
if (fd != -1) {
long flags = 0;
if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) {
}
close(fd);
continue;
}
}
if (errno == EROFS) {
break;
}
if (errno == EBUSY) {
if (umount2(dir, MNT_DETACH | UMOUNT_NOFOLLOW))
exit(1);
continue;
}
if (errno == ENOTEMPTY) {
if (iter < 100) {
iter++;
goto retry;
}
}
}
exit(1);
}
}
static void kill_and_wait(int pid, int* status)
{
kill(-pid, SIGKILL);
kill(pid, SIGKILL);
for (int i = 0; i < 100; i++) {
if (waitpid(-1, status, WNOHANG | __WALL) == pid)
return;
usleep(1000);
}
DIR* dir = opendir("/sys/fs/fuse/connections");
if (dir) {
for (;;) {
struct dirent* ent = readdir(dir);
if (!ent)
break;
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
continue;
char abort[300];
snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort",
ent->d_name);
int fd = open(abort, O_WRONLY);
if (fd == -1) {
continue;
}
if (write(fd, abort, 1) < 0) {
}
close(fd);
}
closedir(dir);
} else {
}
while (waitpid(-1, status, __WALL) != pid) {
}
}
static void setup_test()
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
write_file("/proc/self/oom_score_adj", "1000");
if (symlink("/dev/binderfs", "./binderfs")) {
}
}
struct thread_t {
int created, call;
event_t ready, done;
};
static struct thread_t threads[16];
static void execute_call(int call);
static int running;
static void* thr(void* arg)
{
struct thread_t* th = (struct thread_t*)arg;
for (;;) {
event_wait(&th->ready);
event_reset(&th->ready);
execute_call(th->call);
__atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
event_set(&th->done);
}
return 0;
}
static void execute_one(void)
{
int i, call, thread;
for (call = 0; call < 12; call++) {
for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
th->created = 1;
event_init(&th->ready);
event_init(&th->done);
event_set(&th->done);
thread_start(thr, th);
}
if (!event_isset(&th->done))
continue;
event_reset(&th->done);
th->call = call;
__atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
event_set(&th->ready);
event_timedwait(&th->done, 50);
break;
}
}
for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
sleep_ms(1);
}
static void execute_one(void);
#define WAIT_FLAGS __WALL
static void loop(void)
{
int iter = 0;
for (;; iter++) {
char cwdbuf[32];
sprintf(cwdbuf, "./%d", iter);
if (mkdir(cwdbuf, 0777))
exit(1);
int pid = fork();
if (pid < 0)
exit(1);
if (pid == 0) {
if (chdir(cwdbuf))
exit(1);
setup_test();
execute_one();
exit(0);
}
int status = 0;
uint64_t start = current_time_ms();
for (;;) {
if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
break;
sleep_ms(1);
if (current_time_ms() - start < 5000)
continue;
kill_and_wait(pid, &status);
break;
}
remove_dir(cwdbuf);
}
}
uint64_t r[1] = {0xffffffffffffffff};
void execute_call(int call)
{
intptr_t res = 0;
switch (call) {
case 0:
memcpy((void*)0x20000000, "./file0\000", 8);
syscall(__NR_mkdirat, /*fd=*/0xffffff9c, /*path=*/0x20000000ul,
/*mode=*/0ul);
break;
case 1:
memcpy((void*)0x20000080, "./file0\000", 8);
memcpy((void*)0x200000c0, "ramfs\000", 6);
syscall(__NR_mount, /*src=*/0ul, /*dst=*/0x20000080ul,
/*type=*/0x200000c0ul, /*flags=*/0ul, /*data=*/0ul);
break;
case 2:
memcpy((void*)0x20000240, "./file0/file0\000", 14);
syscall(__NR_mkdirat, /*fd=*/0xffffff9c, /*path=*/0x20000240ul,
/*mode=*/0ul);
break;
case 3:
memcpy((void*)0x20000480, "./file0/file0\000", 14);
syscall(__NR_chdir, /*dir=*/0x20000480ul);
break;
case 4:
memcpy((void*)0x20000180, "./file0\000", 8);
syscall(__NR_mkdirat, /*fd=*/0xffffff9c, /*path=*/0x20000180ul,
/*mode=*/0ul);
break;
case 5:
memcpy((void*)0x20000080, "./file0/file1\000", 14);
res =
syscall(__NR_openat, /*fd=*/0xffffffffffffff9cul, /*file=*/0x20000080ul,
/*flags=O_CREAT|O_CLOEXEC|O_RDWR*/ 0x80042ul, /*mode=*/0ul);
if (res != -1)
r[0] = res;
break;
case 6:
syscall(__NR_write, /*fd=*/r[0], /*data=*/0x20000980ul, /*len=*/0x58ul);
break;
case 7:
memcpy((void*)0x200000c0, "./file0/file0\000", 14);
syscall(__NR_mkdirat, /*fd=*/0xffffff9c, /*path=*/0x200000c0ul,
/*mode=*/0ul);
break;
case 8:
memcpy((void*)0x20000280, "./file1\000", 8);
syscall(__NR_mkdirat, /*fd=*/0xffffff9c, /*path=*/0x20000280ul,
/*mode=*/0ul);
break;
case 9:
memcpy((void*)0x20000200, "./file0\000", 8);
memcpy((void*)0x200001c0, "overlay\000", 8);
memcpy((void*)0x20000340, "lowerdir", 8);
*(uint8_t*)0x20000348 = 0x3d;
memcpy((void*)0x20000349, "./file0", 7);
*(uint8_t*)0x20000350 = 0x2c;
memcpy((void*)0x20000351, "workdir", 7);
*(uint8_t*)0x20000358 = 0x3d;
memcpy((void*)0x20000359, "./file1", 7);
*(uint8_t*)0x20000360 = 0x2c;
memcpy((void*)0x20000361, "upperdir", 8);
*(uint8_t*)0x20000369 = 0x3d;
memcpy((void*)0x2000036a, "./file0/file0", 13);
*(uint8_t*)0x20000377 = 0x2c;
*(uint8_t*)0x20000378 = 0;
syscall(__NR_mount, /*src=*/0ul, /*dst=*/0x20000200ul,
/*type=*/0x200001c0ul, /*flags=*/0ul, /*opts=*/0x20000340ul);
break;
case 10:
memcpy((void*)0x20000200, "./file0\000", 8);
memcpy((void*)0x200001c0, "overlay\000", 8);
memcpy((void*)0x20000340, "lowerdir", 8);
*(uint8_t*)0x20000348 = 0x3d;
memcpy((void*)0x20000349, "./file0", 7);
*(uint8_t*)0x20000350 = 0x2c;
memcpy((void*)0x20000351, "workdir", 7);
*(uint8_t*)0x20000358 = 0x3d;
memcpy((void*)0x20000359, "./file1", 7);
*(uint8_t*)0x20000360 = 0x2c;
memcpy((void*)0x20000361, "upperdir", 8);
*(uint8_t*)0x20000369 = 0x3d;
memcpy((void*)0x2000036a, "./file0/file0", 13);
*(uint8_t*)0x20000377 = 0x2c;
*(uint8_t*)0x20000378 = 0;
syscall(__NR_mount, /*src=*/0ul, /*dst=*/0x20000200ul,
/*type=*/0x200001c0ul, /*flags=*/0ul, /*opts=*/0x20000340ul);
break;
case 11:
memcpy((void*)0x20000100, "./file0/file1\000", 14);
*(uint64_t*)0x20000140 = 0x80041;
*(uint64_t*)0x20000148 = 0;
*(uint64_t*)0x20000150 = 0;
syscall(__NR_openat2, /*fd=*/0xffffffffffffff9cul, /*file=*/0x20000100ul,
/*how=*/0x20000140ul, /*size=*/0x18ul);
break;
}
}
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1,
/*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul,
/*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1,
/*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1,
/*offset=*/0ul);
for (procid = 0; procid < 6; procid++) {
if (fork() == 0) {
use_temporary_dir();
loop();
}
}
sleep(1000000);
return 0;
}
Powered by blists - more mailing lists