/* * Check decoding of openat2 syscall. * * Copyright (c) 2020-2021 The strace developers. * All rights reserved. * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "tests.h" #include "scno.h" #include #include #include #include #include #include #include #ifndef VERBOSE # define VERBOSE 0 #endif #ifndef FD0_PATH # define FD0_PATH "" #else # define YFLAG #endif #ifndef SKIP_IF_PROC_IS_UNAVAILABLE # define SKIP_IF_PROC_IS_UNAVAILABLE #endif #ifdef YFLAG # define AT_FDCWD_FMT "<%s>" # define AT_FDCWD_ARG(arg) arg, #else # define AT_FDCWD_FMT # define AT_FDCWD_ARG(arg) #endif static const char sample[] = "openat2.sample"; int main(void) { SKIP_IF_PROC_IS_UNAVAILABLE; #ifdef YFLAG char *cwd = get_fd_path(get_dir_fd(".")); #endif long rc; const char *rcstr; struct open_how *how = tail_alloc(sizeof(*how)); struct open_how *how_big = tail_alloc(sizeof(*how_big) + 8); rc = syscall(__NR_openat2, 0, NULL, NULL, (kernel_ulong_t) 0xdeadc0debadc0dedULL); printf("openat2(0" FD0_PATH ", NULL, NULL, %llu) = %s\n", (unsigned long long) (kernel_ulong_t) 0xdeadc0debadc0dedULL, sprintrc(rc)); rc = syscall(__NR_openat2, -100, "", how + 1, sizeof(*how)); printf("openat2(%s" AT_FDCWD_FMT ", \"\", %p, %zu) = %s\n", XLAT_KNOWN(-100, "AT_FDCWD"), AT_FDCWD_ARG(cwd) how + 1, sizeof(*how), sprintrc(rc)); rc = syscall(__NR_openat2, -1, sample, how, 11); printf("openat2(-1, \"%s\", %p, 11) = %s\n", sample, how, sprintrc(rc)); static struct strval64 flags[] = { { ARG_STR(O_RDONLY|O_EXCL) }, { ARG_STR(O_WRONLY|O_CREAT) }, { ARG_STR(O_RDWR|O_LARGEFILE) }, { ARG_STR(O_ACCMODE|O_TMPFILE) }, { ARG_ULL_STR(O_RDONLY|0xdeadface80000000) }, }; static uint64_t modes[] = { 0, 0777, 0xbadc0dedfacebeefULL }; static struct strval64 resolve[] = { { 0, NULL }, { ARG_STR(RESOLVE_NO_XDEV) }, { ARG_ULL_STR(RESOLVE_NO_XDEV|RESOLVE_IN_ROOT|RESOLVE_CACHED|0xfeedfacedcaffec0) }, { 0xdec0dedbeeffffc0, NULL }, }; const size_t iters = MAX(MAX(ARRAY_SIZE(flags), ARRAY_SIZE(modes)), ARRAY_SIZE(resolve)); for (size_t i = 0; i < iters * 4; i++) { how->flags = flags[i % ARRAY_SIZE(flags)].val; how->mode = modes[i % ARRAY_SIZE(modes)]; how->resolve = resolve[i % ARRAY_SIZE(resolve)].val; fill_memory(how_big + 1, 8); memcpy(how_big, how, sizeof(*how)); for (size_t j = 0; j < 4; j++) { rc = syscall(__NR_openat2, -1, sample, j > 1 ? how_big : how, j ? sizeof(*how) + 8 : sizeof(*how)); rcstr = sprintrc(rc); printf("openat2(-1, \"%s\", {flags=%s", sample, sprintxlat(flags[i % ARRAY_SIZE(flags)].str, flags[i % ARRAY_SIZE(flags)].val, NULL)); if (how->mode || (i % ARRAY_SIZE(flags) == 1) || (i % ARRAY_SIZE(flags) == 3)) { printf(", mode=%#03" PRIo64, modes[i % ARRAY_SIZE(modes)]); } printf(", resolve=%s", sprintxlat(resolve[i % ARRAY_SIZE(resolve)].str, resolve[i % ARRAY_SIZE(resolve)].val, resolve[i % ARRAY_SIZE(resolve)].val ? "RESOLVE_???" : NULL)); if (j == 1) printf(", ???"); if (j == 2) { printf(", /* bytes %zu..%zu */ \"\\x80\\x81" "\\x82\\x83\\x84\\x85\\x86\\x87\"", sizeof(*how), sizeof(*how) + 7); } printf("}, %zu) = %s\n", j ? sizeof(*how) + 8 : sizeof(*how), rcstr); if (j == 2) memset(how_big + 1, 0, 8); } } how->flags = O_RDONLY | O_NOCTTY; how->mode = 0; how->resolve = 0; rc = syscall(__NR_openat2, -100, "/dev/full", how, sizeof(*how)); printf("openat2(%s" AT_FDCWD_FMT ", \"/dev/full\"" ", {flags=%s, resolve=0}, %zu) = %s%s\n", XLAT_KNOWN(-100, "AT_FDCWD"), AT_FDCWD_ARG(cwd) XLAT_STR(O_RDONLY|O_NOCTTY), sizeof(*how), sprintrc(rc), rc >= 0 ? FD0_PATH : ""); puts("+++ exited with 0 +++"); return 0; }