首页 > 解决方案 > Linux 内核如何知道它应该从系统调用路径参数中读取多少字节?

问题描述

我在 google 中搜索发现 Linux 内核使用 struct 作为变量。

#define EMBEDDED_LEVELS 2
struct nameidata {
    struct path path;
    struct qstr last;
    struct path root;
    struct inode    *inode; /* path.dentry.d_inode */
    unsigned int    flags;
    unsigned    seq, m_seq;
    int     last_type;
    unsigned    depth;
    int     total_link_count;
    struct saved {
        struct path link;
        struct delayed_call done;
        const char *name;
        unsigned seq;
    } *stack, internal[EMBEDDED_LEVELS];
    struct filename *name;
    struct nameidata *saved;
    struct inode    *link_inode;
    unsigned    root_seq;
    int     dfd;
} __randomize_layout;

例如对于execvesysteml 调用(在此处找到https://elixir.bootlin.com/linux/latest/source/fs/exec.c
,此函数会将文件名指针作为路径名传递给另一个函数,并将 nameidata结构名称设置为这个路径名

static int __do_execve_file(int fd, struct filename *filename,
                struct user_arg_ptr argv,
                struct user_arg_ptr envp,
                int flags, struct file *file)

我的问题是它如何计算从堆栈传递给这个函数的参数的长度(例如"/bin/sh")?

(编者注:const char *pathnamearg toexecve(2)不必指向堆栈内存。我认为这个问题是假设您在用户空间堆栈上构建路径并传递指向该路径的 shellcode 用例。

(我正在学习汇编,我被困在系统调用的参数传递部分)

标签: assemblylinux-kernelparameter-passingsystem-callsabi

解决方案


Linux 使用以零结尾的字符串,这是 C 的标准字符串格式。字符串的结尾用零字节标记,字符串中第一个零字节之外的任何字节都不是字符串的一部分。值得注意的是,这意味着文件名中不能有零字节。(出于同样的原因,大多数 shellcode 不能有零字节,因为它们旨在利用某种字符串缓冲区溢出。)

实际上,内核通常不需要知道文件名的长度,而是使用类似strcmp逐字节比较字符串的函数,在比较不同的第一个字节或遇到的第一个零字节处停止。但是,如有必要,可以使用类似的函数计算字符串的长度strlen


推荐阅读