From patchwork Tue Sep 25 08:43:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoming Ni X-Patchwork-Id: 974338 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=huawei.com 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 42KGLG0J9fz9s9G for ; Tue, 25 Sep 2018 19:41:41 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id D865C1A9617 for ; Tue, 25 Sep 2018 11:41:38 +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 454023E68B0 for ; Tue, 25 Sep 2018 11:31:30 +0200 (CEST) Received: from huawei.com (szxga07-in.huawei.com [45.249.212.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by in-4.smtp.seeweb.it (Postfix) with ESMTPS id 2A68210016E6 for ; Tue, 25 Sep 2018 11:31:28 +0200 (CEST) Received: from DGGEMS407-HUB.china.huawei.com (unknown [172.30.72.60]) by Forcepoint Email with ESMTP id 1FF85D8B1EAD for ; Tue, 25 Sep 2018 17:31:24 +0800 (CST) Received: from linux-work.huawei.com (10.67.189.174) by DGGEMS407-HUB.china.huawei.com (10.3.19.207) with Microsoft SMTP Server id 14.3.399.0; Tue, 25 Sep 2018 17:31:16 +0800 From: nixiaoming To: , Date: Tue, 25 Sep 2018 16:43:44 +0800 Message-ID: <20180925084344.4397-1-nixiaoming@huawei.com> X-Mailer: git-send-email 2.10.1 MIME-Version: 1.0 X-Originating-IP: [10.67.189.174] X-CFilter-Loop: Reflected X-Virus-Scanned: clamav-milter 0.99.2 at in-4.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=-0.0 required=7.0 tests=SPF_HELO_PASS,SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-4.smtp.seeweb.it X-Mailman-Approved-At: Tue, 25 Sep 2018 11:41:37 +0200 Cc: nixiaoming@huawei.com Subject: [LTP] [PATCH] syscalls/fanotify: test fanotify_init new flags FAN_EVENT_INFO_TID 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" fanotify_info_tid: test fanotify_init with FAN_EVENT_INFO_TID data->pid is ID(pid) of the thread that caused the event fanotify_info_tgid: test fanotify_init without FAN_EVENT_INFO_TID data->pid is ID(tgid) of the process that caused the event Signed-off-by: nixiaoming --- testcases/kernel/syscalls/fanotify/Makefile | 3 +- .../kernel/syscalls/fanotify/fanotify_info_tgid.c | 200 ++++++++++++++++++++ .../kernel/syscalls/fanotify/fanotify_info_tid.c | 204 +++++++++++++++++++++ 3 files changed, 406 insertions(+), 1 deletion(-) create mode 100644 testcases/kernel/syscalls/fanotify/fanotify_info_tgid.c create mode 100644 testcases/kernel/syscalls/fanotify/fanotify_info_tid.c diff --git a/testcases/kernel/syscalls/fanotify/Makefile b/testcases/kernel/syscalls/fanotify/Makefile index bb58878..d85c755 100644 --- a/testcases/kernel/syscalls/fanotify/Makefile +++ b/testcases/kernel/syscalls/fanotify/Makefile @@ -17,7 +17,8 @@ # top_srcdir ?= ../../../.. - +fanotify_info_tid: CFLAGS+=-pthread +fanotify_info_tgid: CFLAGS+=-pthread include $(top_srcdir)/include/mk/testcases.mk include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/fanotify/fanotify_info_tgid.c b/testcases/kernel/syscalls/fanotify/fanotify_info_tgid.c new file mode 100644 index 0000000..3b10d79 --- /dev/null +++ b/testcases/kernel/syscalls/fanotify/fanotify_info_tgid.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2013 SUSE. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Started by nixiaoming + * + * DESCRIPTION + * After fanotify_init without FAN_EVENT_INFO_TID, + * check whether the program can only show tgid + * in the multithreaded program triggered the event.. + * + * This is a regression test for commit 55c5b2ed10331c3b22: + * + * fanotify: support reporting thread id instead of process id + */ +#define _GNU_SOURCE +#include "config.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tst_test.h" +#include "fanotify.h" + +#if defined(HAVE_SYS_FANOTIFY_H) +#include + + +#define BUF_SIZE 256 +#define gettid() syscall(SYS_gettid) + +static char fname[BUF_SIZE]; +int fd_notify; + +static int tid; +static int tgid; +static char tid_file[BUF_SIZE]; + +void *thread_create_file(void *arg LTP_ATTRIBUTE_UNUSED) +{ + int fd; + + tid = gettid(); + snprintf(tid_file, sizeof(tid_file), "%s/test_tid_%d", fname, tid); + sleep(1); + fd = SAFE_OPEN(tid_file, O_WRONLY|O_CREAT, 0600); + tst_res(TINFO, "open file=%s. fd=%d, tid=%i\n", tid_file, fd, tid); + SAFE_WRITE(1, fd, tid_file, sizeof(tid_file)); + tst_res(TINFO, "write file=%s. fd=%d, tid=%i\n", tid_file, fd, tid); + SAFE_CLOSE(fd); + tst_res(TINFO, "close file=%s. fd=%d, tid=%i\n", tid_file, fd, tid); + SAFE_UNLINK(tid_file); + tst_res(TINFO, "unlink file=%s. fd=%d, tid=%i\n", tid_file, fd, tid); + sleep(1); + pthread_exit(0); +} + +static const char* mask2str(uint64_t mask) +{ + static char buffer[10]; + int offset = 0; + + if (mask & FAN_ACCESS) + buffer[offset++] = 'R'; + if (mask & FAN_ONDIR) + buffer[offset++] = 'D'; + if (mask & FAN_OPEN) + buffer[offset++] = 'O'; + if (mask & FAN_CLOSE_WRITE || mask & FAN_CLOSE_NOWRITE) + buffer[offset++] = 'C'; + if (mask & FAN_MODIFY || mask & FAN_CLOSE_WRITE) + buffer[offset++] = 'W'; + buffer[offset] = '\0'; + + return buffer; +} + + +static void show_data(const struct fanotify_event_metadata *data) +{ + static char printbuf[100]; + static char pathname[PATH_MAX]; + struct stat st; + int len; + + snprintf(printbuf, sizeof(printbuf), "/proc/self/fd/%i", data->fd); + len = readlink(printbuf, pathname, sizeof(pathname)); + if (len < 0) { + /* fall back to the device/inode */ + if (fstat(data->fd, &st) < 0) { + perror("stat"); + exit(1); + } + snprintf(pathname, sizeof(pathname), "device %i:%i inode %ld\n", + major(st.st_dev), minor(st.st_dev), st.st_ino); + } else { + pathname[len] = '\0'; + } + tst_res(TINFO, "envnt: %i %s %s\n", data->pid, mask2str(data->mask), + pathname); +} + +void test01(void) +{ + int res; + int ret; + char buffer[4096] = {0}; + struct fanotify_event_metadata *data; + + ret = fanotify_mark(fd_notify, FAN_MARK_ADD, FAN_CLOSE | FAN_OPEN | FAN_EVENT_ON_CHILD, AT_FDCWD, fname); + if (ret != 0) { + tst_brk(TBROK, "fanotify_mark (%d, FAN_MARK_ADD, FAN_CLOSE | FAN_OPEN |FAN_EVENT_ON_CHILD, AT_FDCWD, %s) " + "failed, ret=%d\n", fd_notify, fname, ret); + } + tst_res(TINFO, "add notify mark\n"); + res = SAFE_READ(0, fd_notify, buffer, 4096); + data = (struct fanotify_event_metadata *) buffer; + while (FAN_EVENT_OK(data, res)) { + show_data(data); + if (data->pid == tid) + tst_res(TFAIL, "data->pid == envent task thread id %u\n", tid); + else if (data->pid == tgid) + tst_res(TPASS, "data->pid %u != envent task thread id %u\n", data->pid, tid); + else + tst_res(TINFO, "Environmental interference....\n"); + close(data->fd); + data = FAN_EVENT_NEXT(data, res); + } + fflush(stdout); + + /* Remove mark to clear FAN_MARK_IGNORED_SURV_MODIFY */ + ret = fanotify_mark(fd_notify, FAN_MARK_REMOVE, FAN_CLOSE | FAN_OPEN | FAN_EVENT_ON_CHILD, AT_FDCWD, fname); + if (ret != 0) { + tst_brk(TBROK, "fanotify_mark (%d, FAN_MARK_REMOVE, FAN_CLOSE | FAN_OPEN | FAN_EVENT_ON_CHILD, AT_FDCWD, %s) " + "failed, ret=%d\n", fd_notify, fname, ret); + } + tst_res(TINFO, "remove notify mark\n"); +} + +static void setup(void) +{ + pthread_t p_id; + + tgid = getpid(); + sprintf(fname, "tfile_%d", tgid); + mkdir(fname, 0755); + + fd_notify = SAFE_FANOTIFY_INIT(0, 0); + if (fd_notify < 0) + tst_brk(TCONF, "no support\n"); + pthread_create(&p_id, NULL, thread_create_file, NULL); +} + +static void cleanup(void) +{ + if (fd_notify > 0) + SAFE_CLOSE(fd_notify); + rmdir(fname); +} + +static struct tst_test test = { + .test_all = test01, + .setup = setup, + .cleanup = cleanup, + .needs_tmpdir = 1, + .needs_root = 1 +}; + +#else +TST_TEST_TCONF("system doesn't have required fanotify support"); +#endif diff --git a/testcases/kernel/syscalls/fanotify/fanotify_info_tid.c b/testcases/kernel/syscalls/fanotify/fanotify_info_tid.c new file mode 100644 index 0000000..4baf714 --- /dev/null +++ b/testcases/kernel/syscalls/fanotify/fanotify_info_tid.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013 SUSE. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Started by nixiaoming + * + * DESCRIPTION + * After fanotify_init adds flags FAN_EVENT_INFO_TID, + * check whether the program can accurately identify which thread id + * in the multithreaded program triggered the event.. + * + * This is a regression test for commit 55c5b2ed10331c3b22: + * + * fanotify: support reporting thread id instead of process id + */ +#define _GNU_SOURCE +#include "config.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tst_test.h" +#include "fanotify.h" + +#if defined(HAVE_SYS_FANOTIFY_H) +#include +#ifdef FAN_EVENT_INFO_TID + +#define BUF_SIZE 256 +#define gettid() syscall(SYS_gettid) + +static char fname[BUF_SIZE]; +int fd_notify; + +static int tid; +static int tgid; +static char tid_file[BUF_SIZE]; + +void *thread_create_file(void *arg LTP_ATTRIBUTE_UNUSED) +{ + int fd; + + tid = gettid(); + snprintf(tid_file, sizeof(tid_file), "%s/test_tid_%d", fname, tid); + sleep(1); + fd = SAFE_OPEN(tid_file, O_WRONLY|O_CREAT, 0600); + tst_res(TINFO, "open file=%s. fd=%d, tid=%i\n", tid_file, fd, tid); + SAFE_WRITE(1, fd, tid_file, sizeof(tid_file)); + tst_res(TINFO, "write file=%s. fd=%d, tid=%i\n", tid_file, fd, tid); + SAFE_CLOSE(fd); + tst_res(TINFO, "close file=%s. fd=%d, tid=%i\n", tid_file, fd, tid); + SAFE_UNLINK(tid_file); + tst_res(TINFO, "unlink file=%s. fd=%d, tid=%i\n", tid_file, fd, tid); + sleep(1); + pthread_exit(0); +} + +static const char* mask2str(uint64_t mask) +{ + static char buffer[10]; + int offset = 0; + + if (mask & FAN_ACCESS) + buffer[offset++] = 'R'; + if (mask & FAN_ONDIR) + buffer[offset++] = 'D'; + if (mask & FAN_OPEN) + buffer[offset++] = 'O'; + if (mask & FAN_CLOSE_WRITE || mask & FAN_CLOSE_NOWRITE) + buffer[offset++] = 'C'; + if (mask & FAN_MODIFY || mask & FAN_CLOSE_WRITE) + buffer[offset++] = 'W'; + buffer[offset] = '\0'; + + return buffer; +} + + +static void show_data(const struct fanotify_event_metadata *data) +{ + static char printbuf[100]; + static char pathname[PATH_MAX]; + struct stat st; + int len; + + snprintf(printbuf, sizeof(printbuf), "/proc/self/fd/%i", data->fd); + len = readlink(printbuf, pathname, sizeof(pathname)); + if (len < 0) { + /* fall back to the device/inode */ + if (fstat(data->fd, &st) < 0) { + perror("stat"); + exit(1); + } + snprintf(pathname, sizeof(pathname), "device %i:%i inode %ld\n", + major(st.st_dev), minor(st.st_dev), st.st_ino); + } else { + pathname[len] = '\0'; + } + tst_res(TINFO, "envnt: %i %s %s\n", data->pid, mask2str(data->mask), + pathname); +} + +void test01(void) +{ + int res; + int ret; + char buffer[4096] = {0}; + struct fanotify_event_metadata *data; + + ret = fanotify_mark(fd_notify, FAN_MARK_ADD, FAN_CLOSE | FAN_OPEN | FAN_EVENT_ON_CHILD, AT_FDCWD, fname); + if (ret != 0) { + tst_brk(TBROK, "fanotify_mark (%d, FAN_MARK_ADD, FAN_CLOSE | FAN_OPEN |FAN_EVENT_ON_CHILD, AT_FDCWD, %s) " + "failed, ret=%d\n", fd_notify, fname, ret); + } + tst_res(TINFO, "add notify mark\n"); + res = SAFE_READ(0, fd_notify, buffer, 4096); + data = (struct fanotify_event_metadata *) buffer; + while (FAN_EVENT_OK(data, res)) { + show_data(data); + if (data->pid == tid) + tst_res(TPASS, "data->pid == envent task thread id %u\n", tid); + else if (data->pid == tgid) + tst_res(TFAIL, "data->pid %u != envent task thread id %u\n", data->pid, tid); + else + tst_res(TINFO, "Environmental interference....\n"); + close(data->fd); + data = FAN_EVENT_NEXT(data, res); + } + fflush(stdout); + + /* Remove mark to clear FAN_MARK_IGNORED_SURV_MODIFY */ + ret = fanotify_mark(fd_notify, FAN_MARK_REMOVE, FAN_CLOSE | FAN_OPEN | FAN_EVENT_ON_CHILD, AT_FDCWD, fname); + if (ret != 0) { + tst_brk(TBROK, "fanotify_mark (%d, FAN_MARK_REMOVE, FAN_CLOSE | FAN_OPEN | FAN_EVENT_ON_CHILD, AT_FDCWD, %s) " + "failed, ret=%d\n", fd_notify, fname, ret); + } + tst_res(TINFO, "remove notify mark\n"); +} + +static void setup(void) +{ + pthread_t p_id; + + tgid = getpid(); + sprintf(fname, "tfile_%d", tgid); + mkdir(fname, 0755); + + fd_notify = SAFE_FANOTIFY_INIT(FAN_EVENT_INFO_TID, 0); + if (fd_notify < 0) + tst_brk(TCONF, "no support FAN_EVENT_INFO_TID\n"); + pthread_create(&p_id, NULL, thread_create_file, NULL); +} + +static void cleanup(void) +{ + if (fd_notify > 0) + SAFE_CLOSE(fd_notify); + rmdir(fname); +} + +static struct tst_test test = { + .test_all = test01, + .setup = setup, + .cleanup = cleanup, + .needs_tmpdir = 1, + .needs_root = 1 +}; + +#else +TST_TEST_TCONF("system doesn't support fanotify_init flags: FAN_EVENT_INFO_TID"); +#endif /* ifdef FAN_EVENT_INFO_TID */ + +#else +TST_TEST_TCONF("system doesn't have required fanotify support"); +#endif