Implement name_to_handle_at and open_by_handle_at syscalls decoding

* 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.
This commit is contained in:
Дмитрий Левин 2015-11-22 21:29:32 +00:00
parent 60d7524090
commit 4b3a1703bd
8 changed files with 261 additions and 2 deletions

View File

@ -63,6 +63,7 @@ strace_SOURCES = \
fcntl.c \
fetch_seccomp_fprog.c \
file.c \
file_handle.c \
flock.c \
futex.c \
get_robust_list.c \

140
file_handle.c Normal file
View File

@ -0,0 +1,140 @@
/*
* 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;
}

View File

@ -32,8 +32,6 @@
#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

View File

@ -178,6 +178,7 @@ pathtrace_match(struct tcb *tcp)
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:

1
tests/.gitignore vendored
View File

@ -9,6 +9,7 @@ eventfd
execve
execveat
fanotify_mark
file_handle
filter-unavailable
getdents
getdents64

View File

@ -22,6 +22,7 @@ check_PROGRAMS = \
execve \
execveat \
fanotify_mark \
file_handle \
filter-unavailable \
getdents \
getdents64 \
@ -122,6 +123,7 @@ TESTS = \
execve.test \
execveat.test \
fanotify_mark.test \
file_handle.test \
filter-unavailable.test \
getdents.test \
getdents64.test \

101
tests/file_handle.c Normal file
View File

@ -0,0 +1,101 @@
/*
* 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

15
tests/file_handle.test Executable file
View File

@ -0,0 +1,15 @@
#!/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