Android 10 insmodソース分析


Android 10 insmodソース分析
  • insmod関数
  • sys_finit_module
  • マクロ定義等価
  • 概要_NR_init_moduleとsys_init_module

  • 本明細書のコードはrk 3399-android 10に由来する.
    insmod関数
    ここでのinsmod関数は、ドライバロードwifi_です.load_driverの後に呼び出される関数:wifiについてload_driverのソースコード分析前のブログ:android移植wifi駆動プロセスporting
    ファイルの場所:rk3399-android-10/frameworks/opt/net/wifi/libwifi_hal/wifi_hal_common.cpp
    static int insmod(const char *filename, const char *args) {
         
      int ret;
      int fd;
    
      fd = TEMP_FAILURE_RETRY(open(filename, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
      printf("insmod filename = %s
    "
    ,filename); if (fd < 0) { PLOG(ERROR) << "Failed to open " << filename; return -1; } ret = syscall(__NR_finit_module, fd, args, 0); close(fd); if (ret < 0) { PLOG(ERROR) << "finit_module return: " << ret; } return ret; }

    ここで、彼が呼び出した関数は次のとおりです.
    syscallについて:rk3399-android-10/kernel/arch/arm/kernel/entry-common.S
    .macro  syscall, nr, func
            .ifgt   __sys_nr - 
    r .error "Duplicated/unorded system call entry" .endif .rept
    r - __sys_nr .long sys_ni_syscall .endr .long \func .equ __sys_nr,
    r + 1

    このセクションでは、長い間多くの資料を調べてきましたが、macroマクロ定義と呼び出された関数との具体的なつながりは理解できません.ちゃんと指導して欲しい...
    についてNR_finit_module: rk3399-android-10/kernel/include/uapi/asm-generic/unistd.h
    #define __NR_finit_module 273//     
    __SYSCALL(__NR_finit_module, sys_finit_module)
    

    現在、insmodは上述の定義によって、このコードsyscall(__NR_finit_module, fd, args, 0);を通じて、システム呼び出し番号(割り込み番号)を利用してsys_を呼び出すことができることしか知られていない.finit_module,finit_moduleのシステム呼び出し番号は__です.NR_finit_module.
    sys_finit_moduleの定義:rk3399-android-10/kernel/include/linux/syscalls.h
    asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
    

    注意:asmlinkageは、レジスタではなくスタックからの関数読み出しのパラメータを表します.
    sys_finit_module rk3399-android-10/kernel/kernel/module.cには、次の定義があります.
    SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
    {
         
            struct load_info info = {
          };
            loff_t size;
            void *hdr;
            int err;
    
            err = may_init_module();
            if (err)
                    return err;
    
            pr_debug("finit_module: fd=%d, uargs=%p, flags=%i
    "
    , fd, uargs, flags); if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS |MODULE_INIT_IGNORE_VERMAGIC)) return -EINVAL; err = kernel_read_file_from_fd(fd, &hdr, &size, INT_MAX, READING_MODULE); // rk3399-android-10/kernel/fs/exec.c , , fd if (err) return err; info.hdr = hdr; info.len = size; return load_module(&info, uargs, flags); }

    まず,上記から総合すると,この関数定義式は:SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)であることが分かる.この行の意味はasmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);の行の定義とほぼ同じです.詳細な中間のマクロ定義の変換過程に興味のある可視文章の「マクロ定義の等価」章.
    次に上のsys_を見てみましょうfinit_moduleが呼び出す次のレベルの関数.ファイルの場所:rk3399-android-10/kernel/kernel/module.c
    static int may_init_module(void)
    {
         
            if (!capable(CAP_SYS_MODULE) || modules_disabled)//capable                ,      0
            //CAP_SYS_MODULE               ,   rk3399-android-10/kernel/include/uapi/linux/capability.h
                    return -EPERM;
            return 0;
    }
    //load_module               ,    
    static int load_module(struct load_info *info, const char __user *uargs,
                           int flags)
    {
         
            struct module *mod;
            long err = 0;
            char *after_dashes
    
            err = elf_header_check(info);
           .....
            return do_init_module(mod);
    	   ...
    }  
    

    マクロ定義の等価
    マクロ定義の最終等価についてはsyscalls.hファイル.rk3399-android-10/kernel/include/linux/syscalls.h
    #ifndef SYSCALL_DEFINE0
    #define SYSCALL_DEFINE0(sname)                                  \
            SYSCALL_METADATA(_##sname, 0);                          \
            asmlinkage long sys_##sname(void);                      \
            ALLOW_ERROR_INJECTION(sys_##sname, ERRNO);              \
            asmlinkage long sys_##sname(void)
    #endif /* SYSCALL_DEFINE0 */
    
    #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
    #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
    #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
    #define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
    #define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
    #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
    

    上から分かるようにSYSCALL_DEFINE3 ==》 SYSCALL_DEFINEx(3,_finit_module,VA_ARGS)のうち_VA_ARGS__対応はSYSCALL_DEFINE 3の後のすべてのパラメータセット、すなわちint, fd, const char __user *, uargs, int, flagsまたはrk3399-android-10/kernel/include/linux/syscalls.hで、以下の定義があります.
    #define SYSCALL_DEFINEx(x, sname, ...)                          \
            SYSCALL_METADATA(sname, x, __VA_ARGS__)                 \
            __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
    

    以上より、SYSCALL_を知るDEFINEx ==》 __SYSCALL_DEFINEx(3, _finit_module, VA_ARGS)
    分析を続けたのかrk3399-android-10/kernel/include/linux/syscalls.h
    #ifndef __SYSCALL_DEFINEx
    #define __SYSCALL_DEFINEx(x, name, ...)                                 \
            __diag_push();                                                  \
            __diag_ignore(GCC, 8, "-Wattribute-alias",                      \
                          "Type aliasing is used to sanitize syscall arguments");\
            asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))       \
                    __attribute__((alias(__stringify(__se_sys##name))));    \
            c                        \
            static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
            asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
            asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))  \
            {                                                               \
                    long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\
                    __MAP(x,__SC_TEST,__VA_ARGS__);                         \
                    __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));       \
                    return ret;                                             \
            }                                                               \
            __diag_pop();                                                   \
            static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
    #endif /* __SYSCALL_DEFINEx */
    

    以上より、__SYSCALL_DEFINEx(3, _finit_module, __VA_ARGS__)は、
    asmlinkage long sys_finit_module(__MAP(3,__SC_DECL, __VA_ARGS__))      \
                    __attribute__((alias(__stringify(__se_sys_finit_module)))); \
                    ALLOW_ERROR_INJECTION(sys_finit_module, ERRNO); \
                    static inline long __do_sys_finit_module(__MAP(3,__SC_DECL,__VA_ARGS__));\
                    asmlinkage long __se_sys_finit_module(__MAP(3,__SC_LONG,__VA_ARGS__));\
                    asmlinkage long __se_sys_finit_module(__MAP(3,__SC_LONG,__VA_ARGS__)) \
                    {
         \
                            long ret = __do_sys_finit_module(__MAP(3,__SC_CAST,__VA_ARGS__));\
                             __MAP(3,__SC_TEST,__VA_ARGS__);                         \
                            __PROTECT(3, ret,__MAP(3,__SC_ARGS,__VA_ARGS__));       \
                            return ret;                                             \
                    }\
    static inline long __do_sys_finit_module(__MAP(3,__SC_DECL, __VA_ARGS__))            
    

    上記各種類のマクロ変換:
    asmlinkage long sys_finit_module(int fd, const char __user * uargs, int flags) \
    	__attribute__((alias(__stringify(__se_sys_finit_module)))); \
    	ALLOW_ERROR_INJECTION(sys_finit_module, ERRNO); \
    	static inline long __do_sys_finit_module(int fd, const char __user * uargs, int flags);\
    	asmlinkage long __se_sys_finit_module(long fd, long uargs, long flags);\
    	asmlinkage long __se_sys_finit_module(long fd, long uargs, long flags) \
                    {
         \
                            long ret = __do_sys_finit_module( (int) fd, (const char __user *) uargs, (int) flags);\
                             BUILD_BUG_ON_ZERO(sizeof(int) > sizeof(long)); \
    	         BUILD_BUG_ON_ZERO(sizeof(char*) > sizeof(long)); \
          	         __PROTECT(2, ret, fd, uargs , flags); \
                            return ret;                                             \
                    }\
    static inline long __do_sys_finit_module(int fd, const char __user * uargs, int flags) 
    

    実際にはSYSCALL_DEFINE3(finit_module,int, fd, 。。。)であり、最終的にはasmlinkage long sys_finit_module(int fd, 。。。)に等価である.
    についてNR_init_moduleとsys_init_module
    この部分のコードを学ぶ時、ネット上のいくつかのブログを参考にして、しかしどうしてみんなが書いたinsmod呼び出しの関数がすべて__ですかを知りませんNR_init_module、つまりsys_init_module、バージョンの違いでしょう.
    比較のために、そのコードも貼り付けます.
    場所の定義:rk3399-android-10/kernel/include/linux/syscalls.h
    asmlinkage long sys_init_module(void __user *umod, unsigned long len,
                                    const char __user *uargs);
    

    ファイルの場所:rk3399-android-10/kernel/kernel/module.c
    SYSCALL_DEFINE3(init_module, void __user *, umod,
                    unsigned long, len, const char __user *, uargs)
    {
         
            int err;
            struct load_info info = {
          };
    
            err = may_init_module();
            if (err)
                    return err;
    
            printk("init_module: umod=%p, len=%lu, uargs=%p
    "
    ,umod,len,uargs); pr_debug("init_module: umod=%p, len=%lu, uargs=%p
    "
    , umod, len, uargs); err = copy_module_from_user(umod, len, &info); if (err) return err; return load_module(&info, uargs, 0); }

    比較すると、両者の違いはinit_moduleは従来のcopy_を通じてfrom_userはkoコードをコピーし、finit_moduleは、ファイル記述子fdによってvfsの下位層の読み出し関数を呼び出してkoコードをカーネルに読み出す.
    まとめ:学習の過程で、external/kmod/tools/modprobe.cに位置するinsmod関数があり、ツールmodprobeで使用されるinsmod関数と推定されることが分かった.ここにコードを貼らない.
    modprobeとinsmodの違い:
  • modprobeはload module時の依存関係
  • を解決できる.
  • modprobeデフォルトでは/lib/moduules/現在のkernel/下にmoduleが検索されますが、insmodはそのパラメータの中でmodule
  • のみが検索されます.