else if (strcmp(args[0], "uid") == 0) {
if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto out;
- if (global.uid != 0) {
+ if (global.uid >= 0) {
ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
err_code |= ERR_ALERT;
goto out;
else if (strcmp(args[0], "gid") == 0) {
if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto out;
- if (global.gid != 0) {
+ if (global.gid >= 0) {
ha_alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
err_code |= ERR_ALERT;
goto out;
struct passwd *ha_user;
if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto out;
- if (global.uid != 0) {
+ if (global.uid >= 0) {
ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
err_code |= ERR_ALERT;
goto out;
struct group *ha_group;
if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto out;
- if (global.gid != 0) {
+ if (global.gid >= 0) {
ha_alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
err_code |= ERR_ALERT;
goto out;
/* global options */
struct global global = {
+ .uid = -1, // not set
+ .gid = -1, // not set
.hard_stop_after = TICK_ETERNITY,
.close_spread_time = TICK_ETERNITY,
.close_spread_end = TICK_ETERNITY,
{
int from_uid __maybe_unused = geteuid();
- if (global.gid) {
+ if (global.gid > 0) {
if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
" without 'uid'/'user' is generally useless.\n", program_name);
}
#endif
- if (global.uid && setuid(global.uid) == -1) {
+ if (global.uid > 0 && setuid(global.uid) == -1) {
ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
protocol_unbind_all();
exit(1);
* and ruid by set_identity() just above, so it's better to
* remind the user to fix uncoherent settings.
*/
- if (global.uid) {
+ if (global.uid > 0) {
ha_alert("[%s.main()] Some configuration options require full "
"privileges, so global.uid cannot be changed.\n", argv[0]);
#if defined(USE_LINUX_CAP)
" might not work well.\n", argv[0]);
}
+ if (global.uid < 0 && geteuid() == 0)
+ ha_warning("[%s.main()] HAProxy was started as the root user and does "
+ "not make use of 'user' nor 'uid' global options to drop the "
+ "privileges. This is generally considered as a bad practice "
+ "security-wise. If running as root is intentional, please make "
+ "it explicit using 'uid 0' or 'user root', and also please "
+ "consider using the 'chroot' directive to isolate the process "
+ "into a totally empty and read-only directory if possible."
+#if defined(USE_LINUX_CAP)
+ " Also, since your operating system supports it, always prefer "
+ "relying on capabilities with unprivileged users than running "
+ "with full privileges (look for 'setcap' in the configuration"
+ "manual)."
+#endif
+ "\n", argv[0]);
+
/*
* This is only done in daemon mode because we might want the
* logs on stdout in mworker mode. If we're NOT in QUIET mode,