首页 > 代码库 > Linux Kernel中获取当前目录方法(undone)

Linux Kernel中获取当前目录方法(undone)

目录

0. 引言1. 基于进程内存镜像信息struct mm_struct获取struct path调用d_path()获取当前进程的"绝对路径"2. 基于文件描述符(fd)、task_struct调用d_path()获取当前进程的"当前目录"3. 基于dentry、vfsmount调用d_path()获取当前进程的"当前目录"4. 基于get_fs_pwd获取当前目录

 

0. 引言

本文涉及的是ring0下的获取当前进程工作目录的方法,LKM位于linux的内核内存区域,任何进程都可以通过LKM的导出函数指定当前LKM的代码,所以,我们需要在LKM中获取当前调用进程的当前工作目录

 

1. 基于进程内存镜像信息struct mm_struct获取struct path调用d_path()获取当前进程的"绝对路径"

d_path是内核提供的根据dentry和vfsmount获取绝对路径函数

此函数有2个版本,以内核版本2.6.25为分界1. extern char *d_path(const struct path *, char *, int); 2. extern char * d_path(struct dentry *, struct vfsmount *, char *, int);

get_absolute_path.c

#include <linux/module.h>#include <linux/fcntl.h>//for O_RDONLY#include <linux/fs.h>//for filp_open#include <linux/uaccess.h>//for get_fs#include <linux/limits.h>//for PATH_MAX #include <linux/sched.h> #include <linux/mm.h>char* get_absolute_path(struct task_struct * task){    char * ret_ptr = NULL;    char * tpath   = NULL ;    struct vm_area_struct * vma = NULL;    struct path base_path;    tpath = (char*)kmalloc(512, 0);    if(NULL == tpath || NULL == task)    {        return NULL;    }    memset(tpath,\0,512);    task_lock(task);    /*     获取当前进程的内存空间信息(通过内存空间)    */    if(task->mm && task->mm->mmap)    {        vma = task->mm->mmap;    }    else    {        task_unlock(task);        kfree(tpath);        return NULL;    }    /*    取得path(a struct含dentry和vfsmount)    */    while(vma)    {        if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)        {                base_path = vma->vm_file->f_path;            break;        }        vma = vma->vm_next;    }    task_unlock(task);    /*     * 调用 d_path, 得到绝对路径     */    ret_ptr = d_path(&base_path, tpath, 512);    return ret_ptr;} int init_module(void){  struct task_struct * task = current;  char *path = get_absolute_path(task);  printk("FULLPATH: %s\n", path);  return 0;}void cleanup_module(void){}MODULE_LICENSE("GPL");

Makefile

## Variables needed to build the kernel module#name      = get_absolute_pathobj-m += $(name).oall: build.PHONY: build install cleanbuild:    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules CONFIG_DEBUG_SECTION_MISMATCH=yinstall: build    -mkdir -p /lib/modules/`uname -r`/kernel/arch/x86/kernel/    cp $(name).ko /lib/modules/`uname -r`/kernel/arch/x86/kernel/    depmod /lib/modules/`uname -r`/kernel/arch/x86/kernel/$(name).koclean:    [ -d /lib/modules/$(shell uname -r)/build ] &&     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Relevant Link:

http://blog.csdn.net/cenziboy/article/details/8761621

 

2. 基于文件描述符(fd)、task_struct调用d_path()获取当前进程的"当前目录"

/*根据task_struct、fd(文件描述符)获取当前工作路径*/int get_path(struct task_struct *mytask, int fd) {    struct file *myfile = NULL;     struct files_struct *files = NULL;     char path[100] = {\0};     char *ppath = path;        files = mytask->files;     if (!files)     {        printk("files is null..\n");         return -1;    }     myfile = files->fdt->fd[fd];    if (!myfile)     {         printk("myfile is null..\n");        return -1;     }     ppath = d_path(&(myfile->f_path), ppath, 100);     printk("FULLPATH: %s\n", ppath);     return 1; }

Relevant Link:

http://edsionte.com/techblog/archives/4406http://xd03071149.blog.163.com/blog/static/12350636320129822841854/

 

3. 基于dentry、vfsmount调用d_path()获取当前进程的"当前目录"

