|  | /* | 
|  | * Check decoding of fanotify_mark syscall. | 
|  | * | 
|  | * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org> | 
|  | * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com> | 
|  | * Copyright (c) 2015-2018 The strace developers. | 
|  | * All rights reserved. | 
|  | * | 
|  | * Redistribution and use in source and binary forms, with or without | 
|  | * modification, are permitted provided that the following conditions | 
|  | * are met: | 
|  | * 1. Redistributions of source code must retain the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer. | 
|  | * 2. Redistributions in binary form must reproduce the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer in the | 
|  | *    documentation and/or other materials provided with the distribution. | 
|  | * 3. The name of the author may not be used to endorse or promote products | 
|  | *    derived from this software without specific prior written permission. | 
|  | * | 
|  | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 
|  | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
|  | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
|  | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
|  | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
|  | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|  | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|  | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
|  | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | */ | 
|  |  | 
|  | #include "tests.h" | 
|  |  | 
|  | #include <asm/unistd.h> | 
|  |  | 
|  | #if defined HAVE_SYS_FANOTIFY_H && defined HAVE_FANOTIFY_MARK && \ | 
|  | defined __NR_fanotify_mark | 
|  |  | 
|  | # include <limits.h> | 
|  | # include <stdio.h> | 
|  | # include <unistd.h> | 
|  | # include <sys/fanotify.h> | 
|  |  | 
|  | #if XLAT_RAW | 
|  | # define str_fan_mark_add	"0x1" | 
|  | # define str_fan_modify_ondir	"0x40000002" | 
|  | # define str_at_fdcwd		"-100" | 
|  | #elif XLAT_VERBOSE | 
|  | # define str_fan_mark_add	"0x1 /* FAN_MARK_ADD */" | 
|  | # define str_fan_modify_ondir	"0x40000002 /* FAN_MODIFY|FAN_ONDIR */" | 
|  | # define str_at_fdcwd		"-100 /* AT_FDCWD */" | 
|  | #else | 
|  | # define str_fan_mark_add	"FAN_MARK_ADD" | 
|  | # define str_fan_modify_ondir	"FAN_MODIFY|FAN_ONDIR" | 
|  | # define str_at_fdcwd		"AT_FDCWD" | 
|  | #endif | 
|  |  | 
|  | /* Performs fanotify_mark call via the syscall interface. */ | 
|  | static void | 
|  | do_call(kernel_ulong_t fd, kernel_ulong_t flags, const char *flags_str, | 
|  | uint64_t mask, const char *mask_str, kernel_ulong_t dirfd, | 
|  | const char *dirfd_str, kernel_ulong_t path, const char *path_str) | 
|  | { | 
|  | long rc; | 
|  |  | 
|  | rc = syscall(__NR_fanotify_mark, fd, flags, | 
|  | # if (LONG_MAX > INT_MAX) \ | 
|  | || (defined __x86_64__ && defined __ILP32__) \ | 
|  | || defined LINUX_MIPSN32 | 
|  | mask, | 
|  | # else | 
|  | /* arch/parisc/kernel/sys_parisc32.c, commit ab8a261b */ | 
|  | #  ifdef HPPA | 
|  | LL_VAL_TO_PAIR((mask << 32) | (mask >> 32)), | 
|  | #  else | 
|  | LL_VAL_TO_PAIR(mask), | 
|  | #  endif | 
|  | # endif | 
|  | dirfd, path); | 
|  |  | 
|  | printf("fanotify_mark(%d, %s, %s, %s, %s) = %s\n", | 
|  | (int) fd, flags_str, mask_str, dirfd_str, path_str, | 
|  | sprintrc(rc)); | 
|  | } | 
|  |  | 
|  | struct strval { | 
|  | kernel_ulong_t val; | 
|  | const char *str; | 
|  | }; | 
|  |  | 
|  | struct strval64 { | 
|  | uint64_t val; | 
|  | const char *str; | 
|  | }; | 
|  |  | 
|  | #define STR16 "0123456789abcdef" | 
|  | #define STR64 STR16 STR16 STR16 STR16 | 
|  |  | 
|  | int | 
|  | main(void) | 
|  | { | 
|  | enum { | 
|  | PATH1_SIZE = 64, | 
|  | }; | 
|  |  | 
|  | static const kernel_ulong_t fds[] = { | 
|  | (kernel_ulong_t) 0xdeadfeed12345678ULL, | 
|  | F8ILL_KULONG_MASK, | 
|  | (kernel_ulong_t) 0xdeb0d1edffffffffULL, | 
|  | }; | 
|  | static const struct strval flags[] = { | 
|  | { F8ILL_KULONG_MASK, "0" }, | 
|  | { (kernel_ulong_t) 0xdec0deddefaced00ULL, | 
|  | "0xefaced00" | 
|  | #if !XLAT_RAW | 
|  | " /* FAN_MARK_??? */" | 
|  | #endif | 
|  | }, | 
|  | { (kernel_ulong_t) 0xda7a105700000040ULL, | 
|  | #if XLAT_RAW | 
|  | "0x40" | 
|  | #elif XLAT_VERBOSE | 
|  | "0x40 /* FAN_MARK_IGNORED_SURV_MODIFY */" | 
|  | #else | 
|  | "FAN_MARK_IGNORED_SURV_MODIFY" | 
|  | #endif | 
|  | }, | 
|  | { (kernel_ulong_t) 0xbadc0deddeadfeedULL, | 
|  | #if XLAT_RAW || XLAT_VERBOSE | 
|  | "0xdeadfeed" | 
|  | #endif | 
|  | #if XLAT_VERBOSE | 
|  | " /* " | 
|  | #endif | 
|  | #if !XLAT_RAW | 
|  | "FAN_MARK_ADD|FAN_MARK_DONT_FOLLOW|FAN_MARK_ONLYDIR|" | 
|  | "FAN_MARK_IGNORED_MASK|FAN_MARK_IGNORED_SURV_MODIFY|" | 
|  | "FAN_MARK_FLUSH|0xdeadfe00" | 
|  | #endif | 
|  | #if XLAT_VERBOSE | 
|  | " */" | 
|  | #endif | 
|  | }, | 
|  | }; | 
|  | static const struct strval64 masks[] = { | 
|  | { ARG_ULL_STR(0) }, | 
|  | { 0xdeadfeedfacebeefULL, | 
|  | #if XLAT_RAW || XLAT_VERBOSE | 
|  | "0xdeadfeedfacebeef" | 
|  | #endif | 
|  | #if XLAT_VERBOSE | 
|  | " /* " | 
|  | #endif | 
|  | #if !XLAT_RAW | 
|  | "FAN_ACCESS|FAN_MODIFY|FAN_CLOSE_WRITE|FAN_OPEN|" | 
|  | "FAN_ACCESS_PERM|FAN_ONDIR|FAN_EVENT_ON_CHILD|" | 
|  | "0xdeadfeedb2ccbec4" | 
|  | #endif | 
|  | #if XLAT_VERBOSE | 
|  | " */" | 
|  | #endif | 
|  | }, | 
|  | { ARG_ULL_STR(0xffffffffb7fcbfc4) | 
|  | #if !XLAT_RAW | 
|  | " /* FAN_??? */" | 
|  | #endif | 
|  | }, | 
|  | }; | 
|  | static const struct strval dirfds[] = { | 
|  | { (kernel_ulong_t) 0xfacefeed00000001ULL, "1" }, | 
|  | { (kernel_ulong_t) 0xdec0ded0ffffffffULL, | 
|  | #if XLAT_RAW | 
|  | "-1" | 
|  | #elif XLAT_VERBOSE | 
|  | "-1 /* FAN_NOFD */" | 
|  | #else | 
|  | "FAN_NOFD" | 
|  | #endif | 
|  | }, | 
|  | { (kernel_ulong_t) 0xbadfacedffffff9cULL, str_at_fdcwd }, | 
|  | { (kernel_ulong_t) 0xdefaced1beeff00dULL, "-1091571699" }, | 
|  | }; | 
|  | static const char str64[] = STR64; | 
|  |  | 
|  | static char bogus_path1_addr[sizeof("0x") + sizeof(void *) * 2]; | 
|  | static char bogus_path1_after_addr[sizeof("0x") + sizeof(void *) * 2]; | 
|  |  | 
|  | char *bogus_path1 = tail_memdup(str64, PATH1_SIZE); | 
|  | char *bogus_path2 = tail_memdup(str64, sizeof(str64)); | 
|  |  | 
|  | struct strval paths[] = { | 
|  | { (kernel_ulong_t) 0, "NULL" }, | 
|  | { (kernel_ulong_t) (uintptr_t) (bogus_path1 + PATH1_SIZE), | 
|  | bogus_path1_after_addr }, | 
|  | { (kernel_ulong_t) (uintptr_t) bogus_path1, bogus_path1_addr }, | 
|  | { (kernel_ulong_t) (uintptr_t) bogus_path2, "\"" STR64 "\"" }, | 
|  | }; | 
|  |  | 
|  | unsigned int i; | 
|  | unsigned int j; | 
|  | unsigned int k; | 
|  | unsigned int l; | 
|  | unsigned int m; | 
|  | int rc; | 
|  |  | 
|  |  | 
|  | snprintf(bogus_path1_addr, sizeof(bogus_path1_addr), "%p", bogus_path1); | 
|  | snprintf(bogus_path1_after_addr, sizeof(bogus_path1_after_addr), "%p", | 
|  | bogus_path1 + PATH1_SIZE); | 
|  |  | 
|  | rc = fanotify_mark(-1, FAN_MARK_ADD, FAN_MODIFY | FAN_ONDIR, | 
|  | -100, "."); | 
|  | printf("fanotify_mark(-1, %s, %s, %s, \".\") = %s\n", | 
|  | str_fan_mark_add, str_fan_modify_ondir, str_at_fdcwd, | 
|  | sprintrc(rc)); | 
|  |  | 
|  | for (i = 0; i < ARRAY_SIZE(fds); i++) { | 
|  | for (j = 0; j < ARRAY_SIZE(flags); j++) { | 
|  | for (k = 0; k < ARRAY_SIZE(masks); k++) { | 
|  | for (l = 0; l < ARRAY_SIZE(dirfds); l++) { | 
|  | for (m = 0; m < ARRAY_SIZE(paths); m++) | 
|  | do_call(fds[i], | 
|  | flags[j].val, | 
|  | flags[j].str, | 
|  | masks[k].val, | 
|  | masks[k].str, | 
|  | dirfds[l].val, | 
|  | dirfds[l].str, | 
|  | paths[m].val, | 
|  | paths[m].str); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | puts("+++ exited with 0 +++"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | #else | 
|  |  | 
|  | SKIP_MAIN_UNDEFINED("HAVE_SYS_FANOTIFY_H && HAVE_FANOTIFY_MARK && " | 
|  | "__NR_fanotify_mark") | 
|  |  | 
|  | #endif |