android13/external/ltp/testcases/kernel/syscalls/fanotify/fanotify14.c

186 lines
4.3 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 Matthew Bobrowski. All Rights Reserved.
*
* Started by Matthew Bobrowski <mbobrowski@mbobrowski.org>
*/
/*\
* [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.
*/
#define _GNU_SOURCE
#include "tst_test.h"
#include <errno.h>
#ifdef HAVE_SYS_FANOTIFY_H
#include "fanotify.h"
#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
},
{
/* FAN_REPORT_NAME without FAN_REPORT_DIR_FID is not valid */
FAN_CLASS_NOTIF | FAN_REPORT_NAME, 0, 0
},
{
/* FAN_REPORT_NAME without FAN_REPORT_DIR_FID is not valid */
FAN_CLASS_NOTIF | FAN_REPORT_FID | FAN_REPORT_NAME, 0, 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);
goto out;
}
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);
goto out;
}
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);
out:
SAFE_CLOSE(fanotify_fd);
}
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_cleanup(void)
{
if (fanotify_fd > 0)
SAFE_CLOSE(fanotify_fd);
}
static struct tst_test test = {
.needs_root = 1,
.test = do_test,
.tcnt = ARRAY_SIZE(test_cases),
.setup = do_setup,
.cleanup = do_cleanup,
.mount_device = 1,
.mntpoint = MNTPOINT,
.all_filesystems = 1
};
#else
TST_TEST_TCONF("System does not have required fanotify support");
#endif