task_structのeuidを書き換えてrootになる


Rev.5を表示中。最新版はこちら

プロセスは固有のtask_struct構造体で管理されるコンテキストを有しています。はそこからいろいろなstructが紐づいているのですが、こいつがプロセスその物と言っても過言でありません。従ってtask_structを操作することはプロセスそのものを操作することになります。

で、まずはtask_structのeuidを書き換えて、一般プロセスがroot権限で動作できることを確認します。

動作確認カーネルモジュール

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>


#define PROC_NAME "hogehoge"

static size_t proc_write( struct file *filp, const char __user *buff,
                        unsigned long len, void *data );

static struct proc_dir_entry *dirp;
static	void	do_test(struct task_struct *process);

static int proc_init_module(void)
{
        dirp = (struct proc_dir_entry *)
                create_proc_entry(PROC_NAME, 0666, (struct proc_dir_entry *) 0);
        if (dirp == 0)
                return(-EINVAL);
        dirp->write_proc = (write_proc_t *) proc_write;

        return 0;
}

static void proc_cleanup_module(void)
{
        remove_proc_entry(PROC_NAME, (struct proc_dir_entry *) 0);
}


static size_t proc_write( struct file *filp, const char __user *buff,
                        unsigned long len, void *data )
{
	char	_buff[64];

	if (copy_from_user(_buff, buff, len )) {
    		return -EFAULT;
	}
	int	mypid = (int)simple_strtol(_buff, NULL, 0);

	struct task_struct *process;
	process = find_task_by_vpid(mypid);
	if (process) { 
		do_test(process);
	}
	else {
		printk("pid error:%d\n", mypid);
    		return -EFAULT;
	}
	return len;
}

static  void    do_test(struct task_struct *process)
{ 
	process->euid = 0;
}
 
module_init(proc_init_module);
module_exit(proc_cleanup_module);

Makefile

KERNELSRCDIR = ~/rpmbuild/BUILD/kernel-2.6.27/linux-2.6.27.i686/
BUILD_DIR := $(shell pwd)
VERBOSE = 0

# モジュール名
obj-m := test.o

all:
       make -C $(KERNELSRCDIR) SUBDIRS=$(BUILD_DIR) KBUILD_VERBOSE=$(VERBOSE) modules

clean:
       rm -f *.o
       rm -f *.ko
       rm -f *.mod.c
       rm -f *~

モジュールをカーネルに組み込む
[root@localhost test]# insmod test.ko

/proc下にhogehogeが作成されているの確認
[root@localhost test]# ls /proc/hogehoge
/proc/hogehoge

一般ユーザになる。
[root@localhost test]# su kitamura
[kitamura@localhost test]$ cat /etc/shadow
cat: /etc/shadow: 許可がありません

自bashのプロセスIDを確認
[kitamura@localhost test]$ ps
  PID TTY          TIME CMD
11786 pts/0    00:00:00 bash
11806 pts/0    00:00:00 ps

そのプロセスIDを/proc/hogehogeに書き込む
[kitamura@localhost test]$ echo 11786 > /proc/hogehoge

root権限で動作できることを確認
[kitamura@localhost test]$ cat /etc/shadow
root:$$8l4a.5Bm$tuixsbkdSwvmtMq6BV40:14522:0:99999:7:::
bin:*:14498:0:99999:7:::
daemon:*:14498:0:99999:7:::

備忘

下記設定はカーネルモジュールお決まりのまじない。モジュールがロードされたときに呼び出す処理をproc_init_module、アンロードされるときの処理をproc_cleanup_moduleに記述する。
module_init(proc_init_module);
module_exit(proc_cleanup_module);

proc_init_moduleではアクセスモード666で/procファイルシステム下にPROC_NAME "hogehoge"を作成。その書き込みコールバック処理をproc_writeに設定している。これで、/proc/hogehogeに何か書き込まれたらproc_writeが呼ばれる。

proc_writでcopy_from_userで書き込まれたデータ(プロセスID)を取得し、find_task_by_vpidで該当するtask_structを取得し、rootのIDである0をprocess->euidにセットすればroot権限で動作する。

rootって頑丈な牙城ってイメージですが、内部的にこれだけなんですね。実証してみるとちょっとへ〜って感じでした。

最終更新 2010/01/10 17:04:35 - north
(2010/01/10 12:49:03 作成)


検索

アクセス数
2855700
最近のコメント
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
Adsense
広告情報が設定されていません。