システムコール下のDSは?


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

ユーザプロセスが、システムコールでカーネルモードに入ってとき、CS/DSはカーネルの__KERNEL_CS/__KERNEL_DSで動作しているものとばっかし思っていた。

システムコールがコールされると、アセンブラで記述されたsystem_callへ処理が移る。そこでaxにセットされたシステムコールNOから、その処理へとコールされるが、その前にSAVE_ALLマクロで、レジスタをpush。でその後DSセレクタに__USER_DSを設定してる・・・。と言うことは、システムコール下のカーネルパスは、__USER_DSで動作しているってわけ?
.macro SAVE_ALL
       cld
       PUSH_GS
       pushl_cfi %fs
       pushl_cfi %es
       pushl_cfi %ds
       pushl_cfi %eax
       CFI_REL_OFFSET eax, 0
       pushl_cfi %ebp
       CFI_REL_OFFSET ebp, 0
       pushl_cfi %edi
       CFI_REL_OFFSET edi, 0
       pushl_cfi %esi
       CFI_REL_OFFSET esi, 0
       pushl_cfi %edx
       CFI_REL_OFFSET edx, 0
       pushl_cfi %ecx
       CFI_REL_OFFSET ecx, 0
       pushl_cfi %ebx
       CFI_REL_OFFSET ebx, 0
       movl $(__USER_DS), %edx
       movl %edx, %ds
       movl %edx, %es
       movl $(__KERNEL_PERCPU), %edx
       movl %edx, %fs
       SET_KERNEL_GS %edx
.endm
とりあえず、実際どうなのか見てみるのが一番ってことで、/proc/hogehogeのwrite時のDSを確認するサンプル。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>

#define PROC_NAME "hogehoge"

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

static struct proc_dir_entry *dirp;

char *k_buff = "abc";
static int proc_init_module(void)
{
   printk("kernel[%x] user[%x]\n", __KERNEL_DS, __USER_DS);

   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, char __user *u_buff,
                                  unsigned long len, void *data )
{
   int i = 0;

   myget_ds("proc_write start");
   while (1) {
       if (u_buff[i] == 0x0a) {
           u_buff[i] = 0x00;
           break;
       }
       i++;
   }
   printk("kbuff:[%p]:[%s]\n", k_buff, k_buff);
   printk("ubuff:[%p]:[%s]\n", u_buff,  u_buff);
   myget_ds("proc_write end");
   return len;
}

static  void    myset_ds(void)
{
   asm ("movw $0x68, %ax;"
        "movw %ax, %ds;");
}

static  void    myget_ds(const char* msg)
{
    short int   ds;

     asm ("movw %%ds, %%ax;"
          "movw %%ax, %0;"
           :"=r"(ds)
           :
           :"%ax");
     printk("ds %s:%x\n", msg, ds);
}
module_init(proc_init_module);
module_exit(proc_cleanup_module);
動作結果1
DS=7bの__USER_DS下で動作している。
[76758.013174] kernel[68] user[7b]     <-__KERNEL_DS=0x68/__USER_DS=0x7b
[76770.346988] ds proc_write start:7b
[76770.346998] kbuff:[e0aa608e]:[abc]
[76770.347002] ubuff:[b7477000]:[123]
[76770.347005] ds proc_write end:7b    <-__USER_DS
動作結果2(proc_write()のmyset_ds()を有効にして__KERNEL_DSで動作)
DS=68の__KERNEL_DSにしても問題なさそう。
[77591.594712] ds proc_write start:7b
[77591.594712] kbuff:[e0a6e08e]:[abc]
[77591.594712] ubuff:[b7477000]:[123]
[77591.594712] ds proc_write end:68     <-__KERNEL_DS
確か__USER_DS/__KERNEL_DSとも、DPLのみの違いで、ペース=0/リミット=0xfffffのはず。カーネルモードでのアクセスには支障はないんだろうけど・・・? でもなんで、わざわざSAVE_ALLマクロで__USER_DSに設定するのかな? セキュリィティ上の理由? X86のプロテクトモードわかっておりません。

カーネルスレッドはどうなのかな?

最終更新 2012/07/30 19:25:14 - north
(2012/07/30 19:25:14 作成)


検索

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