| /* |
| * Check decoding of fanotify_mark syscall. |
| * |
| * Copyright (c) 2015-2016 Dmitry V. Levin <[email protected]> |
| * Copyright (c) 2016 Eugene Syromyatnikov <[email protected]> |
| * 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 |