Add a general netlink socket parser

Introduce a general socket netlink parser which prints the header and
a string for the remaining part of the buffer.  It doesn't handle all
the netlink flags and types yet because the parser needs more
information, this will be implemented later.

* net.c (decode_sockbuf): New function.
(SYS_FUNC(send), SYS_FUNC(sendto), SYS_FUNC(recv), SYS_FUNC(recvfrom)):
Use it instead of printstr.
* msghdr.c (print_msghdr): Pass IOV_DECODE_NETLINK to tprint_iov_upto()
for netlink sockets.
* netlink.c: New file.
* Makefile.am (strace_SOURCES): Add it.
* defs.h (decode_netlink, getfdproto): New prototypes.
(iov_decode): Add IOV_DECODER_NETLINK.
* io.c (print_iovec): Use decode_netlink().
* util.c (getfdproto): Remove static keyword.
* xlat/netlink_flags.in: New file.
* xlat/netlink_types.in: New file.
This commit is contained in:
Fabien Siron 2016-07-06 15:49:22 +00:00 committed by Dmitry V. Levin
parent 7499ce0244
commit 2850f745ca
9 changed files with 119 additions and 10 deletions

View File

@ -160,6 +160,7 @@ strace_SOURCES = \
mtd.c \
native_defs.h \
net.c \
netlink.c \
numa.c \
open.c \
or1k_atomic.c \

5
defs.h
View File

