bpfilter umh導致的libc依賴問題

Linux 4.18開始支持bpfilter,用于代替netfilter,其工作原理見下圖:

bpfilter

可以看到bpfilter需要一個UMH(User Module Helper)實現(xiàn)eBPF的規(guī)則轉(zhuǎn)換,這個UMH是需要運行在用戶空間的。在內(nèi)核源碼下的net/bpfilter可以看到以下文件:

.
├── bpfilter_kern.c
├── bpfilter_umh_blob.S
├── Kconfig
├── main.c
├── Makefile
└── msgfmt.h

其中,main.c就是要在用戶空間運行的bpfilter_umh的源代碼,main.c將編譯成net/bpfilter/bpfilter_umh,然后在bpfilter_umh_blob.S里面用incbin將編譯好的bpfilter_umh包進去:

/* net/bpfilter/bpfilter_umh_blob.S */

/* SPDX-License-Identifier: GPL-2.0 */
    .section .init.rodata, "a"
    .global bpfilter_umh_start
bpfilter_umh_start:
    .incbin "net/bpfilter/bpfilter_umh"
    .global bpfilter_umh_end
bpfilter_umh_end:

bpfilter在加載的時候?qū)pfilter_umh fork到用戶空間里運行:

/* net/bpfilter/bpfilter_kern.c */

static int __init load_umh(void)
{
    int err;

    /* fork usermode process */
    err = fork_usermode_blob(&bpfilter_umh_start,
                 &bpfilter_umh_end - &bpfilter_umh_start,
                 &info);
    if (err)
        return err;
    pr_info("Loaded bpfilter_umh pid %d\n", info.pid);

    /* health check that usermode process started correctly */
    if (__bpfilter_process_sockopt(NULL, 0, 0, 0, 0) != 0) {
        stop_umh();
        return -EFAULT;
    }
    if (IS_ENABLED(CONFIG_INET))
        bpfilter_process_sockopt = &__bpfilter_process_sockopt;

    return 0;
}
# net/bpfilter/Kconfig

menuconfig BPFILTER
    bool "BPF based packet filtering framework (BPFILTER)"
    depends on NET && BPF && INET
    help
      This builds experimental bpfilter framework that is aiming to
      provide netfilter compatible functionality via BPF

if BPFILTER
config BPFILTER_UMH
    tristate "bpfilter kernel module with user mode helper"
    depends on $(success,$(srctree)/scripts/cc-can-link.sh $(CC))
    default m
    help
      This builds bpfilter kernel module with embedded user mode helper
endif

要特別注意的是,在Kconfig中,如果CONFIG_BPFILTER_UMHm,那么bpfilter_umh將不會使用靜態(tài)鏈接的方式編譯,這樣一來,如果目標系統(tǒng)使用的libc與編譯內(nèi)核的工具鏈使用的libc差距過大的話,會導致bpfilter_umh無法工作,也就意味著bpfilter模塊無法裝載。

例如,使用glibc的工具鏈編譯的啟用bpfilter支持的內(nèi)核,放在musl環(huán)境的OpenWrt中,由于C庫不同致使bpfilter_umh無法運行,bpfilter模塊也就不能加載,最終導致iptables報錯:

root@OpenWrt:~# iptables -L
iptables v1.6.2: can't initialize iptables table `filter': No child process

為了解決這個問題,需要將CONFIG_BPFILTER_UMH設定為y,這樣會給bpfilter_umh添加-static的鏈接參數(shù)(靜態(tài)鏈接),就不會產(chǎn)生libc的依賴問題了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容