1. 首先得到文件对应的struct file结构2. 后再用结构中的f_dentry和f_vfsmnt字段充当d_path的前两个参数3. 得到了这个文件的绝对路径了具体步骤如下 

关于linux内核中和文件系统、VFS相关的数据结构,请参阅另一篇文章

http://www.cnblogs.com/LittleHann/p/3865490.html

code

#include <linux/module.h>#include <linux/fcntl.h>//for O_RDONLY#include <linux/fs.h>//for filp_open#include <linux/uaccess.h>//for get_fs#include <linux/limits.h>//for PATH_MAX #include <linux/sched.h> #include <linux/mm.h> #include <linux/fdtable.h> #include <linux/types.h>#include <linux/stat.h> #include <linux/unistd.h>#include <linux/dcache.h>#include <linux/fs_struct.h>  #include <linux/mount.h>#define MAX_TMPPATH 1024void get_absolute_path(char *mod_name){    /* 假设 1024 已经足够了 */    char tmp_path[MAX_TMPPATH] = {0};    char * ptr = NULL;    struct dentry *dentry = NULL;    struct vfsmount * mnt = NULL;    memset(tmp_path, 0, MAX_TMPPATH);    ptr = tmp_path + MAX_TMPPATH - 256;     task_lock(current);    /* Get the Process working dentry */    dentry = current->fs->pwd.dentry;     /* Get the Process working vfsmount */    mnt = current->fs->pwd.mnt;    do    {        /* Process the dentry */        while(dentry && dentry->d_name.name && strcmp(dentry->d_name.name,"/"))        {                ptr = ptr - strlen(dentry->d_name.name);                if(ptr <= tmp_path + strlen(dentry->d_name.name) + 1)                {                    break;                }                memcpy(ptr, dentry->d_name.name, strlen(dentry->d_name.name));                *(--ptr) = /;                dentry= dentry->d_parent;        }        /* Process the filesystem mountpoint, 突破挂载点 */        if(mnt && mnt->mnt_mountpoint && mnt->mnt_mountpoint->d_name.name && strcmp(mnt->mnt_mountpoint->d_name.name,"/"))        {                dentry = mnt->mnt_mountpoint;                ptr = ptr - strlen(dentry->d_name.name);                if(ptr <= tmp_path + strlen(dentry->d_name.name) + 1)                {                    break;                }                memcpy(ptr,dentry->d_name.name,strlen(dentry->d_name.name));                *(--ptr) = /;                mnt = mnt->mnt_parent;                dentry= dentry->d_parent;        }    } while( 0 !=  strcmp(mnt->mnt_mountpoint->d_name.name,"/")); /* end do */    /* 直到文件系统的挂载点为 / */    task_unlock(current);    //concat the full path    strcat(ptr, "/");    strcat(ptr, mod_name);    strcat(ptr, ".ko");    printk("full path: %s\n",ptr);}int init_module(void){     get_absolute_path(THIS_MODULE->name);}void cleanup_module(void){}MODULE_LICENSE("GPL");

Makefile

## Variables needed to build the kernel module#name      = fd_d_pathobj-m += $(name).oall: build.PHONY: build install cleanbuild:    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules CONFIG_DEBUG_SECTION_MISMATCH=yinstall: build    -mkdir -p /lib/modules/`uname -r`/kernel/arch/x86/kernel/    cp $(name).ko /lib/modules/`uname -r`/kernel/arch/x86/kernel/    depmod /lib/modules/`uname -r`/kernel/arch/x86/kernel/$(name).koclean:    [ -d /lib/modules/$(shell uname -r)/build ] &&     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Relevant Link:

http://blog.csdn.net/cenziboy/article/details/7999217

 

4. 基于get_fs_pwd获取当前目录

2.6.39以上才能用//获取.ko文件路径   /*get_fs_pwd(current->fs, &ko_pwd);ko_buf = (char*)__get_free_page(GFP_USER);ko_path = dentry_path_raw(ko_pwd.dentry, ko_buf, PAGE_SIZE); free_page((unsigned long)ko_buf);*/   /*getcwd(buf, sizeof(buf));*/

待研究

 

Copyright (c) 2014 LittleHann All rights reserved