From patchwork Sun May 19 05:25:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Bobrowski X-Patchwork-Id: 1101513 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mbobrowski.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mbobrowski-org.20150623.gappssmtp.com header.i=@mbobrowski-org.20150623.gappssmtp.com header.b="tXstX8PU"; dkim-atps=neutral Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4569VD0d1zz9s9N for ; Sun, 19 May 2019 15:25:56 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id A002C3EA51A for ; Sun, 19 May 2019 07:25:53 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-4.smtp.seeweb.it (in-4.smtp.seeweb.it [217.194.8.4]) by picard.linux.it (Postfix) with ESMTP id E50E33EA1BF for ; Sun, 19 May 2019 07:25:51 +0200 (CEST) Received: from mail-pg1-x541.google.com (mail-pg1-x541.google.com [IPv6:2607:f8b0:4864:20::541]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by in-4.smtp.seeweb.it (Postfix) with ESMTPS id 26EDA1000B33 for ; Sun, 19 May 2019 07:25:43 +0200 (CEST) Received: by mail-pg1-x541.google.com with SMTP id a3so5206618pgb.3 for ; Sat, 18 May 2019 22:25:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mbobrowski-org.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=DRsUh2bfDErqHpoew7jIB16N2eBQ3mV6DLXHHVd7upg=; b=tXstX8PUbOawlBZrlRpeDscskQxL6goFveRuDsMVsC4Kj5yg7TLROb61ez8n8O+AX7 YStvpRAurTXyTAtERyVE8BUsYr6YHXPasHN5rJrZ0j0N4JfgJD9E+YDpYdl0kqLeer/o CV2/4lbl8xrmpB0bIEjgzBJI9pE/ep8D5q/NcZW1LGGjQQ6tgLpYbW7viDmTHsSZINbZ BGTXwRuo24S2a9JJnU94COZtGDMvlPCfqVcQkzLxByBfgRlPtQjpGYbpHaxckIeLYs6x xp1EaYU/Vyuzv0lpDWoIe0SHrqe/AJSCIP77olajS/ofL66PPCCEfOV62uTJTdrcr/mw 5Ryw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=DRsUh2bfDErqHpoew7jIB16N2eBQ3mV6DLXHHVd7upg=; b=QtpdDPgRqwIrb23bftUkOnfAq9KdgpyM3H4nfXCifyBLsqE1CbRHWlGxm4MTGfc/Zq RHDy6MBY9lj4ET2g+c3LeE+ozSx87vsUglv6k54jkurEKul+LawFLom3ZMW6cS3AnOgD XP9Vus3JI6wJH6nnG6YXAnbiZ5mqeCkPxKLuFpBQXhFUOjKBWt9NTw6aXiLVh48GhlCO foSEzJ+ajVxptmZY+tusZ6tciDs4B3lNYDjtNBsvw/mJPViIlzLAWqsjQ7ud3jXM58Z+ y71j9XpeSxotA/Kyqr431XuBGDRw/nPFrB/YMQjRXeqNh/IZTRD5PiJuKoztrPKeHDG7 AWAA== X-Gm-Message-State: APjAAAVAK/xmUxLcfM7znEzhe0mcSbGzTqIF12INcQb1BbFf1quEtxIy 9Fx18cEuVmb66RIQ3J+5g5Un/PXqAw== X-Google-Smtp-Source: APXvYqytLU/389+bUvrB/Ha6zNR+wh1KImXy9yXem/oRvQ7JjIP2e92gUF+m+12+E9agx9TDjClIJg== X-Received: by 2002:a63:a55:: with SMTP id z21mr68197283pgk.440.1558243544310; Sat, 18 May 2019 22:25:44 -0700 (PDT) Received: from poseidon.Home (n114-74-156-190.sbr2.nsw.optusnet.com.au. [114.74.156.190]) by smtp.gmail.com with ESMTPSA id o7sm19709854pfp.168.2019.05.18.22.25.40 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 18 May 2019 22:25:43 -0700 (PDT) Date: Sun, 19 May 2019 15:25:35 +1000 From: Matthew Bobrowski To: ltp@lists.linux.it Message-ID: <5a1302c56c25f53395757727ec509169bdd6bc03.1558242368.git.mbobrowski@mbobrowski.org> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.11.3 (2019-02-01) X-Virus-Scanned: clamav-milter 0.99.2 at in-4.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.1 required=7.0 tests=DKIM_SIGNED,DKIM_VALID, SPF_HELO_NONE,SPF_NONE autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-4.smtp.seeweb.it Cc: jack@suse.cz Subject: [LTP] [PATCH v3 1/3] syscalls/fanotify13: new test to verify FAN_REPORT_FID functionality X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" A newly defined test file to validate the fanotify FAN_REPORT_FID functionality. A new line entry for this test file has been added within runtest/syscalls. Additionally, defined a helper function that can be used to obtain __kernel_fsid_t and file_handle objects. This helper will be used by test files related to verifying FAN_REPORT_FID. The name_to_handle_at() function is conditionally added to accommodate for builds on older distributions. Signed-off-by: Matthew Bobrowski Reviewed-by: Amir Goldstein --- configure.ac | 1 + runtest/syscalls | 1 + testcases/kernel/syscalls/fanotify/.gitignore | 1 + testcases/kernel/syscalls/fanotify/fanotify.h | 56 +++- .../kernel/syscalls/fanotify/fanotify13.c | 313 ++++++++++++++++++ 5 files changed, 369 insertions(+), 3 deletions(-) create mode 100644 testcases/kernel/syscalls/fanotify/fanotify13.c diff --git a/configure.ac b/configure.ac index 53ad784d7..ac4d85b0e 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,7 @@ AC_CHECK_FUNCS([ \ kcmp \ mkdirat \ mknodat \ + name_to_handle_at \ openat \ preadv \ preadv2 \ diff --git a/runtest/syscalls b/runtest/syscalls index 2b8ca719b..dfdc6cbf9 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -537,6 +537,7 @@ fanotify09 fanotify09 fanotify10 fanotify10 fanotify11 fanotify11 fanotify12 fanotify12 +fanotify13 fanotify13 ioperm01 ioperm01 ioperm02 ioperm02 diff --git a/testcases/kernel/syscalls/fanotify/.gitignore b/testcases/kernel/syscalls/fanotify/.gitignore index 4256b8cd3..16bdd99e5 100644 --- a/testcases/kernel/syscalls/fanotify/.gitignore +++ b/testcases/kernel/syscalls/fanotify/.gitignore @@ -10,4 +10,5 @@ /fanotify10 /fanotify11 /fanotify12 +/fanotify13 /fanotify_child diff --git a/testcases/kernel/syscalls/fanotify/fanotify.h b/testcases/kernel/syscalls/fanotify/fanotify.h index 14654b7c7..d6e259002 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify.h +++ b/testcases/kernel/syscalls/fanotify/fanotify.h @@ -29,6 +29,11 @@ #define __FANOTIFY_H__ #include "config.h" +#include +#include +#include +#include +#include #if defined(HAVE_SYS_FANOTIFY_H) @@ -57,9 +62,6 @@ static long fanotify_mark(int fd, unsigned int flags, uint64_t mask, #ifndef FAN_REPORT_TID #define FAN_REPORT_TID 0x00000100 #endif -#ifndef FAN_REPORT_FID -#define FAN_REPORT_FID 0x00000200 -#endif #ifndef FAN_MARK_INODE #define FAN_MARK_INODE 0 @@ -89,6 +91,54 @@ struct fanotify_mark_type { const char * name; }; +#ifndef FAN_REPORT_FID +#define FAN_REPORT_FID 0x00000200 + +struct fanotify_event_info_header { + uint8_t info_type; + uint8_t pad; + uint16_t len; +}; + +struct fanotify_event_info_fid { + struct fanotify_event_info_header hdr; + __kernel_fsid_t fsid; + unsigned char handle[0]; +}; + +/* + * Helper function used to obtain __kernel_fsid_t and file_handle objects + * for a given path. Used by test files correlated to FAN_REPORT_FID + * functionality. + */ +static inline void fanotify_get_fid(const char *path, __kernel_fsid_t *fsid, + struct file_handle *handle) +{ + int mount_id; + struct statfs stats; + + if (statfs(path, &stats) == -1) + tst_brk(TBROK | TERRNO, + "statfs(%s, ...) failed", path); + memcpy(fsid, &stats.f_fsid, sizeof(stats.f_fsid)); + +#ifdef HAVE_NAME_TO_HANDLE_AT + if (name_to_handle_at(AT_FDCWD, path, handle, &mount_id, 0) == -1) { + if (errno == EOPNOTSUPP) { + tst_brk(TCONF, + "filesystem %s does not support file handles", + tst_device->fs_type); + } + tst_brk(TBROK | TERRNO, + "name_to_handle_at(AT_FDCWD, %s, ...) failed", path); + } +#else + tst_brk(TCONF, "name_to_handle_at() is not implmented"); +#endif /* HAVE_NAME_TO_HANDLE_AT */ +} + +#endif + #define INIT_FANOTIFY_MARK_TYPE(t) \ { FAN_MARK_ ## t, "FAN_MARK_" #t } diff --git a/testcases/kernel/syscalls/fanotify/fanotify13.c b/testcases/kernel/syscalls/fanotify/fanotify13.c new file mode 100644 index 000000000..820f1390c --- /dev/null +++ b/testcases/kernel/syscalls/fanotify/fanotify13.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 Matthew Bobrowski. All Rights Reserved. + * + * Started by Matthew Bobrowski + * + * DESCRIPTION + * Validate that the values returned within an event when + * FAN_REPORT_FID is specified matches those that are obtained via + * explicit invocation to system calls statfs(2) and + * name_to_handle_at(2). + */ +#define _GNU_SOURCE +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "tst_test.h" +#include "fanotify.h" + +#if defined(HAVE_SYS_FANOTIFY_H) +#include + +#define PATH_LEN 128 +#define BUF_SIZE 256 +#define DIR_ONE "dir_one" +#define FILE_ONE "file_one" +#define FILE_TWO "file_two" +#define MOUNT_PATH "mntpoint" +#define EVENT_MAX ARRAY_SIZE(objects) +#define DIR_PATH_ONE MOUNT_PATH"/"DIR_ONE +#define FILE_PATH_ONE MOUNT_PATH"/"FILE_ONE +#define FILE_PATH_TWO MOUNT_PATH"/"FILE_TWO + +struct event_t { + unsigned long long expected_mask; + __kernel_fsid_t fsid; + struct file_handle handle; + char buf[MAX_HANDLE_SZ]; +}; + +static struct object_t { + const char *path; + int is_dir; +} objects[] = { + {FILE_PATH_ONE, 0}, + {FILE_PATH_TWO, 0}, + {DIR_PATH_ONE, 1} +}; + +static struct test_case_t { + struct fanotify_mark_type mark; + unsigned long long mask; +} test_cases[] = { + { + INIT_FANOTIFY_MARK_TYPE(INODE), + FAN_OPEN | FAN_CLOSE_NOWRITE + }, + { + INIT_FANOTIFY_MARK_TYPE(INODE), + FAN_OPEN | FAN_CLOSE_NOWRITE | FAN_ONDIR + }, + { + INIT_FANOTIFY_MARK_TYPE(MOUNT), + FAN_OPEN | FAN_CLOSE_NOWRITE + }, + { + INIT_FANOTIFY_MARK_TYPE(MOUNT), + FAN_OPEN | FAN_CLOSE_NOWRITE | FAN_ONDIR + }, + { + INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), + FAN_OPEN | FAN_CLOSE_NOWRITE + }, + { + INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), + FAN_OPEN | FAN_CLOSE_NOWRITE | FAN_ONDIR + } +}; + +static int fanotify_fd; +static char events_buf[BUF_SIZE]; +static struct event_t event_set[EVENT_MAX]; + +static void create_objects(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(objects); i++) { + if (objects[i].is_dir) + SAFE_MKDIR(objects[i].path, 0755); + else + SAFE_FILE_PRINTF(objects[i].path, "0"); + } +} + +static void get_object_stats(void) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(objects); i++) { + event_set[i].handle.handle_bytes = MAX_HANDLE_SZ; + fanotify_get_fid(objects[i].path, &event_set[i].fsid, + &event_set[i].handle); + } +} + +static void do_setup(void) +{ + int fd; + + /* Check for kernel fanotify support */ + fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY); + SAFE_CLOSE(fd); + + /* Create file and directory objects for testing */ + create_objects(); + + /* Get the filesystem fsid and file handle for each created object */ + get_object_stats(); +} + + +static int setup_marks(unsigned int fd, struct test_case_t *tc) +{ + unsigned int i; + struct fanotify_mark_type *mark = &tc->mark; + + for (i = 0; i < ARRAY_SIZE(objects); i++) { + if (fanotify_mark(fd, FAN_MARK_ADD | mark->flag, tc->mask, + AT_FDCWD, objects[i].path) == -1) { + if (errno == EINVAL && + mark->flag & FAN_MARK_FILESYSTEM) { + tst_res(TCONF, + "FAN_MARK_FILESYSTEM not supported by " + "kernel"); + return 1; + } else if (errno == ENODEV && + !event_set[i].fsid.val[0] && + !event_set[i].fsid.val[1]) { + tst_res(TCONF, + "FAN_REPORT_FID not supported on " + "filesystem type %s", + tst_device->fs_type); + return 1; + } + tst_brk(TBROK | TERRNO, + "fanotify_mark(%d, FAN_MARK_ADD, FAN_OPEN, " + "AT_FDCWD, %s) failed", + fanotify_fd, objects[i].path); + } + + /* Setup the expected mask for each generated event */ + event_set[i].expected_mask = tc->mask; + if (!objects[i].is_dir) + event_set[i].expected_mask &= ~FAN_ONDIR; + } + return 0; +} + +static void do_test(unsigned int number) +{ + unsigned int i; + int len, fds[ARRAY_SIZE(objects)]; + + struct file_handle *event_file_handle; + struct fanotify_event_metadata *metadata; + struct fanotify_event_info_fid *event_fid; + struct test_case_t *tc = &test_cases[number]; + struct fanotify_mark_type *mark = &tc->mark; + + tst_res(TINFO, + "Test #%d: FAN_REPORT_FID with mark flag: %s", + number, mark->name); + + fanotify_fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, O_RDONLY); + if (fanotify_fd == -1) { + if (errno == EINVAL) { + tst_res(TCONF, + "FAN_REPORT_FID not supported by kernel"); + return; + } + tst_brk(TBROK | TERRNO, + "fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, " + "O_RDONLY) failed"); + } + + /* Place marks on a set of objects and setup the expected masks + * for each event that is expected to be generated + */ + if (setup_marks(fanotify_fd, tc) != 0) + return; + + /* Generate sequence of FAN_OPEN events on objects */ + for (i = 0; i < ARRAY_SIZE(objects); i++) + fds[i] = SAFE_OPEN(objects[i].path, O_RDONLY); + + /* Generate sequence of FAN_CLOSE_NOWRITE events on objects. Each + * FAN_CLOSE_NOWRITE event is expected to be merged with its + * respective FAN_OPEN event that was performed on the same object + */ + for (i = 0; i < ARRAY_SIZE(objects); i++) { + if (fds[i] > 0) + SAFE_CLOSE(fds[i]); + } + + /* Read events from event queue */ + len = SAFE_READ(0, fanotify_fd, events_buf, BUF_SIZE); + + /* Iterate over event queue */ + for (i = 0, metadata = (struct fanotify_event_metadata *) events_buf; + FAN_EVENT_OK(metadata, len); + metadata = FAN_EVENT_NEXT(metadata, len), i++) { + event_fid = (struct fanotify_event_info_fid *) (metadata + 1); + event_file_handle = (struct file_handle *) event_fid->handle; + + /* File descriptor is redundant with FAN_REPORT_FID */ + if (metadata->fd != FAN_NOFD) + tst_res(TFAIL, + "Unexpectedly received file descriptor %d in " + "event. Expected to get FAN_NOFD(%d)", + metadata->fd, FAN_NOFD); + + /* Ensure that the correct mask has been reported in event */ + if (metadata->mask != event_set[i].expected_mask) + tst_res(TFAIL, + "Unexpected mask received: %llx (expected: " + "%llx) in event", + metadata->mask, + event_set[i].expected_mask); + + /* Verify handle_bytes returned in event */ + if (event_file_handle->handle_bytes + != event_set[i].handle.handle_bytes) { + tst_res(TFAIL, + "handle_bytes (%x) returned in event does not " + "equal to handle_bytes (%x) returned in " + "name_to_handle_at(2)", + event_file_handle->handle_bytes, + event_set[i].handle.handle_bytes); + continue; + } + + /* Verify handle_type returned in event */ + if (event_file_handle->handle_type != + event_set[i].handle.handle_type) { + tst_res(TFAIL, + "handle_type (%x) returned in event does not " + "equal to handle_type (%x) returned in " + "name_to_handle_at(2)", + event_file_handle->handle_type, + event_set[i].handle.handle_type); + continue; + } + + /* Verify file identifier f_handle returned in event */ + if (memcmp(event_file_handle->f_handle, + event_set[i].handle.f_handle, + event_set[i].handle.handle_bytes) != 0) { + tst_res(TFAIL, + "event_file_handle->f_handle does not match " + "event_set[i].handle.f_handle returned in " + "name_to_handle_at(2)"); + continue; + } + + /* Verify filesystem ID fsid returned in event */ + if (memcmp(&event_fid->fsid, &event_set[i].fsid, + sizeof(event_set[i].fsid)) != 0) { + tst_res(TFAIL, + "event_fid.fsid != stat.f_fsid that was " + "obtained via statfs(2)"); + continue; + } + + tst_res(TPASS, + "got event: mask=%llx, pid=%d, fid=%x.%x.%lx values " + "returned in event match those returned in statfs(2) " + "and name_to_handle_at(2)", + metadata->mask, + getpid(), + event_fid->fsid.val[0], + event_fid->fsid.val[1], + *(unsigned long *) event_file_handle->f_handle); + } +} + +static void do_cleanup(void) +{ + if (fanotify_fd > 0) + SAFE_CLOSE(fanotify_fd); +} + +static struct tst_test test = { + .setup = do_setup, + .test = do_test, + .tcnt = ARRAY_SIZE(test_cases), + .cleanup = do_cleanup, + .needs_root = 1, + .needs_tmpdir = 1, + .mount_device = 1, + .mntpoint = MOUNT_PATH, + .all_filesystems = 1 +}; + +#else + TST_TEST_CONF("System does not have required fanotify support"); +#endif From patchwork Sun May 19 05:25:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Bobrowski X-Patchwork-Id: 1101514 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=2001:1418:10:5::2; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mbobrowski.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mbobrowski-org.20150623.gappssmtp.com header.i=@mbobrowski-org.20150623.gappssmtp.com header.b="gKmj99+M"; dkim-atps=neutral Received: from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4569VX55jnz9s3Z for ; Sun, 19 May 2019 15:26:12 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 057763EA53D for ; Sun, 19 May 2019 07:26:10 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-3.smtp.seeweb.it (in-3.smtp.seeweb.it [IPv6:2001:4b78:1:20::3]) by picard.linux.it (Postfix) with ESMTP id E39D23EA1BF for ; Sun, 19 May 2019 07:26:07 +0200 (CEST) Received: from mail-pf1-x442.google.com (mail-pf1-x442.google.com [IPv6:2607:f8b0:4864:20::442]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by in-3.smtp.seeweb.it (Postfix) with ESMTPS id 03EBC1A00EED for ; Sun, 19 May 2019 07:26:07 +0200 (CEST) Received: by mail-pf1-x442.google.com with SMTP id u17so5620092pfn.7 for ; Sat, 18 May 2019 22:26:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mbobrowski-org.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=9TZmO0yVutHEOqxLAL7wXxGf2bx/idv/KOsNNbWQuIY=; b=gKmj99+MuNhvJFAEE2ZL040hEiNFTArxU8N3LK5PvtyR+HlB2xH4ZA0Mbi7mFf6p00 S2B8nBdfkSyI9OIQ5mKCHsJatKOh9/xaXQlLGzepOlncPyUDPAz61baJcFUIO2tunYeC +jdWc3Fw+XhGgwI4pf+81aenHQ/julRhAz5+8myU4WmSieTmKCafIaolMBcnjvToY3xc pfznMdbUoSyDMinL2cT8MtJYgvMj5CofX1IChPYbUd37Am4r31xYb9R0j2Wnril+R/Ba CrFKRksI8GMmu/4001aceCcs2PdhiQ7rFqb2S0yyW0Lp7aDMKx0ViVFjHsPx7mmg/mC6 D9rA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=9TZmO0yVutHEOqxLAL7wXxGf2bx/idv/KOsNNbWQuIY=; b=eEZbZNa9uS8xpb1yJkJPmbgQy5WrsLyt7G3fvW5KGC8qFSzJCeg7m+7xfx9N3yhLS2 uv5Q/Zi2zN5Ek0NN3Z8ac84Wu+SsQ9zFEF5udiFZPGDHGPmUpTMiBABTeG33hkTHOJoC jiyMLEQuhrp6hbN/wbohqC5zRY4B1zzmeLOOCFH2loImak1mRltEpYDeXVfCROZVAKYj BsElHRDbKItK3b8B+HKV5iGuBNtn0o7u0yQ/a6SCMYgK+ISG7VmToTQRxmLBuagP04tY um8J/FdFXzuYDBi+kQfaIL2WdNlMHlGIfF3taVUKgfUl6u3AzfmS5fqlmD2RP+5DVJdJ bwRQ== X-Gm-Message-State: APjAAAVXWms5MPiM01jrBPe2K0AYbirvhMKIirPOKtEgQvVW9mcWsYmG vJC6BXiZZnVwaQsFyGY/MhT9f0IOMQ== X-Google-Smtp-Source: APXvYqzBdHXCUphDn3TA/9fDck2PgFsaHjBmpzuDPti2e7Ng8t7SpXoTPjMR0q7S4h3GmVP0vY2ZYg== X-Received: by 2002:a63:184:: with SMTP id 126mr41552303pgb.420.1558243565184; Sat, 18 May 2019 22:26:05 -0700 (PDT) Received: from poseidon.Home (n114-74-156-190.sbr2.nsw.optusnet.com.au. [114.74.156.190]) by smtp.gmail.com with ESMTPSA id v40sm19823411pgn.17.2019.05.18.22.26.01 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 18 May 2019 22:26:04 -0700 (PDT) Date: Sun, 19 May 2019 15:25:55 +1000 From: Matthew Bobrowski To: ltp@lists.linux.it Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.11.3 (2019-02-01) X-Virus-Scanned: clamav-milter 0.99.2 at in-3.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.1 required=7.0 tests=DKIM_SIGNED,DKIM_VALID, SPF_HELO_NONE,SPF_NONE autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-3.smtp.seeweb.it Cc: jack@suse.cz Subject: [LTP] [PATCH v3 2/3] syscalls/fanotify14: new test to validate FAN_REPORT_FID return values X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" A newly defined test file has been introduced to validate that the fanotify interface returns the correct error values upon specifying invalid flags and masks in conjunction with FAN_REPORT_FID. A new line entry within runtest/syscalls for this new test file. Signed-off-by: Matthew Bobrowski Reviewed-by: Amir Goldstein --- runtest/syscalls | 1 + testcases/kernel/syscalls/fanotify/.gitignore | 1 + testcases/kernel/syscalls/fanotify/fanotify.h | 25 +++ .../kernel/syscalls/fanotify/fanotify14.c | 171 ++++++++++++++++++ 4 files changed, 198 insertions(+) create mode 100644 testcases/kernel/syscalls/fanotify/fanotify14.c diff --git a/runtest/syscalls b/runtest/syscalls index dfdc6cbf9..5c62895b0 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -538,6 +538,7 @@ fanotify10 fanotify10 fanotify11 fanotify11 fanotify12 fanotify12 fanotify13 fanotify13 +fanotify14 fanotify14 ioperm01 ioperm01 ioperm02 ioperm02 diff --git a/testcases/kernel/syscalls/fanotify/.gitignore b/testcases/kernel/syscalls/fanotify/.gitignore index 16bdd99e5..bf389c96a 100644 --- a/testcases/kernel/syscalls/fanotify/.gitignore +++ b/testcases/kernel/syscalls/fanotify/.gitignore @@ -11,4 +11,5 @@ /fanotify11 /fanotify12 /fanotify13 +/fanotify14 /fanotify_child diff --git a/testcases/kernel/syscalls/fanotify/fanotify.h b/testcases/kernel/syscalls/fanotify/fanotify.h index d6e259002..92fc78dcc 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify.h +++ b/testcases/kernel/syscalls/fanotify/fanotify.h @@ -69,6 +69,31 @@ static long fanotify_mark(int fd, unsigned int flags, uint64_t mask, #ifndef FAN_MARK_FILESYSTEM #define FAN_MARK_FILESYSTEM 0x00000100 #endif +/* New dirent event masks */ +#ifndef FAN_ATTRIB +#define FAN_ATTRIB 0x00000004 +#endif +#ifndef FAN_MOVED_FROM +#define FAN_MOVED_FROM 0x00000040 +#endif +#ifndef FAN_MOVED_TO +#define FAN_MOVED_TO 0x00000080 +#endif +#ifndef FAN_CREATE +#define FAN_CREATE 0x00000100 +#endif +#ifndef FAN_DELETE +#define FAN_DELETE 0x00000200 +#endif +#ifndef FAN_DELETE_SELF +#define FAN_DELETE_SELF 0x00000400 +#endif +#ifndef FAN_MOVE_SELF +#define FAN_MOVE_SELF 0x00000800 +#endif +#ifndef FAN_MOVE +#define FAN_MOVE (FAN_MOVED_FROM | FAN_MOVED_TO) +#endif #ifndef FAN_OPEN_EXEC #define FAN_OPEN_EXEC 0x00001000 #endif diff --git a/testcases/kernel/syscalls/fanotify/fanotify14.c b/testcases/kernel/syscalls/fanotify/fanotify14.c new file mode 100644 index 000000000..735d6accf --- /dev/null +++ b/testcases/kernel/syscalls/fanotify/fanotify14.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 Matthew Bobrowski. All Rights Reserved. + * + * Started by Matthew Bobrowski + * + * DESCRIPTION + * This test file has been designed to ensure that the fanotify + * system calls fanotify_init(2) and fanotify_mark(2) return the + * correct error code to the calling process when an invalid flag or + * mask value has been specified in conjunction with FAN_REPORT_FID. + */ + +#include "tst_test.h" +#include "fanotify.h" + +#include + +#if defined(HAVE_SYS_FANOTIFY_H) +#include + +#define MNTPOINT "mntpoint" +#define FILE1 MNTPOINT"/file1" + +/* List of inode events that are only available when notification group is + * set to report fid + */ +#define INODE_EVENTS (FAN_ATTRIB | FAN_CREATE | FAN_DELETE | FAN_MOVE | \ + FAN_DELETE_SELF | FAN_MOVE_SELF) + +static int fanotify_fd; + +/* Each test case has been designed in a manner whereby the values defined + * within should result in the interface to return an error to the calling + * process. + */ +static struct test_case_t { + unsigned int init_flags; + unsigned int mark_flags; + unsigned long long mask; +} test_cases[] = { + { + FAN_CLASS_CONTENT | FAN_REPORT_FID, 0, 0 + }, + { + FAN_CLASS_PRE_CONTENT | FAN_REPORT_FID, 0, 0 + }, + { + FAN_CLASS_NOTIF, 0, INODE_EVENTS + }, + { + FAN_CLASS_NOTIF | FAN_REPORT_FID, FAN_MARK_MOUNT, INODE_EVENTS + } +}; + +static void do_setup(void) +{ + int fd; + + /* Check for kernel fanotify support */ + fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY); + SAFE_CLOSE(fd); + + /* Create temporary test file to place marks on */ + SAFE_FILE_PRINTF(FILE1, "0"); +} + +static void do_test(unsigned int number) +{ + int ret; + struct test_case_t *tc = &test_cases[number]; + + fanotify_fd = fanotify_init(tc->init_flags, O_RDONLY); + + if (fanotify_fd < 0) { + /* EINVAL is to be returned to the calling process when + * an invalid notification class is specified in + * conjunction with FAN_REPORT_FID + */ + if (errno == EINVAL) { + tst_res(TPASS, + "fanotify_fd=%d, fanotify_init(%x, O_RDONLY) " + "failed with error EINVAL as expected", + fanotify_fd, + tc->init_flags); + return; + } + tst_brk(TBROK | TERRNO, + "fanotify_fd=%d, fanotify_init(%x, O_RDONLY) failed", + fanotify_fd, + tc->init_flags); + } + + /* A test case with a mask set to zero indicate that they've been + * specifically designed to test and fail on the fanotify_init() + * system call. + */ + if (tc->mask == 0) { + tst_res(TFAIL, + "fanotify_fd=%d fanotify_init(%x, O_RDONLY) " + "unexpectedly succeeded when tests with mask 0 are" + "expected to fail when calling fanotify_init()", + fanotify_fd, + tc->init_flags); + return; + } + + ret = fanotify_mark(fanotify_fd, FAN_MARK_ADD | tc->mark_flags, + tc->mask, AT_FDCWD, FILE1); + + if (ret < 0) { + /* EINVAL is to be returned to the calling process when + * attempting to use INODE_EVENTS without FAN_REPORT_FID + * specified on the notification group, or using + * INODE_EVENTS with mark type FAN_MARK_MOUNT. + */ + if (errno == EINVAL) { + tst_res(TPASS, + "ret=%d, fanotify_mark(%d, FAN_MARK_ADD | %x, " + "%llx, AT_FDCWD, %s) failed with error EINVAL " + "as expected", + ret, + fanotify_fd, + tc->mark_flags, + tc->mask, + FILE1); + return; + } + tst_brk(TBROK | TERRNO, + "ret=%d, fanotify_mark(%d, FAN_MARK_ADD | %x, %llx, " + "AT_FDCWD, %s) failed", + ret, + fanotify_fd, + tc->mark_flags, + tc->mask, + FILE1); + } + + tst_res(TFAIL, + "fanotify_fd=%d, ret=%d, fanotify_init(%x, O_RDONLY) and " + "fanotify_mark(%d, FAN_MARK_ADD | %x, %llx, AT_FDCWD, %s) did " + "not return any errors as expected", + fanotify_fd, + ret, + tc->init_flags, + fanotify_fd, + tc->mark_flags, + tc->mask, + FILE1); +} + +static void do_cleanup(void) +{ + if (fanotify_fd > 0) + SAFE_CLOSE(fanotify_fd); +} + +static struct tst_test test = { + .needs_root = 1, + .setup = do_setup, + .test = do_test, + .tcnt = ARRAY_SIZE(test_cases), + .cleanup = do_cleanup, + .mount_device = 1, + .mntpoint = MNTPOINT, + .all_filesystems = 1 +}; + +#else + TST_TEST_CONF("System does not have required fanotify support") +#endif From patchwork Sun May 19 05:26:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Bobrowski X-Patchwork-Id: 1101515 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mbobrowski.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mbobrowski-org.20150623.gappssmtp.com header.i=@mbobrowski-org.20150623.gappssmtp.com header.b="OPcGUoHk"; dkim-atps=neutral Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4569Vv5mn4z9s3Z for ; Sun, 19 May 2019 15:26:31 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 1E5523EA441 for ; Sun, 19 May 2019 07:26:29 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-3.smtp.seeweb.it (in-3.smtp.seeweb.it [IPv6:2001:4b78:1:20::3]) by picard.linux.it (Postfix) with ESMTP id 06B783EA441 for ; Sun, 19 May 2019 07:26:27 +0200 (CEST) Received: from mail-pl1-x641.google.com (mail-pl1-x641.google.com [IPv6:2607:f8b0:4864:20::641]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by in-3.smtp.seeweb.it (Postfix) with ESMTPS id 0C6E51A00EED for ; Sun, 19 May 2019 07:26:26 +0200 (CEST) Received: by mail-pl1-x641.google.com with SMTP id f97so5181662plb.5 for ; Sat, 18 May 2019 22:26:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mbobrowski-org.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=OyDU7cjg2B1Qr52Qaxu+gjf1vmW0JFqvbCm/ocS+RuI=; b=OPcGUoHkhRcPlN/kHQYQ4LJx8/+6sSqQ8EJCQEbTkQMjiBB0A1Cd7fcV984o6IZQXO R+iILan1dm0Y/BeXtKWXJBGPjcbbYJtYYYOzu8kbWkPJbpuE65YnctvtGLHOVN72vUJn xBgFh2AuEKlbvtrh6w3LLDgfeaK2Z/GEA25Lyf+nThIgjZ60LshDA3Ajl46oKUc1Rsvg Aq5iAq0sUqkx11TknsvFQS+klb5r+/6VoShY8zjzDBaGl70gLAqB51JrDdcmYDFhY23/ SuebmP8DVoMzgmiRv+tlZooJE+yp1MK0jv6Vq2JRDmBgdp39BxDUB0GFNSteg7LCZ/mh 65VA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=OyDU7cjg2B1Qr52Qaxu+gjf1vmW0JFqvbCm/ocS+RuI=; b=e/zL01JFoFmwViTH3ip7Tn7/NkIp3e/+DgQYBe7TpVxqIEVqo/Dookn0S+ffhITVtj UQTrZfxhTpNfzlc4p9f7c3ibnzJOE3c8aFLFomaSBsthiaLz8Cm2Xs3Xs6etMITmDX8R TvEE0kNrCN8f/2ffei4MuYODha8rbck+iZVLwD8L9bb+8ccUBSdEqDA4rEl99HMv8vHY z2EpZvVK+gr6RzNNWtuUFoMuts6KuBI36nLXuHt156OX96tRUTX1c/BrY2JhLTndrPyr BKxz7nbVkgHw3lDEHEf3swS82SNm1iMMBYnn7atCEaSvmLnpZDtYyjgtz/YYiYDN/A3g OKzg== X-Gm-Message-State: APjAAAXQ12YtGPrin5wAgcPaaiGIxhjS2NdLv8rlk0xMEMARyNvNwnBJ IzEIMe2QMT/r8TfopVZKt4ZGhB3yyA== X-Google-Smtp-Source: APXvYqyK4LbGeOINITGdg0IJBq9Hkc44T44NjIqQtEqRQXeerEwO/289FS379qWJ1dn5TIpiO1Bxhw== X-Received: by 2002:a17:902:8c8c:: with SMTP id t12mr68434850plo.116.1558243584156; Sat, 18 May 2019 22:26:24 -0700 (PDT) Received: from poseidon.Home (n114-74-156-190.sbr2.nsw.optusnet.com.au. [114.74.156.190]) by smtp.gmail.com with ESMTPSA id a18sm22393894pfr.22.2019.05.18.22.26.20 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 18 May 2019 22:26:23 -0700 (PDT) Date: Sun, 19 May 2019 15:26:15 +1000 From: Matthew Bobrowski To: ltp@lists.linux.it Message-ID: <52fcc83b7fee6ba8d3499297fca4311e3fe74906.1558242368.git.mbobrowski@mbobrowski.org> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.11.3 (2019-02-01) X-Virus-Scanned: clamav-milter 0.99.2 at in-3.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.1 required=7.0 tests=DKIM_SIGNED,DKIM_VALID, SPF_HELO_NONE,SPF_NONE autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-3.smtp.seeweb.it Cc: jack@suse.cz Subject: [LTP] [PATCH v3 3/3] syscalls/fanotify15: verify fid for dirent events X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" A new test file that provides coverage for new dirent events added. A new line entry within the runtest/syscalls file has been also added to support this new test file. Signed-off-by: Matthew Bobrowski Reviewed-by: Amir Goldstein --- runtest/syscalls | 1 + testcases/kernel/syscalls/fanotify/.gitignore | 1 + .../kernel/syscalls/fanotify/fanotify15.c | 245 ++++++++++++++++++ 3 files changed, 247 insertions(+) create mode 100644 testcases/kernel/syscalls/fanotify/fanotify15.c diff --git a/runtest/syscalls b/runtest/syscalls index 5c62895b0..2f9f14736 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -539,6 +539,7 @@ fanotify11 fanotify11 fanotify12 fanotify12 fanotify13 fanotify13 fanotify14 fanotify14 +fanotify15 fanotify15 ioperm01 ioperm01 ioperm02 ioperm02 diff --git a/testcases/kernel/syscalls/fanotify/.gitignore b/testcases/kernel/syscalls/fanotify/.gitignore index bf389c96a..68e4cc7aa 100644 --- a/testcases/kernel/syscalls/fanotify/.gitignore +++ b/testcases/kernel/syscalls/fanotify/.gitignore @@ -12,4 +12,5 @@ /fanotify12 /fanotify13 /fanotify14 +/fanotify15 /fanotify_child diff --git a/testcases/kernel/syscalls/fanotify/fanotify15.c b/testcases/kernel/syscalls/fanotify/fanotify15.c new file mode 100644 index 000000000..02f3b34ab --- /dev/null +++ b/testcases/kernel/syscalls/fanotify/fanotify15.c @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2019 CTERA Networks. All Rights Reserved. + * + * Started by Amir Goldstein + * Modified by Matthew Bobrowski + * + * DESCRIPTION + * Test file that has been purposely designed to verify + * FAN_REPORT_FID functionality while using newly defined dirent + * events. + */ +#define _GNU_SOURCE +#include "config.h" + +#include +#include +#include +#include +#include + +#include "tst_test.h" +#include "fanotify.h" + +#if defined(HAVE_SYS_FANOTIFY_H) +#include + +#define BUF_SIZE 256 +#define EVENT_MAX 256 + +#define MOUNT_POINT "mntpoint" +#define TEST_DIR MOUNT_POINT"/test_dir" +#define DIR1 TEST_DIR"/dir1" +#define DIR2 TEST_DIR"/dir2" +#define FILE1 TEST_DIR"/file1" +#define FILE2 TEST_DIR"/file2" + +struct event_t { + unsigned long long mask; + __kernel_fsid_t fsid; + struct file_handle handle; + char buf[MAX_HANDLE_SZ]; +}; + +static int fanotify_fd; +static char events_buf[BUF_SIZE]; +static struct event_t event_set[EVENT_MAX]; + +static void do_setup(void) +{ + int fd; + + /* Check kernel for fanotify support */ + fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY); + SAFE_CLOSE(fd); + + fanotify_fd = fanotify_init(FAN_REPORT_FID, O_RDONLY); + if (fanotify_fd == -1) { + if (errno == EINVAL) + tst_brk(TCONF, + "FAN_REPORT_FID not supported in kernel"); + tst_brk(TBROK | TERRNO, + "fanotify_init(FAN_REPORT_FID, O_RDONLY) failed"); + } + + SAFE_MKDIR(TEST_DIR, 0755); +} + +static void do_test(void) +{ + int i, fd, len, count = 0; + + struct file_handle *event_file_handle; + struct fanotify_event_metadata *metadata; + struct fanotify_event_info_fid *event_fid; + + if (fanotify_mark(fanotify_fd, FAN_MARK_ADD | FAN_MARK_FILESYSTEM, + FAN_CREATE | FAN_DELETE | FAN_ATTRIB | + FAN_MOVED_FROM | FAN_MOVED_TO | + FAN_DELETE_SELF | FAN_ONDIR, + AT_FDCWD, TEST_DIR) == -1) { + if (errno == ENODEV) + tst_brk(TCONF, + "FAN_REPORT_FID not supported on %s " + "filesystem", tst_device->fs_type); + tst_brk(TBROK | TERRNO, + "fanotify_mark(%d, FAN_MARK_ADD, FAN_CREATE | " + "FAN_DELETE | FAN_MOVED_FROM | FAN_MOVED_TO | " + "FAN_DELETE_SELF | FAN_ONDIR, AT_FDCWD, %s) failed", + fanotify_fd, TEST_DIR); + } + + /* Generate a sequence of events */ + event_set[count].mask = FAN_CREATE | FAN_MOVED_FROM | FAN_MOVED_TO | \ + FAN_DELETE; + event_set[count].handle.handle_bytes = MAX_HANDLE_SZ; + fanotify_get_fid(TEST_DIR, &event_set[count].fsid, + &event_set[count].handle); + count++; + + fd = SAFE_CREAT(FILE1, 0644); + SAFE_CLOSE(fd); + + SAFE_RENAME(FILE1, FILE2); + + event_set[count].mask = FAN_ATTRIB | FAN_DELETE_SELF; + event_set[count].handle.handle_bytes = MAX_HANDLE_SZ; + fanotify_get_fid(FILE2, &event_set[count].fsid, + &event_set[count].handle); + count++; + + SAFE_UNLINK(FILE2); + + /* Generate a sequence of events on a directory. Subsequent events + * are merged, so it's required that we set FAN_ONDIR once in + * order to acknowledge that changes related to a subdirectory + * took place. Events on subdirectories are not merged with events + * on non-subdirectories. + */ + event_set[count].mask = FAN_ONDIR | FAN_CREATE | FAN_MOVED_FROM | \ + FAN_MOVED_TO | FAN_DELETE; + event_set[count].handle.handle_bytes = MAX_HANDLE_SZ; + fanotify_get_fid(TEST_DIR, &event_set[count].fsid, + &event_set[count].handle); + count++; + + SAFE_MKDIR(DIR1, 0755); + + SAFE_RENAME(DIR1, DIR2); + + event_set[count].mask = FAN_ONDIR | FAN_DELETE_SELF; + event_set[count].handle.handle_bytes = MAX_HANDLE_SZ; + fanotify_get_fid(DIR2, &event_set[count].fsid, + &event_set[count].handle); + count++; + + SAFE_RMDIR(DIR2); + + /* Read events from the event queue */ + len = SAFE_READ(0, fanotify_fd, events_buf, BUF_SIZE); + + /* Process each event in buffer */ + for (i = 0, metadata = (struct fanotify_event_metadata *) events_buf; + FAN_EVENT_OK(metadata, len); + metadata = FAN_EVENT_NEXT(metadata,len), i++) { + event_fid = (struct fanotify_event_info_fid *) (metadata + 1); + event_file_handle = (struct file_handle *) event_fid->handle; + + if (i >= count) { + tst_res(TFAIL, + "got unnecessary event: mask=%llx " + "pid=%u fd=%d", + (unsigned long long) metadata->mask, + metadata->pid, + metadata->fd); + metadata->mask = 0; + } else if (metadata->fd != FAN_NOFD) { + tst_res(TFAIL, + "Received unexpected file descriptor %d in " + "event. Expected to get FAN_NOFD(%d)", + metadata->fd, FAN_NOFD); + } else if (metadata->mask != event_set[i].mask) { + tst_res(TFAIL, + "Got event: mask=%llx (expected %llx) " + "pid=%u fd=%d", + (unsigned long long) metadata->mask, + event_set[i].mask, + (unsigned) metadata->pid, + metadata->fd); + } else if (metadata->pid != getpid()) { + tst_res(TFAIL, + "Got event: mask=%llx pid=%u " + "(expected %u) fd=%d", + (unsigned long long) metadata->mask, + (unsigned) metadata->pid, + (unsigned) getpid(), + metadata->fd); + } else if (event_file_handle->handle_bytes != + event_set[i].handle.handle_bytes) { + tst_res(TFAIL, + "Got event: handle_bytes (%x) returned in " + "event does not equal handle_bytes (%x) " + "retunred in name_to_handle_at(2)", + event_file_handle->handle_bytes, + event_set[i].handle.handle_bytes); + } else if (event_file_handle->handle_type != + event_set[i].handle.handle_type) { + tst_res(TFAIL, + "handle_type (%x) returned in event does not " + "equal to handle_type (%x) returned in " + "name_to_handle_at(2)", + event_file_handle->handle_type, + event_set[i].handle.handle_type); + } else if (memcmp(event_file_handle->f_handle, + event_set[i].handle.f_handle, + event_set[i].handle.handle_bytes) + != 0) { + tst_res(TFAIL, + "event_file_handle->f_handle does not match " + "handle.f_handle returned in " + "name_to_handle_at(2)"); + } else if (memcmp(&event_fid->fsid, &event_set[i].fsid, + sizeof(event_set[i].fsid)) != 0) { + tst_res(TFAIL, + "event_fid->fsid != stats.f_fsid that was " + "obtained via statfs(2)"); + } else { + tst_res(TPASS, + "Got event: mask=%llx, pid=%u, " + "fid=%x.%x.%lx values", + metadata->mask, + getpid(), + event_fid->fsid.val[0], + event_fid->fsid.val[1], + *(unsigned long *) + event_file_handle->f_handle); + } + } + + for (; i < count; i++) + tst_res(TFAIL, + "Didn't receive event: mask=%llx", + event_set[i].mask); +} + +static void do_cleanup(void) +{ + if (fanotify_fd > 0) + SAFE_CLOSE(fanotify_fd); +} + +static struct tst_test test = { + .needs_root = 1, + .needs_tmpdir = 1, + .mount_device = 1, + .mntpoint = MOUNT_POINT, + .all_filesystems = 1, + .setup = do_setup, + .test_all = do_test, + .cleanup = do_cleanup +}; + +#else + TST_TEST_CONF("System does not have required fanotify support"); +#endif