From: Eugene Syromyatnikov <evgsyr@gmail.com>
Date: Mon, 24 Sep 2018 06:02:38 +0000 (+0200)
Subject: inotify: decode file descriptor returned by inotify_init
X-Git-Tag: v5.2~15
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=879bc9caacd5d2827d83e27ca4a4ea1a3fea968d;p=strace

inotify: decode file descriptor returned by inotify_init

* inotify.c (SYS_FUNC(inotify_init)): New function.
* linux/dummy.h (sys_inotify_init): Remove macro definition.
* tests/inotify_init.c: New file.
* tests/inotify_init-y.c: Likewise.
* tests/inotify_init1-y.c: Likewise.
* tests/inotify_init1.c [PRINT_PATHS]: Print inotify fd path.
* tests/inotify_init-y.test: New test.
* tests/.gitignore: Add inotify_init, inotify_init-y, inotify_init1-y.
* tests/pure_executables.list: Likewise.
* tests/gen_tests.in (inotify_init, inotify_init1-y): New tests.
* tests/Makefile.am (DECODER_TESTS): Add inotify_init-y.test.
---

diff --git a/inotify.c b/inotify.c
index e12df34b..cd1562f9 100644
--- a/inotify.c
+++ b/inotify.c
@@ -36,6 +36,11 @@ SYS_FUNC(inotify_rm_watch)
 	return RVAL_DECODED;
 }
 
