Package: apache2-bin
Version: 2.4.62-3
Severity: normal
Tags: upstream

Hi,

I'm trying to start apache as a non-root user, with a minimal set of 
capabilities that allow it to work.

My command line looks like this:

capsh \
        --keep=1 \
        --gid=33 \
        --groups=33 \
        --caps="cap_net_bind_service+eip cap_sys_chroot+eip cap_setuid+ep" \
        --uid=33 \
        --addamb=cap_net_bind_service,cap_sys_chroot \
        --print \
        -- \
        -c '/usr/sbin/apache2 -d "/etc/apache2" -DSSL -DNO_DETACH -DFOREGROUND 
-f "/etc/apache2/apache2.conf"'

Diagnostic output from capsh(1) confirms capabilities are set correctly:

Current: cap_net_bind_service,cap_sys_chroot=ip cap_setuid+p
Bounding set 
=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read,cap_perfmon,cap_bpf,cap_checkpoint_restore
Ambient set =cap_net_bind_service,cap_sys_chroot
Current IAB: ^cap_net_bind_service,^cap_sys_chroot
Securebits: 020/0x10/5'b10000 (no-new-privs=0)
 secure-noroot: no (unlocked)
 secure-no-suid-fixup: no (unlocked)
 secure-keep-caps: yes (unlocked)
 secure-no-ambient-raise: no (unlocked)
uid=33(www-data) euid=33(www-data)
gid=33(www-data)
groups=33(www-data)
Guessed mode: UNCERTAIN (0)

However, apache says:

[unixd:alert] [pid 24573:tid 24573] AH02158: Cannot chroot when not started as 
root

The same capsh command works with merecat httpd and allows it to chroot.

The problem seems to be that in modules/arch/unix/mod_unixd.c, in

static int
unixd_drop_privileges(apr_pool_t *pool, server_rec *s),

the code explicitly checks for geteuid() == 0 and doesn't even attempt the
chroot if it's not running as root:

        if (geteuid()) {
            rv = errno;
            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02158)
                         "Cannot chroot when not started as root");
            return rv;
        }

This is just wrong. Apache has no business trying to guess what the kernel
will allow it to do; there could be an arbitrary security/privilege
mechanism (not just capabilities) in place that will allow this particular
process to chroot to that particular directory at this particular time of
day. Apache can't know this unless it tries to chroot.

I think this check should be dropped; at most, if the chroot doesn't
succeed, AND we're not running as root, Apache could include this
information as a hint in the error message.

"Cannot chroot when not started as root" is factually incorrect.

Also, happy new year!

AndrĂ¡s

-- System Information:
Debian Release: trixie/sid
  APT prefers stable-security
  APT policy: (500, 'stable-security'), (350, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 6.12.5-amd64 (SMP w/8 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE, 
TAINT_UNSIGNED_MODULE
Locale: LANG=en_US.UTF-8, LC_CTYPE=hu_HU.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_US.UTF-8
Shell: /bin/sh linked to /usr/bin/dash
Init: runit (via /run/runit.stopit)
LSM: AppArmor: enabled

-- 
  There are more airplanes in the ocean than there are submarines in the air.

Reply via email to