static int chown_cgroup_wrapper(void *data) { struct chown_data *arg = data; char **slist = subsystems; int i, ret = -1; uid_t destuid; if (setresgid(0,0,0) < 0) SYSERROR("Failed to setgid to 0"); if (setresuid(0,0,0) < 0) SYSERROR("Failed to setuid to 0"); if (setgroups(0, NULL) < 0) SYSERROR("Failed to clear groups"); cgm_dbus_disconnect(); if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return -1; } destuid = get_ns_uid(arg->origuid); if (cgm_supports_multiple_controllers) slist = subsystems_inone; for (i = 0; slist[i]; i++) { if (do_chown_cgroup(slist[i], arg->cgroup_path, destuid) < 0) { ERROR("Failed to chown %s:%s to container root", slist[i], arg->cgroup_path); goto fail; } } ret = 0; fail: cgm_dbus_disconnect(); return ret; }
static int do_chown_cgroup(const char *controller, const char *cgroup_path, uid_t origuid) { int sv[2] = {-1, -1}, optval = 1, ret = -1; char buf[1]; uid_t caller_nsuid = get_ns_uid(origuid); if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0) { SYSERROR("Error creating socketpair"); goto out; } if (setsockopt(sv[1], SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) { SYSERROR("setsockopt failed"); goto out; } if (setsockopt(sv[0], SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) { SYSERROR("setsockopt failed"); goto out; } if ( cgmanager_chown_scm_sync(NULL, cgroup_manager, controller, cgroup_path, sv[1]) != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("call to cgmanager_chown_scm_sync failed: %s", nerr->message); nih_free(nerr); goto out; } /* now send credentials */ fd_set rfds; FD_ZERO(&rfds); FD_SET(sv[0], &rfds); if (select(sv[0]+1, &rfds, NULL, NULL, NULL) < 0) { ERROR("Error getting go-ahead from server: %s", strerror(errno)); goto out; } if (read(sv[0], &buf, 1) != 1) { ERROR("Error getting reply from server over socketpair"); goto out; } if (send_creds(sv[0], getpid(), getuid(), getgid())) { SYSERROR("%s: Error sending pid over SCM_CREDENTIAL", __func__); goto out; } FD_ZERO(&rfds); FD_SET(sv[0], &rfds); if (select(sv[0]+1, &rfds, NULL, NULL, NULL) < 0) { ERROR("Error getting go-ahead from server: %s", strerror(errno)); goto out; } if (read(sv[0], &buf, 1) != 1) { ERROR("Error getting reply from server over socketpair"); goto out; } if (send_creds(sv[0], getpid(), caller_nsuid, 0)) { SYSERROR("%s: Error sending pid over SCM_CREDENTIAL", __func__); goto out; } FD_ZERO(&rfds); FD_SET(sv[0], &rfds); if (select(sv[0]+1, &rfds, NULL, NULL, NULL) < 0) { ERROR("Error getting go-ahead from server: %s", strerror(errno)); goto out; } ret = read(sv[0], buf, 1); out: close(sv[0]); close(sv[1]); if (ret == 1 && *buf == '1') return 0; return -1; }