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] Secondary groups are ignored in RewriteMap `prg`

Last updated at Posted at 2025-10-28

日本語の記事は こちら

1. Environment

Item Value
OS Rocky Linux 9
HTTP Server Apache/2.4.62

2. Problem

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

Now, suppose /usr/local/bin/some_map.php has the following settings:

Item Setting
Owner root:myapp
Permission 770

And the user apache belongs to the group myapp.


At first glance, this setup should work without permission errors when invoking some_map:

  • The third argument (username:groupname) in RewriteMap means the program runs as apache:apache.
  • The user apache belongs to the group myapp.
  • Therefore, /usr/local/bin/some_map.php (770, root:myapp) should be accessible.

However, in reality:

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

appears, and the call to some_map fails.

How to get the error log
  1. Set LogLevel rewrite:trace5 in httpd.conf
  2. Run sudo tail /var/log/httpd/error_log | grep map

You’ll get an output like this:

error_log
[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

(End of error log instructions)

3. Cause

In short:

The external process started by RewriteMap prg: only reflects the explicitly specified user:group through setuid() and setgid(),
but it does not inherit any secondary groups.

That is, the secondary group information such as "apache belongs to myapp" is completely ignored.

3-1. Why the secondary groups disappear

The reason lies in how Apache launches external programs through the APR (Apache Portable Runtime) library.

Specifically, in the function apr_proc_create() within apache/apr/threadproc/unix/proc.c:

Here’s what happens:

Operation Executed? Remarks
setgid(attr->gid) Yes Only the explicitly specified group changes *
setuid(attr->uid) Yes Switches user
initgroups(user, gid) No !!! The root of the issue !!!

* When the third argument of RewriteMap is username:groupname, only the groupname is set.

3-2. The role of initgroups()

In Unix/Linux systems:

System call Effect
setuid() Switches user
setgid() Switches to the specified (or primary) group
initgroups(user, gid) Registers all secondary groups the user belongs to in the kernel

In other words, setgid() / setuid() alone do not reflect secondary groups.
That’s exactly what happens here.

4. Verifying the behavior

4-1. Goal

Let’s verify the user and group under which some_map.php runs by dumping /proc/self/status to a regular file from within some_map.php.

(We’ll temporarily make some_map.php accessible to everyone for this test.)

4-2. Steps

  1. Temporarily allow anyone to access some_map.php:
    sudo chmod 777 /usr/local/bin/some_map.php
    
     
  2. Create a writable /var/lib/status.txt file:
    sudo touch /var/lib/status.txt
    sudo chmod 777 /var/lib/status.txt
    
     
  3. Modify /usr/local/bin/some_map.php to write its own /proc/self/status:
    /usr/local/bin/some_map.php
    <?php
    file_put_contents('/var/lib/status.txt', file_get_contents('/proc/self/status'));
    
     
  4. Restart Apache.
     
  5. Check /var/lib/status.txt; you’ll see something like this (excerpt):
    /var/lib/status.txt (excerpt)
    Uid:    48      48      48      48
    Gid:    48      48      48      48
    FDSize: 64
    Groups:
    

4-3. Interpretation

Since Groups: is empty, it’s clear that no secondary groups are loaded.

Here, Uid: and Gid: of 48 correspond to the user and group IDs of apache.
The four numbers represent:

  • Real UID/GID
  • Effective UID/GID
  • Saved set-UID/GID
  • Filesystem UID/GID

5. Workaround

Use sudo -u username -g groupname.

That is, replace:

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

with:

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

If the third argument of RewriteMap is omitted, the external program runs with Apache’s startup privileges (usually root).
By invoking sudo -u username -g groupname, the privilege switch happens inside sudo, not Apache, so secondary groups are correctly initialized.

After applying this change and checking /var/lib/status.txt again, you’ll see (excerpt):

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

1001 is the group ID of the secondary group myapp.

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?