mirror of
https://github.com/haproxy/haproxy.git
synced 2026-05-28 04:12:17 -04:00
MEDIUM: startup: add automatic chroot feature
It is now possible to use "chroot auto" in the configuration. This lets haproxy create an anonymous (cleaned up after the process terminates) and read-only directory for chroot. This directory is created in /tmp; we might want to support creating it in a different directory in the future, either by respecting $TMPDIR or by allowing an optional directory after the "auto" keyword.
This commit is contained in:
parent
2d2980408f
commit
641fe4f119
2 changed files with 55 additions and 12 deletions
|
|
@ -2126,13 +2126,21 @@ ca-base <dir>
|
|||
directives. Absolute locations specified in "ca-file", "ca-verify-file" and
|
||||
"crl-file" prevail and ignore "ca-base".
|
||||
|
||||
chroot <jail dir>
|
||||
chroot { <jail dir> | auto }
|
||||
Changes current directory to <jail dir> and performs a chroot() there before
|
||||
dropping privileges. This increases the security level in case an unknown
|
||||
vulnerability would be exploited, since it would make it very hard for the
|
||||
attacker to exploit the system. This only works when the process is started
|
||||
with superuser privileges. It is important to ensure that <jail_dir> is both
|
||||
empty and non-writable to anyone.
|
||||
attacker to exploit the system. It is important to ensure that <jail dir>
|
||||
is both empty and non-writable to anyone. When the process is started with
|
||||
superuser privileges, the chroot() is performed directly. On Linux, when
|
||||
started unprivileged, haproxy attempts to perform it from inside a new
|
||||
user namespace created with unshare(CLONE_NEWUSER); if that mechanism is
|
||||
unavailable the chroot() will fail with the usual error.
|
||||
|
||||
As a special case, <jail dir> may be set to "auto", in which case haproxy
|
||||
creates an anonymous temporary directory, unlinks it, and chroots into it.
|
||||
The resulting jail has no name in the filesystem and is empty and read-only,
|
||||
removing the need to prepare a dedicated jail directory.
|
||||
|
||||
close-spread-time <time>
|
||||
Define a time window during which idle connections and active connections
|
||||
|
|
|
|||
|
|
@ -3327,6 +3327,44 @@ static void setup_user_ns(uid_t euid, gid_t egid)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int do_chroot(const char *prog, const char *path)
|
||||
{
|
||||
const char *chroot_dir = path;
|
||||
int error = 0;
|
||||
|
||||
if (strcmp(path, "auto") == 0) {
|
||||
/* When "chroot auto" is used, we attempt to chroot to an
|
||||
* anonymous and read-only directory.
|
||||
*/
|
||||
char tmpdir[] = "/tmp/haproxy.XXXXXX";
|
||||
chroot_dir = mkdtemp(tmpdir);
|
||||
if (chroot_dir == NULL) {
|
||||
ha_alert("[%s.main()] Cannot create(%s) for chroot auto.\n",
|
||||
prog, tmpdir);
|
||||
return -1;
|
||||
}
|
||||
error = chdir(tmpdir);
|
||||
/* We can call rmdir() here; we hold a reference to the
|
||||
* directory since it is our CWD (and if chdir() failed we still
|
||||
* want to remove the directory).
|
||||
*/
|
||||
DISGUISE(rmdir(tmpdir));
|
||||
if (!error)
|
||||
error = chroot(".");
|
||||
} else {
|
||||
error = chroot(path);
|
||||
}
|
||||
if (!error)
|
||||
error = chdir("/");
|
||||
|
||||
if (error) {
|
||||
ha_alert("[%s.main()] Cannot chroot(%s).\n", prog, chroot_dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct rlimit limit;
|
||||
|
|
@ -3659,14 +3697,11 @@ int main(int argc, char **argv)
|
|||
|
||||
/* Must chroot and setgid/setuid in the children */
|
||||
/* chroot if needed */
|
||||
if (global.chroot != NULL) {
|
||||
if (chroot(global.chroot) == -1 || chdir("/") == -1) {
|
||||
ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
|
||||
if (nb_oldpids)
|
||||
tell_old_pids(SIGTTIN);
|
||||
protocol_unbind_all();
|
||||
exit(1);
|
||||
}
|
||||
if (global.chroot != NULL && do_chroot(argv[0], global.chroot) != 0) {
|
||||
if (nb_oldpids)
|
||||
tell_old_pids(SIGTTIN);
|
||||
protocol_unbind_all();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ha_free(&global.chroot);
|
||||
|
|
|
|||
Loading…
Reference in a new issue