assembly - 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;
例如对于execve
systeml 调用(在此处找到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 *pathname
arg toexecve(2)
不必指向堆栈内存。我认为这个问题是假设您在用户空间堆栈上构建路径并传递指向该路径的 shellcode 用例。)
(我正在学习汇编,我被困在系统调用的参数传递部分)
解决方案
Linux 使用以零结尾的字符串,这是 C 的标准字符串格式。字符串的结尾用零字节标记,字符串中第一个零字节之外的任何字节都不是字符串的一部分。值得注意的是,这意味着文件名中不能有零字节。(出于同样的原因,大多数 shellcode 不能有零字节,因为它们旨在利用某种字符串缓冲区溢出。)
实际上,内核通常不需要知道文件名的长度,而是使用类似strcmp
逐字节比较字符串的函数,在比较不同的第一个字节或遇到的第一个零字节处停止。但是,如有必要,可以使用类似的函数计算字符串的长度strlen
。
推荐阅读
- django - 0001_initial 迁移不会创建
- c - 插入双向链表时的 C 内存泄漏
- javascript - 在 console.log 中调试截获的请求(开玩笑的木偶)
- java - 如何构造一个类,其变量对于大多数对象具有几乎相同的值
- ruby-on-rails - 简单的 Rails Minitest 案例爆炸
- python - 如何恢复 BERT/XLNet 嵌入?
- xamarin - 如何通过在 Xamarin Forms 中选择另一个下拉列表来动态更改下拉列表值
- vue.js - 如何使用 Vue.Js 上传仅图像文件?
- javascript - 如何在不使用全局变量的情况下从回调中获取数据?
- python - python中的舍入浮点数(处理5s)