cstringlinux-kernelfilepathstrstr

Crash by executing strstr() inside kernel module


I am trying to detect opening folder in a specific location (myPath). I am using strstr() but I see that my system is always crashed(picture) after executing this function. If I remove the check (if(ret)), it works as normal Here is my code:

struct task_struct *task_list;
struct fdtable *        fdt = NULL;
unsigned int process_count = 0;
struct path files_path;
char *access_mode;
char *cwd;
int res;
char *myPath = "/home/anh/src/";
char *buf = (char *)kmalloc(GFP_KERNEL,100*sizeof(char));
char * ret;
for_each_process(task_list) {
        fdt = files_fdtable(task_list->files);
        int i=0;
        while(fdt->fd[i] != NULL) { 
            files_path = fdt->fd[i]->f_path;
            cwd = d_path(&files_path,buf,100*sizeof(char));
            if(cwd){//Check if cwd != NULL
                ret = strstr(cwd, myPath);//check seeked file path and myPath
                if(ret) 
                {
                    printk(KERN_INFO "Open file with fd %d  cwd: %s", i,cwd);
                }   
            }    
            i++;
        }
        process_count++;    
    }

Could someone review and support me to solve this problem?, why the strstr() cannot be used in a Linux kernel module or is there other ways to verify that a string is in inside a string?

Best regards, Anh


Solution

  • A plausible explanation is that an error occurs, so cwd is not a valid pointer. strstr is called on this invalid pointer and crashes. Without if(ret), the strstr call is optimized away so there's no crash.

    Functions in the Linux kernel typically return an error code on error. The documentation of d_path specifically states that this is the case.

    Returns a pointer into the buffer or an error code if the path was too long.

    if (cwd) checks that cwd is non-null. If cwd contains an error code, it's non-null. So if (cwd) is not a useful check. The correct error check for functions that return a pointer is IS_ERR().

                cwd = d_path(&files_path,buf,100*sizeof(char));
                if (IS_ERR(cwd)) {
                        printk(KERN_WARN "At i=%d: d_path -> %ld", i, PTR_ERR(cwd));
                } else {
                        ret = strstr(cwd, myPath);