* file_handle.c: New file.
* Makefile.am (strace_SOURCES): Add it.
* linux/dummy.h (sys_name_to_handle_at, sys_open_by_handle_at):
Remove stub aliases.
* pathtrace.c (pathtrace_match): Add SEN_name_to_handle_at.
* tests/file_handle.c: New file.
* tests/file_handle.test: New test.
* tests/Makefile.am (check_PROGRAMS): Add file_handle.
(TESTS): Add file_handle.test.
* tests/.gitignore: Add file_handle.
fcntl.c \
fetch_seccomp_fprog.c \
file.c \
+ file_handle.c \
flock.c \
futex.c \
get_robust_list.c \
--- /dev/null
+/*
+ * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
+ * 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 "defs.h"
+
+#ifndef MAX_HANDLE_SZ
+# define MAX_HANDLE_SZ 128
+#endif
+
+typedef struct {
+ unsigned int handle_bytes;
+ int handle_type;
+} file_handle_header;
+
+SYS_FUNC(name_to_handle_at)
+{
+ file_handle_header h;
+ const long addr = tcp->u_arg[2];
+
+ if (entering(tcp)) {
+ /* dirfd */
+ print_dirfd(tcp, tcp->u_arg[0]);
+
+ /* pathname */
+ printpath(tcp, tcp->u_arg[1]);
+ tprints(", ");
+
+ /* handle */
+ if (umove_or_printaddr(tcp, addr, &h)) {
+ tprints(", ");
+
+ /* mount_id */
+ printaddr(tcp->u_arg[3]);
+ tprints(", ");
+
+ /* flags */
+ printflags(at_flags, tcp->u_arg[4], "AT_???");
+
+ return RVAL_DECODED;
+ }
+ tprintf("{handle_bytes=%u", h.handle_bytes);
+
+ /*
+ * Abusing tcp->auxstr as a temporary storage.
+ * Will be used and cleared on syscall exit.
+ */
+ tcp->auxstr = (void *) (unsigned long) h.handle_bytes;
+
+ return 0;
+ } else {
+ unsigned int i = (unsigned long) tcp->auxstr;
+
+ if ((!syserror(tcp) || EOVERFLOW == tcp->u_error)
+ && !umove(tcp, addr, &h)) {
+ unsigned char f_handle[MAX_HANDLE_SZ];
+
+ if (i != h.handle_bytes)
+ tprintf(" => %u", h.handle_bytes);
+ if (!syserror(tcp)) {
+ tprintf(", handle_type=%d", h.handle_type);
+ if (h.handle_bytes > MAX_HANDLE_SZ)
+ h.handle_bytes = MAX_HANDLE_SZ;
+ if (!umoven(tcp, addr + sizeof(h), h.handle_bytes,
+ f_handle)) {
+ tprints(", f_handle=0x");
+ for (i = 0; i < h.handle_bytes; ++i)
+ tprintf("%02x", f_handle[i]);
+ }
+ }
+ }
+ tprints("}, ");
+ tcp->auxstr = NULL;
+
+ /* mount_id */
+ printnum_int(tcp, tcp->u_arg[3], "%d");
+ tprints(", ");
+
+ /* flags */
+ printflags(at_flags, tcp->u_arg[4], "AT_???");
+ }
+ return 0;
+}
+
+SYS_FUNC(open_by_handle_at)
+{
+ file_handle_header h;
+ const long addr = tcp->u_arg[1];
+
+ /* mount_fd */
+ printfd(tcp, tcp->u_arg[0]);
+ tprints(", ");
+
+ /* handle */
+ if (!umove_or_printaddr(tcp, addr, &h)) {
+ unsigned char f_handle[MAX_HANDLE_SZ];
+
+ tprintf("{handle_bytes=%u, handle_type=%d",
+ h.handle_bytes, h.handle_type);
+ if (h.handle_bytes > MAX_HANDLE_SZ)
+ h.handle_bytes = MAX_HANDLE_SZ;
+ if (!umoven(tcp, addr + sizeof(h), h.handle_bytes, &f_handle)) {
+ unsigned int i;
+
+ tprints(", f_handle=0x");
+ for (i = 0; i < h.handle_bytes; ++i)
+ tprintf("%02x", f_handle[i]);
+ }
+ tprints("}");
+ }
+ tprints(", ");
+
+ /* flags */
+ tprint_open_modes(tcp->u_arg[2]);
+
+ return RVAL_DECODED;
+}
#endif
/* still unfinished */
-#define sys_name_to_handle_at printargs
-#define sys_open_by_handle_at printargs
#define sys_sysfs printargs
#define sys_vm86 printargs
#define sys_vm86old printargs
case SEN_inotify_add_watch:
case SEN_mkdirat:
case SEN_mknodat:
+ case SEN_name_to_handle_at:
case SEN_newfstatat:
case SEN_openat:
case SEN_pipe2:
execve
execveat
fanotify_mark
+file_handle
filter-unavailable
getdents
getdents64
execve \
execveat \
fanotify_mark \
+ file_handle \
filter-unavailable \
getdents \
getdents64 \
execve.test \
execveat.test \
fanotify_mark.test \
+ file_handle.test \
filter-unavailable.test \
getdents.test \
getdents64.test \
--- /dev/null
+/*
+ * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <alloca.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#ifdef MAX_HANDLE_SZ
+
+int
+main(void)
+{
+ struct file_handle *handle =
+ alloca(sizeof(struct file_handle) + MAX_HANDLE_SZ);
+ const int dirfd = AT_FDCWD;
+ const int flags = AT_SYMLINK_FOLLOW;
+ int mount_id;
+ unsigned int i;
+
+ handle->handle_bytes = 0;
+
+ if (name_to_handle_at(dirfd, ".", handle, &mount_id, flags | 1) != -1
+ || EINVAL != errno) {
+ perror("name_to_handle_at");
+ return 77;
+ }
+ printf("name_to_handle_at(AT_FDCWD, \".\", {handle_bytes=0}, %p"
+ ", AT_SYMLINK_FOLLOW|0x1) = -1 EINVAL (Invalid argument)\n",
+ &mount_id);
+
+ if (name_to_handle_at(dirfd, ".", handle, &mount_id, flags) != -1
+ || EOVERFLOW != errno) {
+ perror("name_to_handle_at");
+ return 77;
+ }
+ printf("name_to_handle_at(AT_FDCWD, \".\", {handle_bytes=0 => %u}"
+ ", %p, AT_SYMLINK_FOLLOW) = -1 EOVERFLOW"
+ " (Value too large for defined data type)\n",
+ handle->handle_bytes, &mount_id);
+
+ assert(!name_to_handle_at(dirfd, ".", handle, &mount_id, flags));
+ printf("name_to_handle_at(AT_FDCWD, \".\", {handle_bytes=%u"
+ ", handle_type=%d, f_handle=0x",
+ handle->handle_bytes, handle->handle_type);
+ for (i = 0; i < handle->handle_bytes; ++i)
+ printf("%02x", handle->f_handle[i]);
+ printf("}, [%d], AT_SYMLINK_FOLLOW) = 0\n", mount_id);
+
+ assert(open_by_handle_at(-1, handle, O_RDONLY | O_DIRECTORY));
+ printf("open_by_handle_at(-1, {handle_bytes=%u, handle_type=1, f_handle=0x",
+ handle->handle_bytes);
+ for (i = 0; i < handle->handle_bytes; ++i)
+ printf("%02x", handle->f_handle[i]);
+ printf("}, O_RDONLY|O_DIRECTORY) = -1 %s\n",
+ EPERM == errno ? "EPERM (Operation not permitted)" :
+ EINVAL == errno ? "EINVAL (Invalid argument)" :
+ "EBADF (Bad file descriptor)");
+
+ puts("+++ exited with 0 +++");
+ return 0;
+}
+
+#else
+
+int
+main(void)
+{
+ return 77;
+}
+
+#endif
--- /dev/null
+#!/bin/sh
+
+# Check name_to_handle_at and open_by_handle_at syscalls decoding.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+
+OUT="$LOG.out"
+run_strace -ename_to_handle_at,open_by_handle_at $args > "$OUT"
+
+match_diff "$OUT" "$LOG"
+rm -f "$OUT"
+
+exit 0