[Bug 277210] jail(8): exec.clean retrieves PWD from user info (can cause services to crash on jail start-up)

From: <bugzilla-noreply_at_freebsd.org>
Date: Wed, 21 Feb 2024 11:55:25 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277210

            Bug ID: 277210
           Summary: jail(8): exec.clean retrieves PWD from user info (can
                    cause services to crash on jail start-up)
           Product: Base System
           Version: Unspecified
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Many People
          Priority: ---
         Component: bin
          Assignee: bugs@FreeBSD.org
          Reporter: johannes.kunde@gmail.com

I recently ran into a problem where one of my services, configured via rc(8), 
failed to start, but only if the corresponding jail was (re)started as a whole.
The same service (re)started without problems when running 'service foo start'.
Digging into the problem, I found out that in case 'exec.clean' has been set in 
jail.conf(5), PWD is set to '/root' (only root:wheel can read here) when
(re)starting the jail, 
but is set to '/' when running 'service foo start' from within the running
jail. 
I think this behavior is caused by the following lines:
https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/jail/command.c#L727-L797.

It is also not documented in the manpage that a chdir(2) happens with
'exec.clean'.

So far, I've found two ways to overcome this behavior. One is to omit
'exec.clean' in 
jail.conf(5), the other is to set '${name}_chdir="/"' in the corresponding
rc(8) script.

However, I wanted to file this bug and discuss the problem, as I'm uncertain if
this behavior 
is intended. When running the very same service on a FreeBSD host system (not
in a jail) 
it starts up normally, because PWD will be "/" in any case. It's also quite
hard to trace 
that issue down to the above lines, as there is no obvious error message other
than what 
is printed out by the affected service itself.

The problem can be easily reproduced with the below C program and rc(8) script:

Compile the program with 'cc -o getcwd getcwd.c' and copy it to
'/usr/local/sbin'.



#include <unistd.h>
#include <limits.h>
#include <syslog.h>

int main() {
        char cwd[PATH_MAX];
                if (getcwd(cwd, sizeof(cwd)) != NULL) {
                        syslog(LOG_DEBUG, "Current working dir: %s\n", cwd);
                } else {
                        syslog(LOG_DEBUG, "getcwd() error");
                        return 1;
                }
        return 0;
}



Copy the following script to '/usr/local/etc/rc.d/getcwd' and run 'chmod +x
/usr/local/etc/rc.d/getcwd'.



#!/bin/sh
#
# PROVIDE: getcwd

. /etc/rc.subr

name="getcwd"
rcvar="getcwd_enable"
command="/usr/local/sbin/${name}"

load_rc_config $name
: ${getcwd_enable:=NO}

run_rc_command "$1"



Run 'sysrc getcwd_enable="YES"'

Now do the following:
1. Restart the jail
2. Run 'service getcwd start'
3. Take a look at '/var/log/debug.log'


NOTE: This behavior is not bound to or related to any specific Jail-Manager.

-- 
You are receiving this mail because:
You are the assignee for the bug.