2017-07-12 10 views
4

私はいつもがdup(NUM)に相当すると仮定しましたが、明らかにこれは当てはまりません!たとえば、dupファイル記述子を使用し、新しいfdを非ブロックに設定すると、元のファイル記述子にも影響します(非ブロック状態はファイル記述のプロパティであり、2つのファイル記述子は両方とも同じファイルの説明)。しかし、/proc/self/fd/NUMを開くと、新しい独立したファイル記述が得られたように見え、古いファイルと新しいファイルの非ブロック状態を個別に設定できます。これを使用して同じ匿名パイプを参照する2つのファイル記述を取得することもできます。それ以外は不可能です(example)。一方、dupソケットfdの場合は、NUMがソケットを参照するとopen("/proc/self/fd/NUM", flags)が失敗します。Linuxカーネルのコードはどこにオープンされていますか( "/ proc/self/fd/NUM")?

これは他の種類の特殊ファイルに対してどのように機能するのかを確認したいと思います。「このようにファイルを再オープンするとどのような権限チェックが行われますか?実際にはこのパスを実装しているLinuxのコードを見つけてください。しかし、私が読んでからfs/proc/fd.cを読み始めたとき、私はすばらしい操作構造の迷路ですっかり失われました。

だから私の質問です:誰もコードパスを説明してからopen("/proc/self/fd/NUM", flags)を実行することができますか?具体的には、NUMはパイプを指しており、最新のカーネルリリースについて話しています。

+0

興味深い質問です。 [proc_fd_link](http://elixir.free-electrons.com/linux/v4.12.1/source/fs/proc/fd.c#L138)で魔法が起こったようですが、これは '/ proc /自己/ fd/NUM'はへのリンクです。これは、オープンファイルテーブルから 'struct path *'(dentry、基本的に)をコピーするだけです。これは、dentryのinodeを開くための機能を実装するための元の 'struct path'を作成したものに任せます。この場合、[open_fifo](http://elixir.free-electrons.com/linux/v4.12.1/source/fs /pipe.c#L883)を 'fs/pipe.c'から削除します。 TIL:Linuxにはすべてのパイプが存在する "pipefs"があります。 –

答えて

3

コメントは、proc_fd_linkをご覧ください。これは良い考えです。コードがどのようにそこに到達できるかに問題がある場合は、systemtapで自分自身を助けることができます。ここでは魔法のスクリプトさ:/ FDの下からファイルを開くとき

probe kernel.function("proc_fd_link") { 
    print_backtrace(); 
} 

がそれを実行できます:

我々が見るproc_pid_get_linkで
0xffffffffbb2cad70 : proc_fd_link+0x0/0xd0 [kernel] 
0xffffffffbb2c4c3b : proc_pid_get_link+0x6b/0x90 [kernel] (inexact) 
0xffffffffbb36341a : security_inode_follow_link+0x4a/0x70 [kernel] (inexact) 
0xffffffffbb25bf13 : trailing_symlink+0x1e3/0x220 [kernel] (inexact) 
0xffffffffbb25f559 : path_openat+0xe9/0x1380 [kernel] (inexact) 
0xffffffffbb261af1 : do_filp_open+0x91/0x100 [kernel] (inexact) 
0xffffffffbb26fd8f : __alloc_fd+0x3f/0x170 [kernel] (inexact) 
0xffffffffbb24f280 : do_sys_open+0x130/0x220 [kernel] (inexact) 
0xffffffffbb24f38e : sys_open+0x1e/0x20 [kernel] (inexact) 
0xffffffffbb003c57 : do_syscall_64+0x67/0x160 [kernel] (inexact) 
0xffffffffbb8039e1 : return_from_SYSCALL_64+0x0/0x6a [kernel] (inexact) 

/* Are we allowed to snoop on the tasks file descriptors? */ 
if (!proc_fd_access_allowed(inode)) 
     goto out; 

/* permission checks */ 
static int proc_fd_access_allowed(struct inode *inode) 
{ 
     struct task_struct *task; 
     int allowed = 0; 
     /* Allow access to a task's file descriptors if it is us or we 
     * may use ptrace attach to the process and find out that 
     * information. 
     */ 
     task = get_proc_task(inode); 
     if (task) { 
       allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS); 
       put_task_struct(task); 
     } 
     return allowed; 
} 
aaaand

明らかに、あなたはptraceで接続しているのと同じパーマです。

最後に、ソケットを開くのが失敗するのはなぜですか? straceはENXIOが返されることを示します。 。ENXIOのFS/* cは明らかに迅速にgit grepを:

static int no_open(struct inode *inode, struct file *file) 
{ 
     return -ENXIO; 
} 

コードがno_openを使用して終わるかチェックは読者の練習として残しています。また、ソースコードを変更せずにprintfのようなデバッグにsystemtapを使うこともできます。また、関数からの「戻り」に配置してエラーコードを報告することもできます。

関連する問題