コンテキスト:linux-5.0/Documentation/process/adding-syscalls.rst#do-not-call-system-calls-in-the-kernel
まず、カーネルコードは呼び出し規則が間違っているため、「sys_xyzzy()」などの関数を呼び出すことはできません。
しかし、第二に、「データへのアクセス方法はカーネルデータとユーザーデータの間で異なる可能性があります。」
これで、以前の "sys_xyzzy()" 呼び出しを直接置き換える関数があります。例: ksys_mount().
ksys_mount() __user
sys_mount() を呼び出すのと同様に、メモリへのポインタを取得します。したがって、カーネルメモリへのポインタを渡すと失敗するはずです。具体的には、copy_from_user() 呼び出し時に失敗します。ゲームをプレイするためにset_fs()を使用しない限り。
それでは...カーネルの別の場所でksys_mount()を何度も呼び出すのはなぜですか?これらのどれがどのように機能するのですか? set_fs() への呼び出しは含まれていません。
https://elixir.bootlin.com/linux/v5.0/ident/ksys_mount
- ドライバ/ベース/devtmpfs.c
- 初期化/do_mounts.c
- ...
答え1
devtmpfs
現在、カーネルスレッドで実行中です。カーネルスレッドではaddr_limit
効果的に無効になります。少なくともx86の場合はそうです。これはアーキテクチャ固有のコードです。
init/do_mounts.c
とても似ています。カーネル初期化プロセスはカーネルスレッドのように起動し、効果addr_limit
的に無効にする必要があります。その後、do_execve()
ユーザー空間初期化プログラムを呼び出して実行を開始します。コア必ず「set_fs(USER_DS)」を呼び出してください。、ユーザー空間プログラムを実行する前に。