+SYS_FUNC(inotify_init)
+{
+	return RVAL_DECODED | RVAL_FD;
+}
+
 SYS_FUNC(inotify_init1)
 {
 	printflags(inotify_init_flags, tcp->u_arg[0], "IN_???");
diff --git a/linux/dummy.h b/linux/dummy.h
index 15621bd5..2f859a60 100644
--- a/linux/dummy.h
+++ b/linux/dummy.h
@@ -92,7 +92,6 @@
 # define sys_getppid		printargs
 # define sys_gettid		printargs
 # define sys_idle		printargs
-# define sys_inotify_init	printargs
 # define sys_munlockall		printargs
 # define sys_pause		printargs
 # define sys_printargs		printargs
diff --git a/tests/.gitignore b/tests/.gitignore
index 1a2a653f..59c71e00 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -148,7 +148,10 @@ inet-cmsg
 init_module
 inject-nf
 inotify
+inotify_init
+inotify_init-y
 inotify_init1
+inotify_init1-y
 int_0x80
 io_uring_enter
 io_uring_register
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7247a597..a6b79d07 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -234,6 +234,7 @@ DECODER_TESTS = \
 	futex.test \
 	getuid.test \
 	int_0x80.test \
+	inotify_init-y.test \
 	ioctl.test \
 	ioctl_evdev-success-v.test \
 	ioctl_evdev-success.test \
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index db162bc6..22e8c93a 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -123,7 +123,9 @@ group_req	-e trace=setsockopt
 inet-cmsg	-e trace=recvmsg
 init_module	-a27
 inotify	-a23 -e trace=inotify_add_watch,inotify_rm_watch
+inotify_init	-a15
 inotify_init1	-a27
+inotify_init1-y	-a27 -y -e trace=inotify_init1
 io_uring_enter	-y
 io_uring_register	-y
 io_uring_setup	-a26 -y
diff --git a/tests/inotify_init-y.c b/tests/inotify_init-y.c
new file mode 100644
index 00000000..cbe094ba
--- /dev/null
+++ b/tests/inotify_init-y.c
@@ -0,0 +1,2 @@
+#define PRINT_PATHS
+#include "inotify_init.c"
diff --git a/tests/inotify_init-y.test b/tests/inotify_init-y.test
new file mode 100755
index 00000000..69021c93
--- /dev/null
+++ b/tests/inotify_init-y.test
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Check decoding of inotify_init with path decoding enabled.
+#
+# Copyright (c) 2019 The strace developers.
+# All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+. "${srcdir=.}/init.sh"
+
+# Test expects "anon_inode:inotify" link path format for a inotify fd, which
+# is in place since v2.6.33-rc1~34^2~7. Check for older link path formats
+# is implemented in inotify_init1 test.
+require_min_kernel_version_or_skip 2.6.33
+
+run_strace_match_diff -a15 -y -e trace=inotify_init
diff --git a/tests/inotify_init.c b/tests/inotify_init.c
new file mode 100644
index 00000000..363811cc
--- /dev/null
+++ b/tests/inotify_init.c
@@ -0,0 +1,49 @@
+/*
+ * Check decoding of inotify_init syscall.
+ *
+ * Copyright (c) 2018-2019 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+#include <asm/unistd.h>
+#include "scno.h"
+
+#ifdef __NR_inotify_init
+
+# include <stdio.h>
+# include <unistd.h>
+
+int
+main(void)
+{
+#ifdef PRINT_PATHS
+	skip_if_unavailable("/proc/self/fd/");
+#endif
+
+	long rc = syscall(__NR_inotify_init, 42);
+
+#ifdef PRINT_PATHS
+	if (rc < 0)
+		perror_msg_and_skip("inotify_init");
+#endif
+
+	printf("inotify_init() = "
+#ifdef PRINT_PATHS
+	       "%ld<anon_inode:inotify>\n", rc
+#else
+	       "%s\n", sprintrc(rc)
+#endif
+	       );
+
+	puts("+++ exited with 0 +++");
+	return 0;
+}
+
+#else
+
+SKIP_MAIN_UNDEFINED("__NR_inotify_init");
+
+#endif
diff --git a/tests/inotify_init1-y.c b/tests/inotify_init1-y.c
new file mode 100644
index 00000000..53c65e66
--- /dev/null
+++ b/tests/inotify_init1-y.c
@@ -0,0 +1,2 @@
+#define PRINT_PATHS
+#include "inotify_init1.c"
diff --git a/tests/inotify_init1.c b/tests/inotify_init1.c
index 4f352b70..2408b647 100644
--- a/tests/inotify_init1.c
+++ b/tests/inotify_init1.c
@@ -25,9 +25,19 @@
 # endif
 # define all_flags (O_NONBLOCK | cloexec_flag)
 
+#ifdef PRINT_PATHS
+# define RC_FMT "%ld<%s>"
+#else
+# define RC_FMT "%s"
+#endif
+
 int
 main(void)
 {
+#ifdef PRINT_PATHS
+	skip_if_unavailable("/proc/self/fd/");
+#endif
+
 	static const kernel_ulong_t bogus_flags1 =
 		(kernel_ulong_t) 0xfacefeeddeadbeefULL | O_NONBLOCK;
 	static const kernel_ulong_t bogus_flags2 =
@@ -46,8 +56,51 @@ main(void)
 	       (unsigned int) bogus_flags2, sprintrc(rc));
 
 	rc = syscall(__NR_inotify_init1, all_flags);
-	printf("inotify_init1(IN_NONBLOCK%s) = %s\n",
-	       all_flags & cloexec_flag ? "|IN_CLOEXEC" : "", sprintrc(rc));
+
+#ifdef PRINT_PATHS
+	if (rc < 0)
+		perror_msg_and_skip("inotify_init(%#x)", all_flags);
+
+	/*
+	 * Kernels that do not have v2.6.33-rc1~34^2~7 do not have
+	 * "anon_inode:" prefix.  Let's assume that it can be either "inotify"
+	 * or "anon_inode:inotify" for now, as any change there may be
+	 * of interest.
+	 */
+	char path[sizeof("/proc/self/fd/") + sizeof(rc) * 3];
+	char buf[2] = "";
+	const char *inotify_path;
+	ssize_t ret;
+
+	ret = snprintf(path, sizeof(path), "/proc/self/fd/%ld", rc);
+	if ((ret < 0) || ((size_t) ret >= sizeof(path)))
+		perror_msg_and_fail("snprintf(path)");
+
+	ret = readlink(path, buf, sizeof(buf));
+	if (ret < 0)
+		perror_msg_and_fail("readlink");
+
+	switch (buf[0]) {
+	case 'a':
+		inotify_path = "anon_inode:inotify";
+		break;
+	case 'i':
+		inotify_path = "inotify";
+		break;
+	default:
+		error_msg_and_fail("Unexpected first char '%c' of inotify fd "
+				   "link path", buf[0]);
+	}
+#endif
+
+	printf("inotify_init1(IN_NONBLOCK%s) = " RC_FMT "\n",
+	       all_flags & cloexec_flag ? "|IN_CLOEXEC" : "",
+#ifdef PRINT_PATHS
+	       rc, inotify_path
+#else
+	       sprintrc(rc)
+#endif
+	       );
 
 	puts("+++ exited with 0 +++");
 
diff --git a/tests/pure_executables.list b/tests/pure_executables.list
index d306085e..58749797 100755
--- a/tests/pure_executables.list
+++ b/tests/pure_executables.list
@@ -126,7 +126,10 @@ group_req
 inet-cmsg
 init_module
 inotify
+inotify_init
+inotify_init-y
 inotify_init1
+inotify_init1-y
 io_uring_enter
 io_uring_register
 io_uring_setup