要求:
高級(jí)操作系統(tǒng)與分布式系統(tǒng)作業(yè)
ps和top命令列出了unix中當(dāng)前所有進(jìn)程的相關(guān)信息,作業(yè)要求在linux中增加兩個(gè)系統(tǒng)調(diào)用,功能如下:
hide():執(zhí)行此系統(tǒng)調(diào)用后,隱藏當(dāng)前進(jìn)程,即當(dāng)前進(jìn)程不能夠被ps和top命令查看到。
unhide():執(zhí)行此系統(tǒng)調(diào)用后,取消隱藏當(dāng)前進(jìn)程,即當(dāng)前進(jìn)程恢復(fù)正常,能夠被ps和top命令查看到。
解題思路:
Ps命令和top命令從/proc文件系統(tǒng)中讀取進(jìn)程信息并顯示出來。因此,如果一個(gè)進(jìn)程的進(jìn)程號(hào)沒有在/proc文件系統(tǒng)中反映出來,則這個(gè)進(jìn)程被“隱藏”了,“隱藏”進(jìn)程在ps或top命令的輸出不出現(xiàn)。
2。修改linux的進(jìn)程控制塊task_struts,在進(jìn)程控制塊中增加一個(gè)字段:
int hide;
hide的值為1時(shí),表示該進(jìn)程被隱藏;為0時(shí),表示該進(jìn)程不被隱藏。
3。修改創(chuàng)建進(jìn)程的相關(guān)代碼,在進(jìn)程創(chuàng)建時(shí),置hide為0;即進(jìn)程在初始創(chuàng)建時(shí)(默認(rèn))不被隱藏。
4。在系統(tǒng)中增加系統(tǒng)調(diào)用hide(),其功能為:
1)將進(jìn)程控制塊中的hide置1;
2)刪除/proc文件系統(tǒng)中該進(jìn)程的相關(guān)目錄項(xiàng);
5。在系統(tǒng)中增加系統(tǒng)調(diào)用unhide(),其功能為:
1)將進(jìn)程控制塊中的hide清0;
2)增加/proc文件系統(tǒng)中該進(jìn)程的相關(guān)目錄項(xiàng)
具體做法:(實(shí)驗(yàn)內(nèi)核版本2.6.28,)
跟蹤內(nèi)核可知,proc目錄下進(jìn)程號(hào)目錄是動(dòng)態(tài)生成的,是在每次readdir,getdents時(shí)動(dòng)態(tài)生成,所以從某種意義上說增加或刪除/proc文件系統(tǒng)中該進(jìn)程的相關(guān)目錄項(xiàng)這種說法是不正確的。proc目錄內(nèi)容的填充函數(shù)是proc_pid_readdir(fs/proc/base.c)
int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) //內(nèi)核源碼,修改前
{
unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
struct tgid_iter iter;
struct pid_namespace *ns;
if (!reaper)
goto out_no_task;
for (; nr < ARRAY_SIZE(proc_base_stuff); filp->f_pos++, nr++) { //這個(gè)for,填充self目錄
const struct pid_entry *p = &proc_base_stuff[nr];
if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0)
goto out;
}
ns = filp->f_dentry->d_sb->s_fs_info;
iter.task = NULL;
iter.tgid = filp->f_pos - TGID_OFFSET;
for (iter = next_tgid(ns, iter);
iter.task;
iter.tgid += 1, iter = next_tgid(ns, iter)) { //這個(gè)for,根據(jù)系統(tǒng)內(nèi)進(jìn)程動(dòng)態(tài)添加子進(jìn)程號(hào)目錄,也正是我們需要修改的函數(shù)
filp->f_pos = iter.tgid + TGID_OFFSET;
if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
put_task_struct(iter.task);
goto out;
}
}
filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET;
out:
put_task_struct(reaper);
out_no_task:
return 0;
}
將proc_pid_readdir函數(shù)中的for循環(huán)修改為
for (iter = next_tgid(ns, iter);
iter.task;
iter.tgid += 1, iter = next_tgid(ns, iter)) { //這個(gè)for,根據(jù)系統(tǒng)內(nèi)進(jìn)程動(dòng)態(tài)添加子進(jìn)程號(hào)目錄,也正是我們需要修改的函數(shù)
if(!iter.task->hide){
filp->f_pos = iter.tgid + TGID_OFFSET;
if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
put_task_struct(iter.task);
goto out;
}
}
}
修改task_struct 添加hide字段(include/linux/sched.h)
struct task_struct{
...//現(xiàn)有字段
int hide;//添加hide字段,切忌不要在最開始添加,因?yàn)殚_始的字段的偏移量已固定,內(nèi)核中其他部分已直接引用,如果在最開始添加,將導(dǎo)致現(xiàn)有代碼不能正常工作
}
修改進(jìn)程創(chuàng)建代碼,初始化時(shí)置hide字段為0,修改copy_process函數(shù)(kernel/fork.c)
p = dup_task_struct(current);
if (!p)
goto fork_out;
p->hide=0;//添加
rt_mutex_init_task(p);
最后一步就是添加系統(tǒng)調(diào)用了,
修改kernel/sys.c
添加
asmlinkage long sys_hide()
{
current->hide=1;
return 0;
}
asmlinkage long sys_unhide()
{
current->hide=0;
return 0;
}
修改arch/x86/asm/include/unistd_32.h
#define __NR_inotify_init1 332
#define __NR_hide 333
#define __NR_unhide 334
#ifdef __KERNEL__
修改arch/x86/kernel/syscall_table_32.s
.long sys_dup3 /* 330 */
.long sys_pipe2
.long sys_inotify_init1
.long sys_hide
.long sys_unhide
重新編譯內(nèi)核...OK....

實(shí)驗(yàn)驗(yàn)證:
1 test_hide.c
#include <stdio.h>
int main(){
int pid=getpid();
char command[80];
sprintf(command,"ps aux|grep %d\n",pid);
printf("-------------------------------\n");
system(command);
printf("-------------------------------\n");
asm volatile(\
"int $0x80"\
::"a"(333)); // 執(zhí)行333號(hào)系統(tǒng)調(diào)用即sys_hide
system(command);
asm volatile(\
"int $0x80"\
::"a"(334));
printf("-------------------------------\n");
system(command);
printf("-------------------------------\n");
return 0;
}
2 運(yùn)行,查看實(shí)驗(yàn)結(jié)果
