首页 > 代码库 > 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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。