我在google中搜索到,我发现Linux内核将结构体用于变量。
#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
系统调用(在https://elixir.bootlin.com/linux/latest/source/fs/exec.c中找到)此函数会将文件名指针作为pathName传递给另一个函数,并将nameidata结构名设置为此pathName
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
的execve(2)
arg并不have)指向堆栈内存。我认为这个问题是假设您在shellcode用例中在用户上构造路径的,空间堆栈,然后将其传递给指针。)
((我正在学习汇编,并且被卡在系统调用的参数传递部分中)
Linux使用零终止的字符串,这是C的标准字符串格式。字符串的结尾由零字节标记,字符串中第一个零字节之后的任何字节都不是字符串的一部分。值得注意的是,这意味着文件名中不能包含零字节。 (出于同样的原因,大多数shellcode不能有零字节,因为它们是为了利用某种字符串缓冲区溢出。)
实际上,内核通常不需要知道文件名的长度,而使用execve(2)
之类的函数逐字节比较字符串,停在比较不同的第一个字节或遇到的第一个零字节处。但是,如有必要,可以使用strcmp
之类的函数来计算字符串的长度。