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


task構造体のeuidを直接書き換えて、root権限を設定するサンプルです。

kernel 2

#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	chg_euid(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) { 
		chg_euid(process);
	}
	else {
		printk("pid error:%d\n", mypid);
   		return -EFAULT;
	}
	return len;
}

static  void    chg_euid(struct task_struct *process)
{ 
	process->euid = 0;
}

module_init(proc_init_module);
module_exit(proc_cleanup_module);

kernel 3

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

MODULE_LICENSE("GPL");

#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    chg_euid(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];
       int     pidno;
       struct  pid     *my_pid;
       struct task_struct *process;

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

       my_pid = find_get_pid(pidno);
       process = get_pid_task(my_pid,  PIDTYPE_PID);

       if (process) {
               chg_euid(process);
       }
       return len;
}

static  void    chg_euid(struct task_struct *process)
{
       struct cred *c;

       c = (struct cred *)__task_cred(process);

       printk("%s:%d\n", process->comm, c->euid);
       c->euid = 0;
}

module_init(proc_init_module);
module_exit(proc_cleanup_module);

動作確認

[kitamura@localhost lkm]# insmod sample.ko
[kitamura@localhost lkm]# su kitamura
[kitamura@localhost lkm]$ cat /etc/shadow
cat: /etc/shadow: 許可がありません

[kitamura@localhost lkm]$ ps
  PID TTY          TIME CMD
11786 pts/0    00:00:00 bash
11806 pts/0    00:00:00 ps

[kitamura@localhost lkm]$ echo 11786 > /proc/hogehoge

[kitamura@localhost lkm]$ dmesg
  :
[29493.018034] pcnet32 0000:02:01.0: eth0: link down
[29505.004610] pcnet32 0000:02:01.0: eth0: link up
[29522.009885] pcnet32 0000:02:01.0: eth0: link down
[29534.005087] pcnet32 0000:02:01.0: eth0: link up
[31874.759000] bash:1000

[kitamura@localhost lkm]$ cat /etc/shadow
  :
root:$$8l4a.5Bm$tuixsbkdSwvmtMq6BV40:14522:0:99999:7:::
bin:*:14498:0:99999:7:::
daemon:*:14498:0:99999:7:::

[kitamura@localhost lkm]$ dmesg
  :
[29493.018034] pcnet32 0000:02:01.0: eth0: link down
[29505.004610] pcnet32 0000:02:01.0: eth0: link up
[29522.009885] pcnet32 0000:02:01.0: eth0: link down
[29534.005087] pcnet32 0000:02:01.0: eth0: link up
[31874.759000] bash:1000
kernel2では、process->euid=0としていますが、kernel3ではprocess->cred->euid=0としています。kernel3では、euid/uid/gid等の実態は、struct credに配置して、task構造体から切り離し、リスト接続しています。こうする事で、do_fork()の子プロセスは、task構造体は親のコピーで、新規にアロケートは子プロセスを作成の負荷を軽減できるわけです。しかも頻度にこの内容を変更することもありません。

サンプルではprocess->cred->euid=0としていますが、__task_cred(process)の返り値は const struct task_struct *と定義されていて、返値のポインターで更新することはできません。競合の問題もありますが、直接変更するとそれをリストしている他のプロセスの権限も変更してしまうことになります。そのためstruct task_struct *とキャストしていますが。これは正しくありません。本来は、新たにcredを割り当て、それを更新し、task構造体に接続されているrcuリストとしてノードを差し替えることで実装しなければなりません。

最終更新 2013/11/05 14:37:54 - north
(2010/01/10 12:49:03 作成)


検索

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