使用system()加载模块
您正试图在您的应用程序中成为 root(通过执行 setuid(0)),但您没有这样做的权限(如果您以普通用户身份运行您的程序)。相反,您应该检查您的程序是否从根目录运行(使用getuid())。此外,最好测试您的模块文件是否存在。这是此类代码的示例(经过测试并进行了所有需要的检查):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#define ROOT_UID 0
#define INSMOD_PATH "/sbin/insmod"
#define MOD_PATH "/.../mymodule.ko"
int main(void)
{
uid_t uid;
int res;
/* Check if program being run by root */
uid = getuid();
if (uid != ROOT_UID) {
fprintf(stderr, "Error: Please run this program as root\n");
return EXIT_FAILURE;
}
/* Check if module file exists */
if (access(MOD_PATH, F_OK) == -1) {
fprintf(stderr, "Error: File \"%s\" doesn't exist\n", MOD_PATH);
return EXIT_FAILURE;
}
/* Load module */
res = system(INSMOD_PATH " " MOD_PATH);
if (res != 0) {
fprintf(stderr, "Error loading module: %d\n", res);
return EXIT_FAILURE;
}
printf("Module \"%s\" was successfully loaded\n", MOD_PATH);
return EXIT_SUCCESS;
}
将此代码另存为main.c 文件。请务必将 MOD_PATH 定义替换为模块文件的实际路径。
使用下一条命令编译它:
$ gcc -Wall -O2 main.c -o load_module
现在做下一步:
$ su
# ./load_module
- 第一个命令将您的用户切换到 root(您将被要求输入 root 密码)。如果您不知道 root 密码,请尝试使用
sudo -s 命令而不是 su。
- 第二个命令运行您的程序。
注意命令提示符的最后一个字符:
-
# 表示您此时拥有 root 权限
-
$ 表示您只有普通用户权限。
使用finit_module()加载模块
在 C 中使用 system() 函数通常被认为是一种不好的做法(因为它需要很长时间才能执行,而且基本上只是试图替换一个更简单的 Bash 脚本)。
如果你想在 C 中加载内核模块而不使用 system(),你可以查看 insmod 工具的源代码。请参阅libkmod/libkmod-module.c 文件、kmod_module_insert_module() 函数。你可以看到这些来源here。
注意finit_module()函数调用。关于这个system call 的一个很好的解释可以在手册页中找到:
$ man finit_module
这是一个如何使用finit_module()系统调用的示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/stat.h>
#include <fcntl.h>
#define ROOT_UID 0
#define MOD_PATH "/.../mymodule.ko"
static inline int finit_module(int fd, const char *uargs, int flags)
{
return syscall(__NR_finit_module, fd, uargs, flags);
}
int main(void)
{
uid_t uid;
long res;
int fd;
/* Check if program being run by root */
uid = getuid();
if (uid != ROOT_UID) {
fprintf(stderr, "Error: Please run this program as root\n");
return EXIT_FAILURE;
}
/* Check if module file exists */
if (access(MOD_PATH, F_OK) == -1) {
fprintf(stderr, "Error: File \"%s\" doesn't exist\n", MOD_PATH);
return EXIT_FAILURE;
}
/* Load module */
fd = open(MOD_PATH, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
perror("Unable to open module file");
return EXIT_FAILURE;
}
res = finit_module(fd, "", 0);
if (res != 0) {
perror("Error when loading module");
close(fd);
return EXIT_FAILURE;
}
close(fd);
printf("Module \"%s\" was successfully loaded\n", MOD_PATH);
return EXIT_SUCCESS;
}