0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Apache】RewriteMap prg では、セカンダリグループが無視される

Last updated at Posted at 2025-10-28

English version is available here!

1. 環境

項目
OS Rocky Linux 9
httpサーバ Apache/2.4.62

2. 問題

httpd.conf
# ...
RewriteEngine On
RewriteMap some_map "prg:/usr/bin/php /usr/local/bin/some_map.php" apache:apache
RewriteCond ${some_map:} ^(.*)$
RewriteRule ^ -

として、さらに /usr/local/bin/some_map.php

項目 設定
所有者 root:myapp
パーミッション 770

とした場合を考える。

そして、 ユーザ apache は、 グループ myapp に所属しているものとする。


直感的には、この場合 some_map を呼び出すにあたって権限エラーにはならないように思える。

  • RewriteMap の第3引数 (username:groupname)により、 some_map の実行者は apache:apache になる
  • ユーザ apache はグループ myapp に所属している
  • よって /usr/local/bin/some_map.php (770 / root:myapp) にはアクセスできるはず

ところが実際には:

Could not open input file: /usr/local/bin/some_map.php

が発生し、 some_map の呼び出しに失敗する。

エラーログの取得方法
  1. httpd.confLogLevel rewrite:trace5 とする
  2. sudo tail /var/log/httpd/error_log | grep map を実行する

すると、次のような結果を得る。

エラーログ
[Mon Oct 27 15:26:21.250136 2025] [rewrite:trace5] [pid pppppp:tid tttttt] mod_rewrite.c(505): [client x.x.x.x:x] x.x.x.x - - [wikinebula.org/sid#ssssssssssss][rid#rrrrrrrrrrrr/initial] map lookup OK: map=some_map key= -> val=Could not open input file: /usr/local/bin/some_map.php

(エラーログの取得方法 ここまで)

3. 原因

結論から言うと:

RewriteMap prg: によって起動される外部プロセスは setuid() / setgid() による「明示されたユーザ:グループのみ」しか反映されず、
ユーザのセカンダリグループは一切引き継がれない

つまり、「apachemyapp に所属している」というセカンダリグループの情報が無効化されている。

3-1. なぜセカンダリグループが消えるのか

それは、 Apache が外部プログラムを起動する際に使用する APR (Apache Portable Runtime) の実装に原因がある。

該当箇所は apache/apr/threadproc/unix/proc.c の 関数 apr_proc_create() :

ここでは:

操作 実行される? 備考
setgid(attr->gid) される 明示されたグループのみ変更※
setuid(attr->uid) される 実行ユーザを変更
initgroups(user, gid) されない !!! 問題の核心 !!!

RewriteMap の第3引数が username:groupname の場合に、 groupname のみが変更される

3-2. initgroups() の役割

Unix / Linux では:

システムコール 影響範囲
setuid() ユーザを切り替える
setgid() 明示されたグループ(なければプライマリグループ)に切り替える
initgroups(user, gid) そのユーザが所属するセカンダリグループ一覧をカーネルに設定する

つまり、 setgid() / setuid() だけではセカンダリグループは反映されない。
これが今回の現象そのもの。

4. 実際の挙動を確認する

4-1. やりたいこと

some_map.php 内で /proc/self/status の内容を通常ファイルに書き出すことで、
some_map.php がどのような ユーザ, グループ で実行されているかを確認しよう。

(そのため、一時的に some_map.php のパーミッションを変更して、誰でもアクセス可能にする)

4-2. 手順

  1. まず、一時的に:
    sudo chmod 777 /usr/local/bin/some_map.php
    
    して some_map.php に誰でもアクセスできるようにする。
     
  2. 次に:
    sudo touch /var/lib/status.txt
    sudo chmod 777 /var/lib/status.txt
    
    を実行して、誰でも読み書き出来る /var/lib/status.txt を作る。
     
  3. そして /usr/local/bin/some_map.php の中で:
    /usr/local/bin/some_map.php
    <?php
    file_put_contents('/var/lib/status.txt', file_get_contents('/proc/self/status'));
    
    とすることで、 /var/lib/status.txt に プログラム some_map を実行しているプロセスのステータス情報を書き込むようにする。
     
  4. Apache を再起動する。
     
  5. /var/lib/status.txt を見てみると、次のようになる(抜粋):
    /var/lib/status.txt(抜粋)
    Uid:    48      48      48      48
    Gid:    48      48      48      48
    FDSize: 64
    Groups:
    

4-3. 結果について

Groups: が空になっていることから、セカンダリグループが読み込まれていないことが分かる。

ちなみに Uid:Gid:48は、 apacheuid および gid である。
4つ並んでいるのは、順に

  • 実 UID/GID
  • 実効 UID/GID
  • 保存 set-UID/GID
  • ファイルシステム UID/GID

である。

5. 対策

sudo -u username -g groupname を利用する。

つまり:

RewriteMap some_map "prg:/usr/bin/php /usr/local/bin/some_map.php" apache:apache

を、次のものに置き換える:

RewriteMap some_map "prg:/usr/bin/sudo -u apache -g apache /usr/bin/php /usr/local/bin/some_map.php"

RewriteMap では、第3引数が省略されると、 Apache 起動時の権限 (通常 root) でプログラムを起動する。
このプログラムで sudo -u username -g groupname を利用すれば、Apache ではなく sudo のほうで権限の切り替えが起こるので、セカンダリグループが正しく読み込まれる。

実際、上記の置き換えを行って、再度 /var/lib/status.txt を出力させると、次のようになる(抜粋):

/var/lib/status.txt(抜粋)
Uid:    48      48      48      48
Gid:    48      48      48      48
FDSize: 64
Groups: 48 1001

1001 は、セカンダリグループ myapp の グループID である。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?