@ -452,7 +452,8 @@ extern enum sock_proto get_proto_by_name(const char *);
enum iov_decode {
IOV_DECODE_ADDR,
IOV_DECODE_STR
IOV_DECODE_STR,
IOV_DECODE_NETLINK
};
typedef enum {
@ -567,6 +568,7 @@ extern const char *signame(const int);
extern void pathtrace_select(const char *);
extern int pathtrace_match(struct tcb *);
extern int getfdpath(struct tcb *, int, char *, unsigned);
extern enum sock_proto getfdproto(struct tcb *, int);
extern const char *xlookup(const struct xlat *, const uint64_t);
extern const char *xlat_search(const struct xlat *, const size_t, const uint64_t);
@ -679,6 +681,7 @@ extern void printsignal(int);
extern void tprint_iov(struct tcb *, unsigned long, unsigned long, enum iov_decode);
extern void tprint_iov_upto(struct tcb *, unsigned long, unsigned long,
enum iov_decode, unsigned long);
extern void decode_netlink(struct tcb *, unsigned long, unsigned long);
extern void tprint_open_modes(unsigned int);
extern const char *sprint_open_modes(unsigned int);
extern void print_seccomp_filter(struct tcb *, unsigned long);

6
io.c
View File

@ -88,6 +88,12 @@ print_iovec(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
c->data_size -= len;
printstr(tcp, iov[0], len);
break;
case IOV_DECODE_NETLINK:
if (len > c->data_size)
len = c->data_size;
c->data_size -= len;
decode_netlink(tcp, iov[0], iov[1]);
break;
default:
printaddr(iov[0]);
break;

View File

@ -335,13 +335,22 @@ decode_msg_control(struct tcb *tcp, unsigned long addr,
static void
print_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size)
{
int family;
enum iov_decode decode;
tprints("{msg_name=");
decode_sockaddr(tcp, (long)msg->msg_name, msg->msg_namelen);
family = decode_sockaddr(tcp, (long)msg->msg_name, msg->msg_namelen);
tprintf(", msg_namelen=%d", msg->msg_namelen);
tprints(", msg_iov=");
if (family == AF_NETLINK)
decode = IOV_DECODE_NETLINK;
else
decode = IOV_DECODE_STR;
tprint_iov_upto(tcp, (unsigned long) msg->msg_iovlen,
(unsigned long) msg->msg_iov, IOV_DECODE_STR, data_size);
(unsigned long) msg->msg_iov, decode, data_size);
tprintf(", msg_iovlen=%lu", (unsigned long) msg->msg_iovlen);
decode_msg_control(tcp, (unsigned long) msg->msg_control,

28
net.c
View File

@ -108,6 +108,19 @@ print_ifindex(unsigned int ifindex)
tprintf("%u", ifindex);
}
static void
decode_sockbuf(struct tcb *tcp, int fd, long addr, long addrlen)
{
switch (verbose(tcp) ? getfdproto(tcp, fd) : SOCK_PROTO_UNKNOWN) {
case SOCK_PROTO_NETLINK:
decode_netlink(tcp, addr, addrlen);
break;
default:
printstr(tcp, addr, addrlen);
}
}
/*
* low bits of the socket type define real socket type,
* other bits are socket type flags.
@ -220,7 +233,7 @@ SYS_FUNC(send)
{
printfd(tcp, tcp->u_arg[0]);
tprints(", ");
printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
tprintf(", %lu, ", tcp->u_arg[2]);
/* flags */
printflags(msg_flags, tcp->u_arg[3], "MSG_???");
@ -232,7 +245,7 @@ SYS_FUNC(sendto)
{
printfd(tcp, tcp->u_arg[0]);
tprints(", ");
printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
tprintf(", %lu, ", tcp->u_arg[2]);
/* flags */
printflags(msg_flags, tcp->u_arg[3], "MSG_???");
@ -287,10 +300,12 @@ SYS_FUNC(recv)
printfd(tcp, tcp->u_arg[0]);
tprints(", ");
} else {
if (syserror(tcp))
if (syserror(tcp)) {
printaddr(tcp->u_arg[1]);
else
printstr(tcp, tcp->u_arg[1], tcp->u_rval);
} else {
decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
tcp->u_rval);
}
tprintf(", %lu, ", tcp->u_arg[2]);
printflags(msg_flags, tcp->u_arg[3], "MSG_???");
@ -310,7 +325,8 @@ SYS_FUNC(recvfrom)
if (syserror(tcp)) {
printaddr(tcp->u_arg[1]);
} else {
printstr(tcp, tcp->u_arg[1], tcp->u_rval);
decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
tcp->u_rval);
}
/* len */
tprintf(", %lu, ", tcp->u_arg[2]);

64
netlink.c Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
* 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"
#include <sys/socket.h>
#include <linux/netlink.h>
#include "xlat/netlink_flags.h"
#include "xlat/netlink_types.h"
void
decode_netlink(struct tcb *tcp, unsigned long addr, unsigned long size)
{
struct nlmsghdr nlmsghdr;
if (size < sizeof(struct nlmsghdr)) {
printstr(tcp, addr, size);
return;
}
if (umove_or_printaddr(tcp, addr, &nlmsghdr))
return;
tprintf("{{len=%u, type=", nlmsghdr.nlmsg_len);
printxval(netlink_types, nlmsghdr.nlmsg_type, "NLMSG_???");
tprints(", flags=");
printflags(netlink_flags, nlmsghdr.nlmsg_flags, "NLM_F_???");
/* manage get/new requests */
tprintf(", seq=%u, pid=%u}", nlmsghdr.nlmsg_seq,
nlmsghdr.nlmsg_pid);
if (size - sizeof(struct nlmsghdr) > 0) {
tprints(", ");
printstr(tcp, addr + sizeof(struct nlmsghdr),
size - sizeof(struct nlmsghdr));
}
tprints("}");
}

2
util.c
View File

@ -472,7 +472,7 @@ sprinttime(time_t t)
return buf;
}
static enum sock_proto
enum sock_proto
getfdproto(struct tcb *tcp, int fd)
{
#ifdef HAVE_SYS_XATTR_H

6
xlat/netlink_flags.in Normal file
View File

@ -0,0 +1,6 @@
NLM_F_REQUEST 0x1
NLM_F_MULTI 0x2
NLM_F_ACK 0x4
NLM_F_ECHO 0x8
NLM_F_DUMP_INTR 0x10
NLM_F_DUMP_FILTERED 0x20

4
xlat/netlink_types.in Normal file
View File

@ -0,0 +1,4 @@
NLMSG_NOOP 0x1
NLMSG_ERROR 0x2
NLMSG_DONE 0x3
NLMSG_OVERRUN 0x4