goto out_warn_father;
/* If we are in a new user namespace, become root there to have
- * privilege over our namespace. When using lxc-execute we default to
- * root, but this can be overriden using the lxc.init_uid and
- * lxc.init_gid configuration options.
+ * privilege over our namespace.
*/
if (!lxc_list_empty(&handler->conf->id_map)) {
- gid_t new_gid = 0;
- if (handler->conf->is_execute && handler->conf->init_gid)
- new_gid = handler->conf->init_gid;
-
- uid_t new_uid = 0;
- if (handler->conf->is_execute && handler->conf->init_uid)
- new_uid = handler->conf->init_uid;
-
- NOTICE("Switching to uid=%d and gid=%d in new user namespace.", new_uid, new_gid);
- if (setgid(new_gid)) {
- SYSERROR("Failed to setgid().");
+ if (lxc_switch_uid_gid(0, 0) < 0)
goto out_warn_father;
- }
- if (setuid(new_uid)) {
- SYSERROR("Failed to setuid().");
- goto out_warn_father;
- }
- if (setgroups(0, NULL)) {
- SYSERROR("Failed to setgroups().");
+
+ /* Drop groups only after we switched to a valid gid in the new
+ * user namespace.
+ */
+ if (lxc_setgroups(0, NULL) < 0)
goto out_warn_father;
- }
}
if (access(handler->lxcpath, X_OK)) {
goto out_warn_father;
}
+ /* The container has been setup. We can now switch to an unprivileged
+ * uid/gid.
+ */
+ if (handler->conf->is_execute) {
+ uid_t new_uid = 0;
+ gid_t new_gid = 0;
+
+ if (handler->conf->init_uid > 0)
+ new_uid = handler->conf->init_uid;
+
+ if (handler->conf->init_gid > 0)
+ new_gid = handler->conf->init_gid;
+
+ /* If we are in a new user namespace we already dropped all
+ * groups when we switched to root in the new user namespace
+ * further above. Only drop groups if we can, so ensure that we
+ * have necessary privilege.
+ */
+ bool can_setgroups = ((getuid() == 0) && (getgid() == 0));
+ if (lxc_list_empty(&handler->conf->id_map) && can_setgroups) {
+ if (lxc_setgroups(0, NULL) < 0)
+ goto out_warn_father;
+ }
+
+ if (lxc_switch_uid_gid(new_uid, new_gid) < 0)
+ goto out_warn_father;
+ }
+
/* The clearenv() and putenv() calls have been moved here to allow us to
* use environment variables passed to the various hooks, such as the
* start hook above. Not all of the variables like CONFIG_PATH or ROOTFS