通過call_usermodehelper()在核心態執行使用者程式【轉】

來源:互聯網
上載者:User

標籤:

轉自:http://edsionte.com/techblog/archives/category/linux%E5%86%85%E6%A0%B8%E7%BC%96%E7%A8%8B背景

如何在Linux核心中執行某些使用者態程式或系統命令?在使用者態中,可以通過execve()實現;在核心態,則可以通過call_usermodehelpere()實現該功能。如果您查閱了call_usermodehelper()核心功能的源碼實現,就可以發現該函數最終會執行do_execve()。而execve系統調用在經曆核心的系統調用流程後,也會最終調用do_execve()。

使用舉例

1.無輸出的可執行檔測試

載入函數demo如下所示:

1 static int __init call_usermodehelper_init(void)
2 {
3     int ret = -1;
4     char path[] = "/bin/mkdir";
5     char *argv[] = {path, "-p", "/home/tester/new/new_dir", NULL};
6  
7     printk("call_usermodehelper module is starting..!\n");
8     ret = call_usermodehelper(path, argv, envp, UMH_WAIT_PROC);
9     printk("ret=%d\n", ret);
10     return 0;
11 }

卸載函數demo如下所示:

1 static void __exit call_usermodehelper_exit(void)
2 {
3     int ret = -1;
4     char path[] = "/bin/rm";
5     char *argv[] = {path, "-r", "/home/tester/new", NULL};
6     char *envp[] = {NULL};
7  
8     printk("call_usermodehelper module is starting..!\n");
9     ret = call_usermodehelper(path, argv, envp, UMH_WAIT_PROC);
10     printk("ret=%d\n", ret);
11 }

2.有輸出的可執行檔測試

如果該可執行檔有輸出,則可以利用輸出重新導向,不過此時的可執行檔應該是/bin/bash,而實際的可執行檔則稱為bash的參數。比如如果想在核心執行ls -la命令,並且將其輸出重新導向到ls_output中,則在上述的argv[]={“/bin/bash”, “-c”, “ls”, “-la”, “>”, “/home/tester/ls_output”, NULL};

本文雖然說明的是在核心態如何調用使用者態程式,不過可以將這種方法抽象一下,看作是核心態主動向使用者態發起通訊的一種方式。

沒有評論 »

發表在Linux核心編程

Tags: 核心態 資料互動 使用者態

Linux核心中通過檔案描述符擷取絕對路徑 2014年3月19日背景

在Linux核心中,已知一個進程的pid和其開啟檔案的檔案描述符fd,如何擷取該檔案的絕對路徑?基本思路是先擷取該檔案在核心中的file結構體,再通過d_path()擷取到整個檔案的絕對路徑。

方法一

如果理解了進程和檔案系統資料結構之間的關係,那麼這種方法可以採用。基本的方法如下:

1.通過進程pid擷取進程描述符task_struct;

2.通過task_struct擷取該進程開啟檔案結構files_struct,從而擷取檔案描述符表;

3.以fd為索引在檔案描述符表中擷取對應檔案的結構體file;

4.通過file擷取對應path結構,該結構封裝當前檔案對應的dentry和掛載點;

5.通過核心功能d_path()擷取該檔案的絕對路徑;

通過進程pid擷取進程描述符demo:

1 struct task_struct *get_proc(pid_t pid)
2 {
3     struct pid *pid_struct = NULL;
4     struct task_struct *mytask = NULL;
5  
6     pid_struct = find_get_pid(pid);
7     if (!pid_struct)
8         return NULL;
9     mytask = pid_task(pid_struct, PIDTYPE_PID);
10     return mytask;
11 }

通過fd以及d_path()擷取絕對路徑demo:

1 int get_path(struct task_struct *mytask, int fd)
2 {
3         struct file *myfile = NULL;
4         struct files_struct *files = NULL;
5         char path[100] = {‘\0‘};
6         char *ppath = path;
7  
8         files = mytask->files;
9         if (!files) {
10                 printk("files is null..\n");
11                 return -1;
12         }
13         myfile = files->fdt->fd[fd];
14         if (!myfile) {
15                 printk("myfile is null..\n");
16                 return -1;
17         }
18         ppath = d_path(&(myfile->f_path), ppath, 100);
19  
20         printk("path:%s\n", ppath);
21         return 0;
22 }

從上面的代碼可以看出,從fd到file結構的擷取均通過各個資料結構之間的指向關係擷取。

方法二

與方法一的思路相同,但是可以直接使用核心提供的函數fget()進行fd到file的擷取。這種方法使用比較簡單,程式更加安全,不過就是少了對資料結構關係的思考過程。其實也可以將fget()函數的實現過程作為參考,欣賞核心中代碼實現的嚴謹性。

 

Linux核心中通過檔案描述符擷取絕對路徑已關閉評論 »

發表在Linux核心編程

Tags: 核心編程 檔案系統 檔案路徑

libc庫和系統調用 2012年6月2日

Linux系統調用這部分經常出現兩個詞:libc庫和封裝函數,不知道你是否清楚它們的含義?

libc

libc是Standard C library的簡稱,它是符合ANSI C標準的一個標準函數庫。libc庫提供C語言中所使用的宏,類型定義,字串操作函數,數學計算函數以及輸入輸出函數等。正如ANSI C是C語言的標準一樣,libc只是一種函數庫標準,每個作業系統都會按照該標準對標準庫進行具體實現。通常我們所說的libc是特指某個作業系統的標準庫,比如我們在Linux作業系統下所說的libc即glibc。glibc是類Unix作業系統中使用最廣泛的libc庫,它的全稱是GNU C Library。

類Unix作業系統通常將libc庫作為作業系統的一部分,它被視為作業系統與使用者程式之間的介面。libc庫不僅實現標準C語言中的函數,而且也包含自己所屬的函數介面。比如在glibc庫中,既包含標準C中的fopen(),又包含類Unix系統中的open()。在類Unix作業系統中,如果缺失了標準庫,那麼整個作業系統將不能正常運轉。

與類Unix作業系統不同的是,Windows系統並不將libc庫作為整個核心作業系統的一部分。通常每個編譯器都附屬自己的libc庫,這些libc既可以靜態編譯到程式中,又可以動態編譯到程式中。也就是說應用程式依賴編譯器而不是作業系統。

封裝函數

在Linux系統中,glibc庫中包含許多API,大多數API都對應一個系統調用,比如應用程式中使用的介面open()就對應同名的系統調用open()。在glibc庫中通過封裝常式(Wrapper Routine)將API和系統調用關聯起來。API是標頭檔中所定義的函數介面,而位於glibc中的封裝常式則是對該API對應功能的具體實現。事實上,我們知道介面open()所要完成的功能是通過系統調用open()完成的,因此封裝常式要做的工作就是先將介面open()中的參數複製到相應寄存器中,然後引發一個異常,從而系統進入核心去執行sys_open(),最後當系統調用執行完畢後,封裝常式還要將錯誤碼返回到應用程式中。

需要注意的是,函數庫中的API和系統調用並沒有一一對應的關係。應用程式藉助系統調用可以獲得核心所提供的服務,像字串操作這樣的函數並不需要藉助核心來實現,因此也就不必與某個系統調用關聯。

不過,我們並不是必須通過封裝常式才能使用系統調用,syscall()和_syscallx()兩個函數可以直接調用系統調用。具體使用方法man手冊中已經說明的很清楚了。

參考:

1. http://en.wikipedia.org/wiki/Libc

2. man syscalls

通過call_usermodehelper()在核心態執行使用者程式【轉】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.