[<prev] [next>] [day] [month] [year] [list]
Message-ID: <6c60b9fb-c578-82ec-d422-a49169f077b6@informatik.uni-wuerzburg.de>
Date: Tue, 19 Dec 2017 13:40:48 +0100
From: Stefan Geißler
<stefan.geissler@...ormatik.uni-wuerzburg.de>
To: netdev@...r.kernel.org
Subject: Reading header and payload at sock_recvmsg() and sock_sendmsg()
Hello netdev mailing list,
I am a PhD student from Germany and currently working on a project that
involves monitoring packets as they are passed from kernel space towards
user space applications. To achieve this, I applied the attached patch
to Kernel v4.4 and implemented the two functions below that are called
from - and with the parameters of - sock_recvmsg() and sock_sendmsg().
For every incoming packet I check if it belongs to the process I want to
monitor. If so, I get the header information as well as the payload and
save the current timestamp. Finally and set the current state to monitor
for the transmission of this packet. Then I compare the payloads of
outgoing packets until a match is found and print the time it took this
packet to travel through the user space.
However, I seem to be unable to get the socket information and data for
incoming packets in __i3_recv_monitor(), as the debug output is always
something like
Dec 19 08:49:51 localhost kernel: [413608.826373] [Packet received]
(13739)0.0.0.0;0;0.0.0.0;0;0;413595528124549
Dec 19 08:49:51 localhost kernel: [413608.831397] [Received data] (null)
Regarding outgoing packets in __i3_send_monitor(), I am at least able to
get the network information from the socket. My data pointer is empty as
well.
Dec 19 09:00:20 localhost kernel: [414238.178057] [Packet send]
(13739)192.168.200.19;36628;192.168.200.20;45110;6;414224859396846
Dec 19 09:00:20 localhost kernel: [414238.181216] [Send data] (null)
The context is that I want to monitor packet processing times of user
space applications that do not alter the payload before retransmitting
packets.
I was hoping that someone with more experience of the network stack
could point me towards what I am missing or doing wrong here.
I hope this is not totally the wrong place to ask such a question and
already thank you in advance!
Best regards,
Stefan
--------------------------------------------------------
void __i3_recv_monitor(struct socket * sock, struct msghdr * msg, size_t
len, int flags) {
int i = 0;
const struct iovec * iov;
if (unlikely(current_state == WAIT_FOR_RECV) && ktime_to_ns(recv_time)
== 0 && current->pid == vnf_pid) {
recv_time = ktime_get();
if (unlikely(debug>=2)) printk(KERN_INFO "[Packet received]
(%u)%pI4;%u;%pI4;%d;%d;%lld\n",
current->pid,
&sock->sk->sk_rcv_saddr,
sock->sk->sk_num,
&sock->sk->sk_daddr,
sock->sk->sk_dport,
sock->sk->sk_protocol,
ktime_to_ns(recv_time));
iov = msg->msg_iter.iov;
recv_data = (char *)kmalloc(iov->iov_len, GFP_KERNEL);
copy_from_user(recv_data, iov->iov_base, iov->iov_len);
printk(KERN_INFO "[Received data] %s\n", *recv_data);
current_state = WAIT_FOR_SEND;
}
}
void __i3_send_monitor(struct socket * sock, struct msghdr * msg) {
int i = 0;
const struct iovec * iov;
// I don't like this approach at all... think about something
different!!
if (unlikely(current_state == WAIT_FOR_SEND) && current->pid == vnf_pid) {
send_time = ktime_get();
if (unlikely(debug>=2)) printk(KERN_INFO "[Packet send]
(%u)%pI4;%u;%pI4;%d;%d;%lld\n",
current->pid,
&sock->sk->sk_rcv_saddr,
sock->sk->sk_num,
&sock->sk->sk_daddr,
sock->sk->sk_dport,
sock->sk->sk_protocol,
ktime_to_ns(send_time));
if (ktime_to_ns(recv_time) != 0) {
iov = msg->msg_iter.iov;
send_data = (char *)kmalloc(iov->iov_len, GFP_KERNEL);
copy_from_user(send_data, iov->iov_base, iov->iov_len);
printk(KERN_INFO "[Send data] %s\n", *send_data);
if (unlikely(*recv_data == *send_data)) {
proc_time = ktime_sub(send_time, recv_time);
if (unlikely(debug>=2)) printk(KERN_INFO "[Processing time] %lld\n",
ktime_to_ns(proc_time));
recv_time = ktime_set(0, 0);
current_state = SLEEP;
kfree(recv_data);
}
kfree(send_data);
}
}
}
--------------------------------------------------------
>From 7ef3d1efe53fbfb937e0c1e5200e1a8e40e220e9 Mon Sep 17 00:00:00 2001
From: Stefan Geissler <stefan.geissler@...ormatik.uni-wuerzburg.de>
Date: Tue, 14 Nov 2017 12:05:39 +0100
Subject: [PATCH 1/2] Added pointers to hook into socket calls for monitoring
reasons
---
net/socket.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/net/socket.c b/net/socket.c
index d730ef9..57ee946 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -113,6 +113,13 @@ unsigned int sysctl_net_busy_read __read_mostly;
unsigned int sysctl_net_busy_poll __read_mostly;
#endif
+// Setup pointer to fill with external wrapper functions to monitor sockets
+void (*__i3_send_monitor_ptr)(struct sock *, struct msghdr *);
+void (*__i3_recv_monitor_ptr)(struct sock *, struct msghdr *, size_t ,
int);
+EXPORT_SYMBOL(__i3_send_monitor_ptr);
+EXPORT_SYMBOL(__i3_recv_monitor_ptr);
+
+
static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
static int sock_mmap(struct file *file, struct vm_area_struct *vma);
@@ -615,6 +622,8 @@ static inline int sock_sendmsg_nosec(struct socket
*sock, struct msghdr *msg)
int sock_sendmsg(struct socket *sock, struct msghdr *msg)
{
+ if ((unlikely(__i3_send_monitor_ptr))
+ (*__i3_send_monitor_ptr)(sock, msg);
int err = security_socket_sendmsg(sock, msg,
msg_data_left(msg));
@@ -716,6 +725,8 @@ static inline int sock_recvmsg_nosec(struct socket
*sock, struct msghdr *msg,
int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int flags)
{
+ if (unlikely(__i3_recv_monitor_ptr))
+ (*__i3_recv_monitor_ptr)(sock, msg, size, flags);
int err = security_socket_recvmsg(sock, msg, size, flags);
return err ?: sock_recvmsg_nosec(sock, msg, size, flags);
@@ -2479,6 +2490,11 @@ EXPORT_SYMBOL(sock_unregister);
static int __init sock_init(void)
{
+ // Ensure pointers are set to NULL as long as no module is loaded.
+ // Unsetting the pointers has to be handled by the module upon exit.
+ __i3_recv_monitor_ptr = NULL;
+ __i3_send_monitor_ptr = NULL;
+
int err;
/*
* Initialize the network sysctl infrastructure.
--
2.7.4
>From 262cf38d4c576f6399851e6f5ecbd3a73a62d416 Mon Sep 17 00:00:00 2001
From: Stefan Geissler <stefan.geissler@...ormatik.uni-wuerzburg.de>
Date: Tue, 14 Nov 2017 14:04:56 +0100
Subject: [PATCH 2/2] Fixed ISO C90 Warnings
---
net/socket.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/net/socket.c b/net/socket.c
index 57ee946..2e840a8 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -114,8 +114,8 @@ unsigned int sysctl_net_busy_poll __read_mostly;
#endif
// Setup pointer to fill with external wrapper functions to monitor sockets
-void (*__i3_send_monitor_ptr)(struct sock *, struct msghdr *);
-void (*__i3_recv_monitor_ptr)(struct sock *, struct msghdr *, size_t ,
int);
+void (*__i3_send_monitor_ptr)(struct socket *, struct msghdr *);
+void (*__i3_recv_monitor_ptr)(struct socket *, struct msghdr *, size_t
, int);
EXPORT_SYMBOL(__i3_send_monitor_ptr);
EXPORT_SYMBOL(__i3_recv_monitor_ptr);
@@ -622,9 +622,10 @@ static inline int sock_sendmsg_nosec(struct socket
*sock, struct msghdr *msg)
int sock_sendmsg(struct socket *sock, struct msghdr *msg)
{
- if ((unlikely(__i3_send_monitor_ptr))
+ int err;
+ if (unlikely(__i3_send_monitor_ptr))
(*__i3_send_monitor_ptr)(sock, msg);
- int err = security_socket_sendmsg(sock, msg,
+ err = security_socket_sendmsg(sock, msg,
msg_data_left(msg));
return err ?: sock_sendmsg_nosec(sock, msg);
@@ -725,9 +726,10 @@ static inline int sock_recvmsg_nosec(struct socket
*sock, struct msghdr *msg,
int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int flags)
{
+ int err;
if (unlikely(__i3_recv_monitor_ptr))
(*__i3_recv_monitor_ptr)(sock, msg, size, flags);
- int err = security_socket_recvmsg(sock, msg, size, flags);
+ err = security_socket_recvmsg(sock, msg, size, flags);
return err ?: sock_recvmsg_nosec(sock, msg, size, flags);
}
@@ -2489,13 +2491,14 @@ void sock_unregister(int family)
EXPORT_SYMBOL(sock_unregister);
static int __init sock_init(void)
-{
+{
+ int err;
+
// Ensure pointers are set to NULL as long as no module is loaded.
// Unsetting the pointers has to be handled by the module upon exit.
__i3_recv_monitor_ptr = NULL;
__i3_send_monitor_ptr = NULL;
-
- int err;
+
/*
* Initialize the network sysctl infrastructure.
*/
--
2.7.4
Powered by blists - more mailing lists