简体   繁体   中英

How does the Linux kernel know how many bytes it should read from system call path arguments?

I searched in google I found that Linux kernel uses a struct for variables.

#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;

for example for execve systeml call (found here https://elixir.bootlin.com/linux/latest/source/fs/exec.c )
this function will pass the filename pointer to another function as a pathName and set the nameidata struct name to this 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)

my question here is how is it calculating the length of the parameter passed to this function from stack (for example "/bin/sh" )?

(Editor's note: the const char *pathname arg to execve(2) doesn't have to point to stack memory. I think this question is assuming the shellcode use-case where you do construct a path on the user-space stack and pass a pointer to that.)

(I am learning assembly and I'm stuck in parameter passing section to system calls)

Linux uses zero terminated strings, which are the standard string format for C. The end of the string is marked by a zero byte, any bytes beyond the first zero byte in the string are not part of the string. Notably that this means that filenames cannot have a zero byte in them. (For the same reason most shellcode can't have a zero byte, as they're meant to exploit some sort of string buffer overflow.)

In practice the kernel often doesn't need to know the length of a filename, and uses functions like strcmp which compare strings byte by byte, stopping either at the first byte that compares different or at the first zero byte encountered. If necessary however the length of a string can be computed with a function like strlen .

Finally i found my answer
here is the source code that i found

#include <stdio.h>

char hello[] = "HelloA\0AAABB";

int main( void )
{
   __asm__
   (
    "mov $hello , %eax;"
    "push %eax;"
    "call myprint;"
   );
}

void myprint(char input[])
{
    printf("%s" , input);
}

I found that '\\0' is the string terminator.so the above code will just output the "HelloA".The rest of it will be ignored.

Another interesting thing that i found is that when you create an array of char in C. the compiler will add a byte at the end of it for the null terminator.

So if we create something like this

char hello[] = "Hello"

It actually compile it like this :

char hello[] = "Hello\0"

and the size of your hello will be 6 instead of 5.

Finally in assembly programming we have to consider the null terminator for parameters passing in system calls. as long as the linux kernel has been written in C programming language we have to accept the rules of C programming language.


Here is the Gdb result of char hello[]

0x8049597 <hello>:      0x48    0x65    0x6c    0x6c    0x6f    0x41    0x00    0x41
0x804959f <hello+8>:    0x41    0x41    0x42    0x42    0x00    0x77    0x6f    0x72

The 0x8049597 is the start address of our string ("HelloA\\0AAABB").
we put the \\0 after A character. the character 'A' is equals to 0x41 hex number in Ascii table. and the \\0 is 0x00.
That's why the printf function will just show 6 first characters of our string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM