-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
new(bpf, modern-bpf): Add socketcall
support
#810
Comments
Here are my thoughts on Add
Direct syscall BPF programs: +static __always_inline unsigned long extract__net_argument(struct pt_regs *regs, int idx)
+{
+ int syscall_id = syscalls_dispatcher__get_syscall_id(regs);
+
+ if (syscall_id == __NR_socketcall) {
+ unsigned long *args = unstash_sc_args();
+ if (!args || idx > 5)
+ return 0;
+ return args[idx];
+ }
+
+ return extract__syscall_argument(regs, idx);
+}
+
SEC("tp_btf/sys_enter")
int BPF_PROG(socket_e,
struct pt_regs *regs,
@@ -26,23 +49,25 @@ int BPF_PROG(socket_e,
/* Parameter 1: domain (type: PT_ENUMFLAGS32) */
/* why to send 32 bits if we need only 8 bits? */
- u8 domain = (u8)extract__syscall_argument(regs, 0);
+ u8 domain = (u8)extract__net_argument(regs, 0);
ringbuf__store_u32(&ringbuf, (u32)socket_family_to_scap(domain)); Test programs would need to follow a similar approach to wrap the arguments into an array. libpman: @Andreagit97 @FedeDP Wdyt? |
Ei @hbrueckner thank you for all these Infos, let me think a little bit about it. I will come back soon with some ideas :) |
Hi @Andreagit97
not to bias you in any direction... here is my current draft outlining above ideas |
I thought a little bit about it, I will propose something similar to your solution but slightly different, I need only some time to put together some code :/ I will come back here ASAP :) |
HI @Andreagit97
Thanks a lot ;-) I am already curious. One thought that came up was to lazy extract the arguments (w/o pushing them into a map). No time to try it out... so the wrapper could extract (==copy) from the socket call args list using the specific argument index. However, need to try and get some feedback from the BPF verifier ;-) |
This is what I was thinking about https://github.com/Andreagit97/libs/tree/support_socketcall. It is just some scratch code to let you understand what I have in mind (I hope 🤣). Maybe we can't do that at all but right now I don't see any blocker in doing something like this. Unfortunately, right now I have really little time to experiment with it but maybe we can collect some early feedback :) P.S it doesn't compile I miss some things like the |
Hi @Andreagit97 , many thanks for that fast update! ❤️
I understand you way of thinking. I also had a similar approach of providing enter/exit maps in
No problem... I am also still in "catch-up" phase and will experiment the next days.
No problem... fully sufficient to understand they idea (and not getting distracted by ifdefs 🤣 ) |
Yeah, the noisiest part of this approach is that every network syscall filler should have a little block at the beginning with the syscall args management like this: #ifdef CAPTURE_SOCKETCALL
if(id == __NR_socketcall)
{
unsigned long args_pointer = extract__syscall_argument(regs, 0);
bpf_probe_read_user(&args, 3*sizeof(unsigned long), (void*)args_pointer);
}
else
{
#endif
args[0] = extract__syscall_argument(regs, 0);
args[1] = extract__syscall_argument(regs, 1);
args[2] = extract__syscall_argument(regs, 2);
#ifdef CAPTURE_SOCKETCALL
}
#endif If we are able to do something generic for all syscalls even better, but let's say I would give priority to performance and code clarity, at the end every syscall is different from another so it could be acceptable to have a dedicated way to handle its arguments, so don't worry too much about that, BTW if we can find better argument management I'm onboard :)
Thank you 🙏 |
Hi @Andreagit97 , I have some updates here. Below is a summary for the helper function based on your initial commit which is pretty nice! Let me know what you think. Further, I spot some changes to your initial commit which I would like to merge in a co-authored commit (by me) with a change in the commit message. Let me know if you are fine with that. Summary on the helper and an example how it looks like for Regarding
[...]
Let me know if you like the /**
* @brief Extract one ore more arguments related to a network / socket system call.
*
* This function takes into consideration whether the network system call has been
* called directly (e.g. accept4) or through the socketcall system call multiplexer.
* For the socketcall multiplexer, arguments are extracted from the second argument
* of the socketcall system call. See socketcall(2) for more information.
*
* @param argv Pointer to store up to @num arguments of size `unsigned long`
* @param num Number of arguments to extract
* @param regs Pointer to the struct pt_regs to access arguments and system call ID
*/
static __always_inline void extract__network_args(void *argv, int num, struct pt_regs *regs)
{
#ifdef CAPTURE_SOCKETCALL
int id = syscalls_dispatcher__get_syscall_id(regs);
if(id == __NR_socketcall)
{
unsigned long args_pointer = extract__syscall_argument(regs, 1);
bpf_probe_read_user(argv, num * sizeof(unsigned long), (void*)args_pointer);
return;
}
#endif
for (int i = 0; i < num; i++)
{
unsigned long *dst = (unsigned long *)argv;
dst[i] = extract__syscall_argument(regs, i);
}
} The helper needs to extract the system call id, as it is not provided as parameter for the In practice, the change, for example, for --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/bind.bpf.c
+++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/bind.bpf.c
@@ -25,8 +25,12 @@ int BPF_PROG(bind_e,
/*=============================== COLLECT PARAMETERS ===========================*/
+ /* Collect parameters at the beginning to easily manage socketcalls */
+ unsigned long args[1];
+ extract__network_args(args, 1, regs);
+
/* Parameter 1: fd (type: PT_FD) */
- s32 fd = (s32)extract__syscall_argument(regs, 0);
+ s32 fd = (s32)args[0];
ringbuf__store_s64(&ringbuf, (s64)fd);
/*=============================== COLLECT PARAMETERS ===========================*/
@@ -54,13 +58,16 @@ int BPF_PROG(bind_x,
auxmap__preload_event_header(auxmap, PPME_SOCKET_BIND_X);
/*=============================== COLLECT PARAMETERS ===========================*/
+ /* Collect parameters at the beginning to easily manage socketcalls */
+ unsigned long args[3];
+ extract__network_args(args, 3, regs);
/* Parameter 1: res (type: PT_ERRNO) */
auxmap__store_s64_param(auxmap, ret);
/* Parameter 2: addr (type: PT_SOCKADDR) */
- unsigned long sockaddr_ptr = extract__syscall_argument(regs, 1);
- u16 addrlen = (u16)extract__syscall_argument(regs, 2);
+ unsigned long sockaddr_ptr = args[1];
+ u16 addrlen = (u16)args[2];
auxmap__store_sockaddr_param(auxmap, sockaddr_ptr, addrlen);
/*=============================== COLLECT PARAMETERS ===========================*/ Also I think about adding, e.g, With some additional fixup and conditionals, I got it working with a small
|
@hbrueckner sorry for the late response :/ I love this solution it seems really smart!
Sure! Feel free to use it :) Completely on board with this solution! Thank you for that! |
Hi @Andreagit97,
No problem... I also have some stuff on table right now ... so will catch up soon with that and also the BPF rebase as the last driver test case PR has been merged!
Thanks a lot! ❤️
My thought was indeed to define the exact number of of the respective socket system calls. If there are quite less being used, it could be a case by case decision (with comment). Finally, I think I have the right direction now to proceed with updating the other socket calls. Thanks a lot for your feedback! |
I think this can be closed, right? @hbrueckner :) |
yes, merged w/ PR #811 |
Motivation
On the
s390x
architecture, network calls are routed through thesocketcall
syscall which in-kernel multiplexes to the different network syscalls, e.g.,socket
,connect
,sendmsg
, ...Direct network syscall support has been added to
s390
backend with Linux kernel v4.3. However,glibc
sticks with kernel headers v3.2 for non-x86 architectures. You can read more details here: https://sourceware.org/pipermail/libc-alpha/2022-September/142108.html (thanks to @stliibm to kick off this discussion).With that in mind, here is brief summary:
glibc
: usessocketcall
as mentioned abovemusl
: uses direct syscalls and falls back tosocketcall
(details here)golang
: usessocketcall
Feature
The
kmod
driver has alreadysocketcall
support. This feature is to add respectivesocketcall
handling to thebpf
andmodern-bpf
drivers.Alternatives
None -- see summary above.
Additional context
None.
The text was updated successfully, but these errors were encountered: