Closed ilammy closed 5 years ago
@StephGbzh @Fabiofont could you please try this out? This patch should fix #4.
I confirm it works for me !
Just curious: How did you find the info ?
I cloned the linux repo and used grep mkdir
and grep pt_regs
(well, ripgrep in fact) but there are way too many occurrences. There are around 14000 commits between tags v4.16 and v4.17 ...
Just a quick pointer to where you looked at to find that the signature changed and the struct had a field named "di" ?
Well, it's not very efficient to look through all commits between versions. As you have noticed, there are quite a few of them. In general you'd be better off looking for specific changes via git log v4.16..v4.17 arch/x86
or git log -S pt_regs v4.16..v4.17
.
However, in this particular case I already knew that there is a patch set with pt_regs changes somewhere so it did not take long to discover this one. It changes the ABI of the system call handlers to receive a pointer to struct pt_regs
which contains values of registers on system call entry. Then it just takes some ABI knowledge: the system call arguments are located in %rdi, %rsi, %rdx, %r10, %r8, %r9 (in that order). execve() gets executable file name as the first argument, so we need the %rdi register which correspons to the "di" field of pt_regs,
Thanks !
I got relative path on kernel v5.3.0 when i execute with relative path. How can I get full path? I ran:
~$ Desktop/main
Hello, World!
then dmesg shows as follows:
[15946.274633] ftrace_hook: execve() before: Desktop/main
[15946.274775] ftrace_hook: execve() after: 0
@ningyuv,
I got relative path on kernel v5.3.0 when i execute with relative path. How can I get full path?
You’d need to append the relative path the current working directory of the current process to get an absolute path. The current process can be accessed via current
global variable, it will give you task_struct
, and from there you can get the current working directory. You can take a peek at getcwd(2)
implementation for a hint.
@ilammy
@ningyuv,
I got relative path on kernel v5.3.0 when i execute with relative path. How can I get full path?
You’d need to append the relative path the current working directory of the current process to get an absolute path. The current process can be accessed via
current
global variable, it will give youtask_struct
, and from there you can get the current working directory. You can take a peek atgetcwd(2)
implementation for a hint.
thanks!
Finally, I appended the relative path the current working directory(such as /path/to/pwd/./main or /path/to/pwd/further/../main), it works correctly with filp_open
function!
I took a peek at getcwd(2)
implementation, but it's diffcult for me. I found a blog that solved this problem.
The blog: Module to display the current working directory
The code:
path_get(¤t->fs->pwd);
buf = kmalloc(4096, GFP_KERNEL);
if (!buf)
goto out_no_buf_mem;
pwd_path = d_path(¤t->fs->pwd, buf, 4096);
pr_info("pwd: %s\n", pwd_path);
kfree(buf);
I tried to hook sys_open(), but it didn't work. Here s a piece of code:
.....
static asmlinkage long (real_sys_open)(struct pt_regs regs);
static asmlinkage long fh_sys_open(struct pt_regs regs) { long ret; char kernel_filename;
/* Copy buffer to kernel space from user space */
kernel_filename = duplicate_filename((void*) regs->di);
/* do something */
pr_info("name: %s\n", kernel_filename);
kfree(kernel_filename);
/* Call original function */
ret = real_sys_open(regs);
return ret;
}
static asmlinkage long (real_sys_open)(const char __user filename, int flags, umode_t mode);
static asmlinkage long fh_sys_open(const char __user filename, int flags, umode_t mode) { long ret; char kernel_filename;
/* Copy buffer to kernel space from user space */
kernel_filename = duplicate_filename(filename);
/* do something */
pr_info("name: %s\n", kernel_filename);
kfree(kernel_filename);
/* Call original function */
ret = real_sys_open(filename, flags, mode);
return ret;
}
/*
{ \
.name = SYSCALL_NAME(_name), \
.function = (_function), \
.original = (_original), \
}
static struct ftrace_hook demo_hooks[] = { HOOK("sys_open", fh_sys_open, &real_sys_open) };
....
If you have any clue why my code didn't work, please tell me. Thanks!
Previously mentioned patchset changed not only the naming convention of x86_64 stubs but their ABI as well. Now they receive a pointer to
struct pt_regs
laid out on the stack. We have to pass this pointer as is to the original handler, and if we wish to examine the arguments of a system call then we have to look into appropriate registers ourselves.