Linuxでシンボリックリンクを含んだパスを正しいパス(realpath)に変換する

■ realpath_for_fs() [Download]
・シンボリックリンクを含んだ絶対パスを安全にrealpathに変換

しばしば、シンボリックリンクを含んだ絶対パスをシンボリックリンクを含まない絶対パス(realpath)としてみたい場合がある。

特に、apacheモジュールを実装する上で、apacheはシンボリックリンクをrealpathに解析した上で、Directiveを見てくれないため、realpathでDirectiveを書いていても、シンボリックリンク経由でアクセスがあった場合は、Direvtiveのパスは無視される。

パスのBaseネームがシンボリックリンクであれば、symlinksコマンド等で調べることができるが、絶対パスの途中にシンボリックリンクが含まれている場合はそう簡単には行かない。

例えば、

/var/www/html/link_dir   ->  /tmp/link_dir

だったらsymlinksでrealpathを見つけることができるが、

/var/www/html/link_dir/path/to/dir/file  ->  /var/www/html/link_dir/path/to/dir/file

といったように、途中にシンボリックリンクが含む場合は解析することができない。

一応はLinux上には、それを解析するrealpathコマンドがあるが、このコマンドはあまりよくない。

man realpth
BUGS
Avoid  using  this  function.  It is broken by design since (unless using the non-standard resolved_path == NULL feature) it is impossible to determine a suitable size for the output buffer, resolved_path.  According to POSIX a buffer of size PATH_MAX suffices, but PATH_MAX need not be a defined  constant, and  may  have  to  be obtained using pathconf().  And asking pathconf() does not really help, since on the one hand POSIX warns that the result of path-conf() may be huge and unsuitable for mallocing memory. And on the other hand pathconf() may return -1 to signify that PATH_MAX is not bounded.
The libc4 and libc5 implementation contains a buffer overflow (fixed in libc-5.4.13).  Thus, set-user-ID programs like mount need a private version.

このあたりの内容を簡単に説明すると、realpath自身でpathの適切なバッファサイズを決定し書き込みの上限サイズを指定することができないのである。

realpathで決定するpathのバッファサイズはPATH_MAXであるが、PATH_MAXが定義されていない場合はpathconfを使って上限値を取得する。

しかし、その値は十分な値である保証がないからである。

そこで、今回は安全な上限サイズを指定できるapr仕様のrealpathを実装してみた。

static char *
realpath_for_fs(const char *path, char *resolved_path, int maxreslth, apr_pool_t *p)

と定義し、

realpath_for_fs(ap_document_root(r), real_path_dir, PATH_MAX, r->pool)

と値を渡してやることで、PATH_MAX+1のバッファサイズを指定してやるのだ。

あとは、随所でapacheで使えるように、aprを使ってメモリ管理を行った。

    buf = apr_pcalloc(p, sizeof(char *));
    npath = resolved_path;

適切にバッファサイズをみて解析をしてくれるので、安全に使うことができる。

「Linuxでシンボリックリンクを含んだパスを正しいパス(realpath)に変換する」への1件のフィードバック

コメントは受け付けていません。