/
githubmirror
/
strace
Обзор
Документация
Войти
/
githubmirror
/
strace
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
tests/ioctl_fs_x.c
257 строк
7 KB
Dmitry V. Levin
Update copyright headers
15 июн 2026, 11:00
15 июн 2026, 11:00
726d2e4
Код
Авторство
О чём код?
/* * Check decoding of linux/fs.h 'X' ioctl commands. * * Copyright (c) 2020-2026 The strace developers. * All rights reserved. * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "tests.h" #include <linux/fs.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> #include "test_fs_xflags.h" static const char *errstr; static int do_ioctl(kernel_ulong_t cmd, kernel_ulong_t arg) { int rc = ioctl(-1, cmd, arg); errstr = sprintrc(rc); #ifdef INJECT_RETVAL if (rc != INJECT_RETVAL) error_msg_and_fail("Return value [%d] does not match" " expectations [%d]", rc, INJECT_RETVAL); static char inj_errstr[4096]; snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr); errstr = inj_errstr; #endif return rc; } static int do_ioctl_ptr(kernel_ulong_t cmd, const void *arg) { return do_ioctl(cmd, (uintptr_t) arg); } #ifdef INJECT_RETVAL static void skip_ioctls(int argc, const char *argv[]) { if (argc < 2) error_msg_and_fail("Usage: %s NUM_SKIP", argv[0]); unsigned long num_skip = strtoul(argv[1], NULL, 0); for (size_t i = 0; i < num_skip; ++i) { int rc = ioctl(-1, FIFREEZE, 0); printf("ioctl(-1, %s) = %s%s\n", XLAT_STR(FIFREEZE), sprintrc(rc), rc == INJECT_RETVAL ? " (INJECTED)" : ""); if (rc == INJECT_RETVAL) return; } error_msg_and_fail("Issued %lu ioctl syscalls but failed" " to detect an injected return code %d", num_skip, INJECT_RETVAL); } #endif /* INJECT_RETVAL */ int main(int argc, const char *argv[]) { #ifdef INJECT_RETVAL skip_ioctls(argc, argv); #endif static const struct { uint32_t cmd; const char *str; bool has_arg; } simple_cmds[] = { { ARG_STR(FIFREEZE), false }, { ARG_STR(FITHAW), false }, { _IO('X', 0xff), "_IOC(_IOC_NONE, 0x58, 0xff, 0)", true }, }; for (size_t i = 0; i < ARRAY_SIZE(simple_cmds); ++i) { do_ioctl(simple_cmds[i].cmd, 0); if (simple_cmds[i].has_arg) { printf("ioctl(-1, " XLAT_FMT ", 0) = %s\n", XLAT_SEL(simple_cmds[i].cmd, simple_cmds[i].str), errstr); } else { printf("ioctl(-1, " XLAT_FMT ") = %s\n", XLAT_SEL(simple_cmds[i].cmd, simple_cmds[i].str), errstr); } static const unsigned long arg = (unsigned long) 0xbadc0deddeadc0deULL; do_ioctl(simple_cmds[i].cmd, arg); if (simple_cmds[i].has_arg) { printf("ioctl(-1, " XLAT_FMT ", %#lx) = %s\n", XLAT_SEL(simple_cmds[i].cmd, simple_cmds[i].str), arg, errstr); } else { printf("ioctl(-1, " XLAT_FMT ") = %s\n", XLAT_SEL(simple_cmds[i].cmd, simple_cmds[i].str), errstr); } } static const struct strval32 null_arg_cmds[] = { { ARG_STR(FITRIM) }, { ARG_STR(FS_IOC_FSSETXATTR) }, { ARG_STR(FS_IOC_FSGETXATTR) }, { ARG_STR(FS_IOC_SHUTDOWN) }, }; for (size_t i = 0; i < ARRAY_SIZE(null_arg_cmds); ++i) { do_ioctl(null_arg_cmds[i].val, 0); printf("ioctl(-1, " XLAT_FMT ", NULL) = %s\n", XLAT_SEL(null_arg_cmds[i].val, null_arg_cmds[i].str), errstr); } TAIL_ALLOC_OBJECT_CONST_PTR(struct fstrim_range, p_range); do_ioctl_ptr(FITRIM, (char *) p_range + 1); printf("ioctl(-1, %s, %p) = %s\n", XLAT_STR(FITRIM), (char *) p_range + 1, errstr); p_range->start = (typeof(p_range->start)) 0xdeadbeefcafef00dULL; p_range->len = (typeof(p_range->len)) 0xfacefeedbabec0deULL; p_range->minlen = (typeof(p_range->minlen)) 0xbadc0deddeadc0deULL; do_ioctl_ptr(FITRIM, p_range); printf("ioctl(-1, %s, {start=%#jx, len=%ju, minlen=%ju}) = %s\n", XLAT_STR(FITRIM), (uintmax_t) p_range->start, (uintmax_t) p_range->len, (uintmax_t) p_range->minlen, errstr); /* FS_IOC_FSSETXATTR */ TAIL_ALLOC_OBJECT_CONST_PTR(struct fsxattr, p_fsxattr); do_ioctl_ptr(FS_IOC_FSSETXATTR, (char *) p_fsxattr + 1); printf("ioctl(-1, %s, %p) = %s\n", XLAT_STR(FS_IOC_FSSETXATTR), (char *) p_fsxattr + 1, errstr); p_fsxattr->fsx_xflags = VALID_FS_XFLAGS; p_fsxattr->fsx_extsize = 0xdeadbeefU; p_fsxattr->fsx_projid = 0xcafef00dU; p_fsxattr->fsx_cowextsize = 0xbabec0deU; do_ioctl_ptr(FS_IOC_FSSETXATTR, p_fsxattr); printf("ioctl(-1, %s, {fsx_xflags=%s, fsx_extsize=%u, fsx_projid=%#x" ", fsx_cowextsize=%u}) = %s\n", XLAT_STR(FS_IOC_FSSETXATTR), XLAT_KNOWN(VALID_FS_XFLAGS, VALID_FS_XFLAGS_STR), p_fsxattr->fsx_extsize, p_fsxattr->fsx_projid, p_fsxattr->fsx_cowextsize, errstr); p_fsxattr->fsx_xflags = ~p_fsxattr->fsx_xflags; do_ioctl_ptr(FS_IOC_FSSETXATTR, p_fsxattr); printf("ioctl(-1, %s, {fsx_xflags=%s, fsx_extsize=%u, fsx_projid=%#x" ", fsx_cowextsize=%u}) = %s\n", XLAT_STR(FS_IOC_FSSETXATTR), XLAT_UNKNOWN(INVALID_FS_XFLAGS, INVALID_FS_XFLAGS_STR), p_fsxattr->fsx_extsize, p_fsxattr->fsx_projid, p_fsxattr->fsx_cowextsize, errstr); /* FS_IOC_FSGETXATTR */ do_ioctl_ptr(FS_IOC_FSGETXATTR, (char *) p_fsxattr + 1); printf("ioctl(-1, %s, %p) = %s\n", XLAT_STR(FS_IOC_FSGETXATTR), (char *) p_fsxattr + 1, errstr); p_fsxattr->fsx_xflags = VALID_FS_XFLAGS; p_fsxattr->fsx_nextents = 0xfacefeedU; if (do_ioctl_ptr(FS_IOC_FSGETXATTR, p_fsxattr) < 0) { printf("ioctl(-1, %s, %p) = %s\n", XLAT_STR(FS_IOC_FSGETXATTR), p_fsxattr, errstr); } else { printf("ioctl(-1, %s, {fsx_xflags=%s, fsx_extsize=%u" ", fsx_nextents=%u, fsx_projid=%#x" ", fsx_cowextsize=%u}) = %s\n", XLAT_STR(FS_IOC_FSGETXATTR), XLAT_KNOWN(VALID_FS_XFLAGS, VALID_FS_XFLAGS_STR), p_fsxattr->fsx_extsize, p_fsxattr->fsx_nextents, p_fsxattr->fsx_projid, p_fsxattr->fsx_cowextsize, errstr); } p_fsxattr->fsx_xflags = ~p_fsxattr->fsx_xflags; if (do_ioctl_ptr(FS_IOC_FSGETXATTR, p_fsxattr) < 0) { printf("ioctl(-1, %s, %p) = %s\n", XLAT_STR(FS_IOC_FSGETXATTR), p_fsxattr, errstr); } else { printf("ioctl(-1, %s, {fsx_xflags=%s, fsx_extsize=%u" ", fsx_nextents=%u, fsx_projid=%#x" ", fsx_cowextsize=%u}) = %s\n", XLAT_STR(FS_IOC_FSGETXATTR), XLAT_UNKNOWN(INVALID_FS_XFLAGS, INVALID_FS_XFLAGS_STR), p_fsxattr->fsx_extsize, p_fsxattr->fsx_nextents, p_fsxattr->fsx_projid, p_fsxattr->fsx_cowextsize, errstr); } /* FS_IOC_SHUTDOWN */ TAIL_ALLOC_OBJECT_CONST_PTR(uint32_t, p_shutdown); do_ioctl_ptr(FS_IOC_SHUTDOWN, (char *) p_shutdown + 1); printf("ioctl(-1, %s, %p) = %s\n", XLAT_STR(FS_IOC_SHUTDOWN), (char *) p_shutdown + 1, errstr); static const struct strval32 shutdown_flags[] = { { ARG_STR(FS_SHUTDOWN_FLAGS_DEFAULT) }, { ARG_STR(FS_SHUTDOWN_FLAGS_LOGFLUSH) }, { ARG_STR(FS_SHUTDOWN_FLAGS_NOLOGFLUSH) }, }; for (size_t i = 0; i < ARRAY_SIZE(shutdown_flags); ++i) { *p_shutdown = shutdown_flags[i].val; do_ioctl_ptr(FS_IOC_SHUTDOWN, p_shutdown); printf("ioctl(-1, %s, [" XLAT_FMT "]) = %s\n", XLAT_STR(FS_IOC_SHUTDOWN), XLAT_SEL(shutdown_flags[i].val, shutdown_flags[i].str), errstr); } #define INVALID_FS_SHUTDOWN_FLAG 0x3 *p_shutdown = INVALID_FS_SHUTDOWN_FLAG; do_ioctl_ptr(FS_IOC_SHUTDOWN, p_shutdown); printf("ioctl(-1, %s, [%s]) = %s\n", XLAT_STR(FS_IOC_SHUTDOWN), XLAT_UNKNOWN(INVALID_FS_SHUTDOWN_FLAG, "FS_SHUTDOWN_FLAGS_???"), errstr); puts("+++ exited with 0 +++"); return 0; }