How to define a specific socket between User Space and Kernel Space?

I have a library in user space that intercepts socket level calls like socket() , connect() , accept() , etc. I only deal with TCP sockets.

Down in Kernel Space I have a network core module that deals with all TCP connections. I need to determine in the driver which sockets were intercepted by the User Space library.

So far, I have used the priority field from struct sock (Kernel), which can be set using setsockopt() in user space. But this is a pretty dirty hack.

Is there any private struct sock field that I could safely use and set from User Space via setsockopt() ?

Thanks.

+4
source share
2 answers

Actually there is no such parameter of "private field" which can be used exclusively with the help of user space and your kernel code.

Using the SO_PRIORITY parameter seems a little too intrusive, as it can change the way the stack processes packets, and this can lead to difficult to understand results. A safer option would be to change the values ​​of SO_RCVBUF or SO_SNDBUF to a small delta from the normal default value. Linux will double the value passed, but you can look for delta from the default values ​​and know that the presence of delta as a signal, that this is your "intercepted" socket.

+5
source

Getting the original question "I need to determine in the driver which sockets were intercepted by the User Space library." there are actually several functions.

First, you need to know that ALL existing connections are stored in the global hash table - "tcp_hashinfo", and you can find the address in / proc / kallsyms.

The main function is not __inet_lookup_skb (), which is called __inet_lookup (), and is broken into __inet_lookup_established () (looking for any matching connectors that were installed) and __inet_lookup_listener () (I was looking for an open listener, but have not established a connection yet).

The main inputs required for searching are source / destination ports and IP address information if the return pointer found is "struct sock *" on the socket.

IPv6 has the same name and the same logic.

The function (__inet_lookup_skb ()) is declared as a "static string" - it cannot be found from / proc / kallsyms, and none of the drivers see it because it is compiled inline. But there is no problem for this, as it will call two other functions - inet_lookup_listener () and inet_lookup_established (), which are NOT compiled inline. Symbols for it are exported, so you can use it from the kernel module.

It is important that reading this hashinfo table is a critical operation - several processors can read and write at the same time, and that is why locking is performed at the beginning / end of functions while reading, do not allow it to change while reading. Since it is difficult to access these RCU locks, even if they are global in nature, do not re-implement these functions, just reuse them.

+1
source

Source: https://habr.com/ru/post/1502472/


All Articles