sudo が Error dropping capabilities, aborting というエラーになるのは capability カーネルモジュールがないから。

非常に困って時間をかなり使ったのでメモとして残しておきます。結論はタイトルどおりなんですが、とある構築中の環境(CentOS 5.3)で sudo -u apache id が失敗することに気づきました。

# sudo -u apache id
sudo: Error dropping capabilities, aborting
: Operation not permitted

うーん。さっぱり意味が解りません。検索すると見つかるページは 0003512: Sudo Bug On CentOS 5.3 - CentOS Bug Tracker というのがあるが、解決していません。
次に strace をしてみることに。

# strace -f -o sudo-trace.log sudo -u apache id

これで sudo-trace.log を確認すると capset(2) が EPERM になっているのが見えます。

....
20635 munmap(0xb778f000, 15976)         = 0
20635 setgid32(48)                      = 0
20635 setgroups32(1, [48])              = 0
20635 setresuid32(48, 48, 48)           = 0
20635 prctl(0x8, 0, 0, 0, 0)            = 0
20635 capset(0x19980330, 0, {CAP_AUDIT_WRITE, CAP_AUDIT_WRITE, 0}) = -1 EPERM (Operation not permitted)
20635 write(2, "sudo: ", 6)             = 6
20635 write(2, "Error dropping capabilities, abo"..., 38) = 38
20635 write(2, ": ", 2)                 = 2
20635 open("/usr/share/locale/locale.alias", O_RDONLY) = 4
20635 fstat64(4, {st_mode=S_IFREG|0644, st_size=2528, ...}) = 0
20635 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7efa000
20635 read(4, "# Locale name alias data base.\n#"..., 4096) = 2528
20635 read(4, "", 4096)                 = 0
20635 close(4)                          = 0
20635 munmap(0xb7efa000, 4096)          = 0
20635 open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 open("/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 open("/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 open("/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 open("/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 write(2, "Operation not permitted\n", 24) = 24
20635 exit_group(1)                     = ?

ここまで調べてまだ解らずに1週間ぐらい放置していたんですが、lsmod すると capability というのがないことに気づきました。

# lsmod
Module                  Size  Used by
loop                   13032  0
binfmt_misc             9256  1
dm_mirror              19764  0
dm_multipath           17192  0
dm_mod                 50708  2 dm_mirror,dm_multipath

sudo -u apache id が成功する別の環境では lsmod が以下のようになり capability があります。

# lsmod
Module                  Size  Used by
loop                   13032  0
capability              4552  0
commoncap               6912  1 capability
binfmt_misc             9256  1
dm_mirror              19764  0
dm_multipath           17192  0
dm_mod                 50708  2 dm_mirror,dm_multipath

ここで modprobe で capability をロードさせてからやってみると無事に sudo が成功するようになりました。

# modprobe capability
# sudo -u apache id
uid=48(apache) gid=48(apache) groups=48(apache)

/etc/sysconfig/udev-stw ファイルに capability を追加して、起動時に modprobe capability されるようにしておきました。

MODULES="capability nvram floppy parport lp snd-powermac"