}
}
- if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
- ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
- "", argv[0]);
- protocol_unbind_all();
- exit(1);
- }
-
- /* If the user is not root, we'll still let them try the configuration
- * but we inform them that unexpected behaviour may occur.
- */
- if ((global.last_checks & LSTCHK_NETADM) && getuid())
- ha_warning("[%s.main()] Some options which require full privileges"
- " might not work well.\n"
- "", argv[0]);
-
if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
/* chroot if needed */
if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
set_identity(argv[0]);
+ /* set_identity() above might have dropped LSTCHK_NETADM if
+ * it changed to a new UID while preserving enough permissions
+ * to honnor LSTCHK_NETADM.
+ */
+ if ((global.last_checks & LSTCHK_NETADM) && getuid()) {
+ /* If global.uid is present in config, it is already set as euid
+ * and ruid by set_identity() call just above, so it's better to
+ * remind the user to fix uncoherent settings.
+ */
+ if (global.uid) {
+ ha_alert("[%s.main()] Some configuration options require full "
+ "privileges, so global.uid cannot be changed.\n", argv[0]);
+#if defined(USE_LINUX_CAP)
+ ha_alert("[%s.main()] Alternately, if your system supports "
+ "Linux capabilities, you may also consider using "
+ "'setcap cap_net_raw' or 'setcap cap_net_admin' in the "
+ "'global' section.\n", argv[0]);
+#endif
+ protocol_unbind_all();
+ exit(1);
+ }
+ /* If the user is not root, we'll still let them try the configuration
+ * but we inform them that unexpected behaviour may occur.
+ */
+ ha_warning("[%s.main()] Some options which require full privileges"
+ " might not work well.\n", argv[0]);
+ }
+
/* check ulimits */
limit.rlim_cur = limit.rlim_max = 0;
getrlimit(RLIMIT_NOFILE, &limit);
#include <haproxy/api.h>
#include <haproxy/cfgparse.h>
#include <haproxy/errors.h>
+#include <haproxy/global.h>
#include <haproxy/tools.h>
/* supported names, zero-terminated */
* - switch euid to non-zero
* - set the effective and permitted caps again
* - then the caller can safely call setuid()
+ * On success LSTCHK_NETADM is unset from global.last_checks, if CAP_NET_ADMIN
+ * or CAP_NET_RAW was found in the caplist from config.
* We don't do this if the current euid is not zero or if the target uid
- * is zero. Returns >=0 on success, negative on failure. Alerts or warnings
- * may be emitted.
+ * is zero. Returns 0 on success, negative on failure. Alerts may be emitted.
*/
int prepare_caps_for_setuid(int from_uid, int to_uid)
{
ha_alert("Failed to set the final capabilities using capset(): %s\n", strerror(errno));
return -1;
}
+
+ if (caplist & ((1 << CAP_NET_ADMIN)|(1 << CAP_NET_RAW)))
+ global.last_checks &= ~LSTCHK_NETADM;
+
/* all's good */
return 0;
}