Fix decoding of struct msghdr.msg_name* arguments of recvmsg syscall
As the msghdr.msg_namelen argument of recvmsg syscall has the same read-write semantics as the address length argument of recvfrom syscall, parser of recvmsg syscall needs a similar fix. * defs.h (fetch_msghdr_namelen): New prototype. (decode_msghdr): Add "int *" argument. * msghdr.c (print_msghdr): Likewise. Treat it as a pointer to struct msghdr.msg_namelen passed to the kernel. Pass to decode_sockaddr the size of socket address actually returned by the kernel. Print both user and kernel address lengths when the value changes. (decode_msghdr, decode_mmsghdr): Add "int *" argument, forward it to print_msghdr. (decode_mmsgvec): Update decode_mmsghdr invocation. (fetch_msghdr_namelen): New function. * net.c (SYS_FUNC(sendmsg)): Update decode_msghdr invocation. (SYS_FUNC(recvmsg)): Use fetch_msghdr_namelen on entering to save struct msghdr.msg_namelen. On exiting, pass the saved value to decode_msghdr.
This commit is contained in:
parent
766e1d9928
commit
d8f77cdf42
3
defs.h
3
defs.h
@ -609,7 +609,8 @@ extern int printflags64(const struct xlat *, uint64_t, const char *);
|
||||
extern const char *sprintflags(const char *, const struct xlat *, uint64_t);
|
||||
extern const char *sprintmode(unsigned int);
|
||||
extern const char *sprinttime(time_t);
|
||||
extern void decode_msghdr(struct tcb *, long, unsigned long);
|
||||
extern bool fetch_msghdr_namelen(struct tcb *, long, int *);
|
||||
extern void decode_msghdr(struct tcb *, const int *, long, unsigned long);
|
||||
extern void decode_mmsgvec(struct tcb *, unsigned long, unsigned int, bool);
|
||||
extern void dumpiov_in_msghdr(struct tcb *, long, unsigned long);
|
||||
extern void dumpiov_in_mmsghdr(struct tcb *, long);
|
||||
|
51
msghdr.c
51
msghdr.c
@ -333,22 +333,27 @@ decode_msg_control(struct tcb *tcp, unsigned long addr,
|
||||
}
|
||||
|
||||
static void
|
||||
print_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size)
|
||||
print_msghdr(struct tcb *tcp, const struct msghdr *msg,
|
||||
const int *const p_user_msg_namelen,
|
||||
const unsigned long data_size)
|
||||
{
|
||||
int family;
|
||||
enum iov_decode decode;
|
||||
const int msg_namelen =
|
||||
p_user_msg_namelen && (int) msg->msg_namelen > *p_user_msg_namelen
|
||||
? *p_user_msg_namelen : (int) msg->msg_namelen;
|
||||
|
||||
tprints("{msg_name=");
|
||||
family = decode_sockaddr(tcp, (long)msg->msg_name, msg->msg_namelen);
|
||||
tprintf(", msg_namelen=%d", msg->msg_namelen);
|
||||
const int family =
|
||||
decode_sockaddr(tcp, (long) msg->msg_name, msg_namelen);
|
||||
const enum iov_decode decode =
|
||||
(family == AF_NETLINK) ? IOV_DECODE_NETLINK : IOV_DECODE_STR;
|
||||
|
||||
tprints(", msg_namelen=");
|
||||
if (p_user_msg_namelen && *p_user_msg_namelen != (int) msg->msg_namelen)
|
||||
tprintf("%d->", *p_user_msg_namelen);
|
||||
tprintf("%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, decode, data_size);
|
||||
tprintf(", msg_iovlen=%lu", (unsigned long) msg->msg_iovlen);
|
||||
@ -362,13 +367,27 @@ print_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size)
|
||||
tprints("}");
|
||||
}
|
||||
|
||||
bool
|
||||
fetch_msghdr_namelen(struct tcb *tcp, const long addr, int *const p_msg_namelen)
|
||||
{
|
||||
struct msghdr msg;
|
||||
|
||||
if (addr && verbose(tcp) && fetch_struct_msghdr(tcp, addr, &msg)) {
|
||||
*p_msg_namelen = msg.msg_namelen;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
decode_msghdr(struct tcb *tcp, long addr, unsigned long data_size)
|
||||
decode_msghdr(struct tcb *tcp, const int *const p_user_msg_namelen,
|
||||
const long addr, const unsigned long data_size)
|
||||
{
|
||||
struct msghdr msg;
|
||||
|
||||
if (addr && verbose(tcp) && fetch_struct_msghdr(tcp, addr, &msg))
|
||||
print_msghdr(tcp, &msg, data_size);
|
||||
print_msghdr(tcp, &msg, p_user_msg_namelen, data_size);
|
||||
else
|
||||
printaddr(addr);
|
||||
}
|
||||
@ -383,14 +402,16 @@ dumpiov_in_msghdr(struct tcb *tcp, long addr, unsigned long data_size)
|
||||
}
|
||||
|
||||
static int
|
||||
decode_mmsghdr(struct tcb *tcp, long addr, bool use_msg_len)
|
||||
decode_mmsghdr(struct tcb *tcp, const int *const p_user_msg_namelen,
|
||||
const long addr, const bool use_msg_len)
|
||||
{
|
||||
struct mmsghdr mmsg;
|
||||
int fetched = fetch_struct_mmsghdr(tcp, addr, &mmsg);
|
||||
|
||||
if (fetched) {
|
||||
tprints("{msg_hdr=");
|
||||
print_msghdr(tcp, &mmsg.msg_hdr, use_msg_len ? mmsg.msg_len : -1UL);
|
||||
print_msghdr(tcp, &mmsg.msg_hdr, p_user_msg_namelen,
|
||||
use_msg_len ? mmsg.msg_len : -1UL);
|
||||
tprintf(", msg_len=%u}", mmsg.msg_len);
|
||||
} else {
|
||||
printaddr(addr);
|
||||
@ -412,7 +433,7 @@ decode_mmsgvec(struct tcb *tcp, unsigned long addr, unsigned int len,
|
||||
for (i = 0; i < len; ++i, addr += fetched) {
|
||||
if (i)
|
||||
tprints(", ");
|
||||
fetched = decode_mmsghdr(tcp, addr, use_msg_len);
|
||||
fetched = decode_mmsghdr(tcp, 0, addr, use_msg_len);
|
||||
if (!fetched)
|
||||
break;
|
||||
}
|
||||
|
28
net.c
28
net.c
@ -286,7 +286,7 @@ SYS_FUNC(sendmsg)
|
||||
{
|
||||
printfd(tcp, tcp->u_arg[0]);
|
||||
tprints(", ");
|
||||
decode_msghdr(tcp, tcp->u_arg[1], (unsigned long) -1L);
|
||||
decode_msghdr(tcp, 0, tcp->u_arg[1], (unsigned long) -1L);
|
||||
/* flags */
|
||||
tprints(", ");
|
||||
printflags(msg_flags, tcp->u_arg[2], "MSG_???");
|
||||
@ -393,19 +393,33 @@ SYS_FUNC(recvfrom)
|
||||
|
||||
SYS_FUNC(recvmsg)
|
||||
{
|
||||
int msg_namelen;
|
||||
|
||||
if (entering(tcp)) {
|
||||
printfd(tcp, tcp->u_arg[0]);
|
||||
tprints(", ");
|
||||
if (fetch_msghdr_namelen(tcp, tcp->u_arg[1], &msg_namelen)) {
|
||||
/* abuse of auxstr to retain state */
|
||||
tcp->auxstr = (void *) (long) msg_namelen;
|
||||
return 0;
|
||||
}
|
||||
printaddr(tcp->u_arg[1]);
|
||||
} else {
|
||||
msg_namelen = (long) tcp->auxstr;
|
||||
tcp->auxstr = NULL;
|
||||
|
||||
if (syserror(tcp))
|
||||
printaddr(tcp->u_arg[1]);
|
||||
tprintf("{msg_namelen=%d}", msg_namelen);
|
||||
else
|
||||
decode_msghdr(tcp, tcp->u_arg[1], tcp->u_rval);
|
||||
/* flags */
|
||||
tprints(", ");
|
||||
printflags(msg_flags, tcp->u_arg[2], "MSG_???");
|
||||
decode_msghdr(tcp, &msg_namelen, tcp->u_arg[1],
|
||||
tcp->u_rval);
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* flags */
|
||||
tprints(", ");
|
||||
printflags(msg_flags, tcp->u_arg[2], "MSG_???");
|
||||
|
||||
return RVAL_DECODED;
|
||||
}
|
||||
|
||||
SYS_FUNC(recvmmsg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user