ModSecurity with Nginx の Audit Log にエラー (Failed to lock global mutex: Permission denied)

CentOS 6.5 + ModSecurity 2.8.0 + Nginx 1.6.0 でテスト
ModSecurity と Nginx をコンパイルして動かしたら audit log に妙なメッセージが。

```
Message: Audit log: Failed to lock global mutex: Permission denied
```

strace すると semop(2) で失敗していることが分かる。

```
3770  17:40:24.018266 semop(655372, {{0, -1, SEM_UNDO}}, 1) = -1 EACCES (Permission denied)
```

ipcs コマンドで確認すると owner がおかしい。

```
------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0x00000000 0          root       600        1
0x00000000 32769      root       600        1
0x00000000 131074     4294967295 600        1
0x00000000 163843     4294967295 600        1
0x00000000 458756     4294967295 600        1
0x00000000 491525     4294967295 600        1
0x00000000 262150     4294967295 600        1
0x00000000 294919     4294967295 600        1
0x00000000 393224     4294967295 600        1
0x00000000 425993     4294967295 600        1
0x00000000 524298     4294967295 600        1
0x00000000 557067     4294967295 600        1
0x00000000 655372     4294967295 600        1
0x00000000 688141     4294967295 600        1
```

Nginx を root で動かせば解決するだろうが、それは避けたい

ソースを grep して探していくと、DEFAULT_USER なるものが見つかる

```
[host]$ grep -r semctl *
standalone/server.c:            if (semctl(ospmutex.crossproc, 0, IPC_SET, ick) < 0) {
standalone/server.c:            if (semctl(ospmutex.crossproc, 0, IPC_SET, ick) < 0) {
```


```c:standalone/server.c
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
    unixd_config.user_name = DEFAULT_USER;
    unixd_config.user_id = ap_uname2id(DEFAULT_USER);
    unixd_config.group_id = ap_gname2id(DEFAULT_GROUP);
    unixd_config.suexec_enabled = 0;
#else
    ap_unixd_config.user_name = DEFAULT_USER;
    ap_unixd_config.user_id = ap_uname2id(DEFAULT_USER);
    ap_unixd_config.group_id = ap_gname2id(DEFAULT_GROUP);
    ap_unixd_config.suexec_enabled = 0;
#endif
```

```c:standalone/server.c
            apr_os_proc_mutex_get(&ospmutex, pmutex);
            buf.sem_perm.uid = unixd_config.user_id;
            buf.sem_perm.gid = unixd_config.group_id;
            buf.sem_perm.mode = 0600;
            ick.buf = &buf;
            if (semctl(ospmutex.crossproc, 0, IPC_SET, ick) < 0) {
                return errno;
            }
```

DEFAULT_USER を探す

```
[host]$ grep -r DEFAULT_USER /usr/include/httpd/*
/usr/include/httpd/unixd.h:#ifndef DEFAULT_USER
/usr/include/httpd/unixd.h:#define DEFAULT_USER "#-1"
```

```c:/usr/include/httpd/unixd.h
#ifndef DEFAULT_USER
#define DEFAULT_USER "#-1"
#endif
#ifndef DEFAULT_GROUP
#define DEFAULT_GROUP "#-1"
#endif
```

DEFAULT_USER などを定義してやればいいので、ModSecurity からコンパイルし直す。以下は一例で、オプションは各環境で適切に設定する。

```
[host]# CFLAGS="-DDEFAULT_USER=\\\"nginx\\\" -DDEFAULT_GROUP=\\\"nginx\\\"" \
CPPFLAGS="-I/usr/include/apr-1 -I/usr/include/httpd" \
./configure \
--disable-apache2-module \
--disable-mlogc \
--enable-standalone-module
[host]# make
[host]# make install
```

Nginx もコンパイルし直す。以下は一例で、オプションは各環境ごとに適切に設定する

```
[host]# ./configure \
--add-module=../modsecurity-2.8.0/nginx/modsecurity \
--user=nginx --group=nginx \
--without-mail_pop3_module \
--without-mail_imap_module \
--without-mail_smtp_module \
--with-cc-opt="-I/usr/include/apr-1 -I/usr/include/httpd" \
--with-ld-opt="-lapr-1 -laprutil-1"
[host]# make
[host]# make install
```

修正完了。

```
[host]# service nginx start
[host]# ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0x00000000 0          root       600        1
0x00000000 32769      root       600        1
0x00000000 131074     nginx      600        1
0x00000000 163843     nginx      600        1
```

修正前はやたらと数が多かったし、
多分直すまではセマフォの削除にも失敗していたと思われる。