In kernel, there exists a lot of 'fmod_ret' functions, such as
'update_socket_protocol'. But it cannot be attached in BCC-python
directly, so this patch provides an interface for Python to use
'fmod_ret' attaching method.
Signed-off-by: Gang Yan <yangang@kylinos.cn>
---
src/python/bcc/__init__.py | 43 ++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/src/python/bcc/__init__.py b/src/python/bcc/__init__.py
index 8bc85516..96de3d40 100644
--- a/src/python/bcc/__init__.py
+++ b/src/python/bcc/__init__.py
@@ -461,6 +461,7 @@ class BPF(object):
self.raw_tracepoint_fds = {}
self.kfunc_entry_fds = {}
self.kfunc_exit_fds = {}
+ self.fmod_ret_fds = {}
self.lsm_fds = {}
self.perf_buffers = {}
self.open_perf_events = {}
@@ -1157,6 +1158,21 @@ class BPF(object):
return True
return False
+ @staticmethod
+ def support_fmod_ret():
+ if not BPF.support_kfunc():
+ return False
+
+ kernel_version = platform.release()
+ major, minor, _ = kernel_version.split(".")
+
+ if int(major) > 5:
+ return True
+ elif int(major) ==5 and int(minor) >= 6:
+ return True
+ else:
+ return False
+
def detach_kfunc(self, fn_name=b""):
fn_name = _assert_is_bytes(fn_name)
fn_name = BPF.add_prefix(b"kfunc__", fn_name)
@@ -1166,6 +1182,15 @@ class BPF(object):
os.close(self.kfunc_entry_fds[fn_name])
del self.kfunc_entry_fds[fn_name]
+ def detach_fmod_ret(self, fn_name=b""):
+ fn_name = _assert_is_bytes(fn_name)
+ fn_name = BPF.add_prefix(b"kmod_ret__", fn_name)
+
+ if fn_name not in self.fmod_ret_fds:
+ raise Exception("Fmod_ret func %s is not attached" % fn_name)
+ os.close(self.fmod_ret_fds[fn_name])
+ del self.fmod_ret_fds[fn_name]
+
def detach_kretfunc(self, fn_name=b""):
fn_name = _assert_is_bytes(fn_name)
fn_name = BPF.add_prefix(b"kretfunc__", fn_name)
@@ -1189,6 +1214,22 @@ class BPF(object):
self.kfunc_entry_fds[fn_name] = fd
return self
+ def attach_fmod_ret(self, fn_name=b""):
+ fn_name = _assert_is_bytes(fn_name)
+ fn_name = BPF.add_prefix(b"kmod_ret__", fn_name)
+
+ if fn_name in self.fmod_ret_fds:
+ raise Exception("Fmod_ret func %s has been attached" % fn_name)
+
+ fn = self.load_func(fn_name, BPF.TRACING)
+ fd = lib.bpf_attach_kfunc(fn.fd)
+
+ if fd < 0:
+ raise Exception("Failed to attach BPF to fmod_ret kernel func")
+ self.fmod_ret_fds[fn_name] = fd
+
+ return self
+
def attach_kretfunc(self, fn_name=b""):
fn_name = _assert_is_bytes(fn_name)
fn_name = BPF.add_prefix(b"kretfunc__", fn_name)
@@ -1824,6 +1865,8 @@ class BPF(object):
self.detach_kretfunc(k)
for k, v in list(self.lsm_fds.items()):
self.detach_lsm(k)
+ for k, v in list(self.fmod_ret_fds.items()):
+ self.detach_fmod_ret(k)
# Clean up opened perf ring buffer and perf events
table_keys = list(self.tables.keys())
--
2.25.1
Hi Gang,
On 07/04/2025 04:37, Gang Yan wrote:
> In kernel, there exists a lot of 'fmod_ret' functions, such as
> 'update_socket_protocol'. But it cannot be attached in BCC-python
> directly, so this patch provides an interface for Python to use
> 'fmod_ret' attaching method.
>
> Signed-off-by: Gang Yan <yangang@kylinos.cn>
> ---
> src/python/bcc/__init__.py | 43 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 43 insertions(+)
>
> diff --git a/src/python/bcc/__init__.py b/src/python/bcc/__init__.py
> index 8bc85516..96de3d40 100644
> --- a/src/python/bcc/__init__.py
> +++ b/src/python/bcc/__init__.py
> @@ -461,6 +461,7 @@ class BPF(object):
> self.raw_tracepoint_fds = {}
> self.kfunc_entry_fds = {}
> self.kfunc_exit_fds = {}
> + self.fmod_ret_fds = {}
> self.lsm_fds = {}
> self.perf_buffers = {}
> self.open_perf_events = {}
> @@ -1157,6 +1158,21 @@ class BPF(object):
> return True
> return False
>
> + @staticmethod
> + def support_fmod_ret():
> + if not BPF.support_kfunc():
> + return False
> +
> + kernel_version = platform.release()
> + major, minor, _ = kernel_version.split(".")
> +
> + if int(major) > 5:
> + return True
> + elif int(major) ==5 and int(minor) >= 6:
Was it not introduced in v5.7 instead of v5.6?
return int(major) > 5 or (int(major) == 5 and int(minor) >= 7)
https://lore.kernel.org/20200304191853.1529-1-kpsingh@chromium.org
But also, it feels wrong to look at the kernel version, in case of
backports, etc. Can you not look at something else? e.g. kallsyms?
Cheers,
Matt
--
Sponsored by the NGI0 Core fund.
On Mon, Apr 07, 2025 at 11:07:41AM +0200, Matthieu Baerts wrote:
Hi Matt,
> Hi Gang,
>
> On 07/04/2025 04:37, Gang Yan wrote:
> > In kernel, there exists a lot of 'fmod_ret' functions, such as
> > 'update_socket_protocol'. But it cannot be attached in BCC-python
> > directly, so this patch provides an interface for Python to use
> > 'fmod_ret' attaching method.
> >
> > Signed-off-by: Gang Yan <yangang@kylinos.cn>
> > ---
> > src/python/bcc/__init__.py | 43 ++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 43 insertions(+)
> >
> > diff --git a/src/python/bcc/__init__.py b/src/python/bcc/__init__.py
> > index 8bc85516..96de3d40 100644
> > --- a/src/python/bcc/__init__.py
> > +++ b/src/python/bcc/__init__.py
> > @@ -461,6 +461,7 @@ class BPF(object):
> > self.raw_tracepoint_fds = {}
> > self.kfunc_entry_fds = {}
> > self.kfunc_exit_fds = {}
> > + self.fmod_ret_fds = {}
> > self.lsm_fds = {}
> > self.perf_buffers = {}
> > self.open_perf_events = {}
> > @@ -1157,6 +1158,21 @@ class BPF(object):
> > return True
> > return False
> >
> > + @staticmethod
> > + def support_fmod_ret():
> > + if not BPF.support_kfunc():
> > + return False
> > +
> > + kernel_version = platform.release()
> > + major, minor, _ = kernel_version.split(".")
> > +
> > + if int(major) > 5:
> > + return True
> > + elif int(major) ==5 and int(minor) >= 6:
>
> Was it not introduced in v5.7 instead of v5.6?
>
> return int(major) > 5 or (int(major) == 5 and int(minor) >= 7)
>
I think v5.7 is right, the 5.6 is from the bcc repo:
bcc/example/cpp/KModRetExample.cc:
* Kfunc modify_ret support is only available at kernel version 5.6 and later.
Maybe this is also need to be fixed later?
>
> https://lore.kernel.org/20200304191853.1529-1-kpsingh@chromium.org
>
>
> But also, it feels wrong to look at the kernel version, in case of
> backports, etc. Can you not look at something else? e.g. kallsyms?
>
Do you think we can do this after making a PR first?
> Cheers,
> Matt
> --
> Sponsored by the NGI0 Core fund.
>
>
Hi Gang,
On 08/04/2025 03:56, Gang Yan wrote:
> On Mon, Apr 07, 2025 at 11:07:41AM +0200, Matthieu Baerts wrote:
> Hi Matt,
>
>
>> Hi Gang,
>>
>> On 07/04/2025 04:37, Gang Yan wrote:
>>> In kernel, there exists a lot of 'fmod_ret' functions, such as
>>> 'update_socket_protocol'. But it cannot be attached in BCC-python
>>> directly, so this patch provides an interface for Python to use
>>> 'fmod_ret' attaching method.
>>>
>>> Signed-off-by: Gang Yan <yangang@kylinos.cn>
>>> ---
>>> src/python/bcc/__init__.py | 43 ++++++++++++++++++++++++++++++++++++++
>>> 1 file changed, 43 insertions(+)
>>>
>>> diff --git a/src/python/bcc/__init__.py b/src/python/bcc/__init__.py
>>> index 8bc85516..96de3d40 100644
>>> --- a/src/python/bcc/__init__.py
>>> +++ b/src/python/bcc/__init__.py
>>> @@ -461,6 +461,7 @@ class BPF(object):
>>> self.raw_tracepoint_fds = {}
>>> self.kfunc_entry_fds = {}
>>> self.kfunc_exit_fds = {}
>>> + self.fmod_ret_fds = {}
>>> self.lsm_fds = {}
>>> self.perf_buffers = {}
>>> self.open_perf_events = {}
>>> @@ -1157,6 +1158,21 @@ class BPF(object):
>>> return True
>>> return False
>>>
>>> + @staticmethod
>>> + def support_fmod_ret():
>>> + if not BPF.support_kfunc():
(I don't know if this dependence is needed here.)
>>> + return False
>>> +
>>> + kernel_version = platform.release()
>>> + major, minor, _ = kernel_version.split(".")
>>> +
>>> + if int(major) > 5:
>>> + return True
>>> + elif int(major) ==5 and int(minor) >= 6:
>>
>> Was it not introduced in v5.7 instead of v5.6?
>>
>> return int(major) > 5 or (int(major) == 5 and int(minor) >= 7)
>>
> I think v5.7 is right, the 5.6 is from the bcc repo:
>
> bcc/example/cpp/KModRetExample.cc:
> * Kfunc modify_ret support is only available at kernel version 5.6 and later.
>
> Maybe this is also need to be fixed later?
Maybe this bit is supported since v5.6 and fmod_ret from 5.7? I didn't
check.
>> https://lore.kernel.org/20200304191853.1529-1-kpsingh@chromium.org
>>
>>
>> But also, it feels wrong to look at the kernel version, in case of
>> backports, etc. Can you not look at something else? e.g. kallsyms?
>>
>
> Do you think we can do this after making a PR first?
I don't know the BCC project, but I think checking the version will not
be accepted. I think it would be better to do something like that instead:
@staticmethod
def support_fmod_ret():
# It is not clear what can be used to check if 'fmod_ret'
# supported by the kernel. Assuming checking kfunc is enough.
return BPF.support_kfunc():
And add a note about that in the commit message, asking BCC devs for
ideas. You can also say you considered checking the kernel version.
Cheers,
Matt
--
Sponsored by the NGI0 Core fund.
© 2016 - 2025 Red Hat, Inc.