Commit 5d897655 by Serge Hallyn Committed by Stéphane Graber

cgmanager: implement attach

The cgroupfs-specific code is moved from attach.c to cgroup.c. lxc-cgmanager now only chgrps the container's cgroup, so that the unprivileged user still owns the tasks file allowing him to enter the container cgroup (for attach). Some other changes rolled into the cgmanager update: Make the list of subsystems not per-handler, as it will not change. As a result, the only state we need to keep in the per-handler cgroup data is the char *cgroup_path, so we can drop the cgm_data struct altogether. Catch nih errors (as not doing so causes later crashes). Signed-off-by: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com> Acked-by: 's avatarStéphane Graber <stgraber@ubuntu.com>
parent d4641754
...@@ -698,32 +698,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun ...@@ -698,32 +698,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
/* attach to cgroup, if requested */ /* attach to cgroup, if requested */
if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) { if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) {
struct cgroup_meta_data *meta_data; if (!lxc_cgroup_attach(name, lxcpath, pid))
struct cgroup_process_info *container_info;
meta_data = lxc_cgroup_load_meta();
if (!meta_data) {
ERROR("could not move attached process %ld to cgroup of container", (long)pid);
goto cleanup_error; goto cleanup_error;
}
container_info = lxc_cgroup_get_container_info(name, lxcpath, meta_data);
lxc_cgroup_put_meta(meta_data);
if (!container_info) {
ERROR("could not move attached process %ld to cgroup of container", (long)pid);
goto cleanup_error;
}
/*
* TODO - switch over to using a cgroup_operation. We can't use
* cgroup_enter() as that takes a handler.
*/
ret = lxc_cgroupfs_enter(container_info, pid, false);
lxc_cgroup_process_info_free(container_info);
if (ret < 0) {
ERROR("could not move attached process %ld to cgroup of container", (long)pid);
goto cleanup_error;
}
} }
/* Let the child process know to go ahead */ /* Let the child process know to go ahead */
......
...@@ -2303,6 +2303,34 @@ bool cgroupfs_setup_limits(struct lxc_handler *h, bool with_devices) ...@@ -2303,6 +2303,34 @@ bool cgroupfs_setup_limits(struct lxc_handler *h, bool with_devices)
return do_setup_cgroup_limits(h, &h->conf->cgroup, with_devices) == 0; return do_setup_cgroup_limits(h, &h->conf->cgroup, with_devices) == 0;
} }
bool lxc_cgroupfs_attach(const char *name, const char *lxcpath, pid_t pid)
{
struct cgroup_meta_data *meta_data;
struct cgroup_process_info *container_info;
int ret;
meta_data = lxc_cgroup_load_meta();
if (!meta_data) {
ERROR("could not move attached process %d to cgroup of container", pid);
return false;
}
container_info = lxc_cgroup_get_container_info(name, lxcpath, meta_data);
lxc_cgroup_put_meta(meta_data);
if (!container_info) {
ERROR("could not move attached process %d to cgroup of container", pid);
return false;
}
ret = lxc_cgroupfs_enter(container_info, pid, false);
lxc_cgroup_process_info_free(container_info);
if (ret < 0) {
ERROR("could not move attached process %d to cgroup of container", pid);
return false;
}
return true;
}
static struct cgroup_ops cgfs_ops = { static struct cgroup_ops cgfs_ops = {
.destroy = cgfs_destroy, .destroy = cgfs_destroy,
.init = cgfs_init, .init = cgfs_init,
...@@ -2315,6 +2343,7 @@ static struct cgroup_ops cgfs_ops = { ...@@ -2315,6 +2343,7 @@ static struct cgroup_ops cgfs_ops = {
.unfreeze_fromhandler = cgfs_unfreeze_fromhandler, .unfreeze_fromhandler = cgfs_unfreeze_fromhandler,
.setup_limits = cgroupfs_setup_limits, .setup_limits = cgroupfs_setup_limits,
.name = "cgroupfs", .name = "cgroupfs",
.attach = lxc_cgroupfs_attach,
.chown = NULL, .chown = NULL,
}; };
static void init_cg_ops(void) static void init_cg_ops(void)
...@@ -2421,3 +2450,9 @@ bool cgroup_chown(struct lxc_handler *handler) ...@@ -2421,3 +2450,9 @@ bool cgroup_chown(struct lxc_handler *handler)
return active_cg_ops->chown(handler); return active_cg_ops->chown(handler);
return true; return true;
} }
bool lxc_cgroup_attach(const char *name, const char *lxcpath, pid_t pid)
{
init_cg_ops();
return active_cg_ops->attach(name, lxcpath, pid);
}
...@@ -182,6 +182,7 @@ struct cgroup_ops { ...@@ -182,6 +182,7 @@ struct cgroup_ops {
int (*unfreeze_fromhandler)(struct lxc_handler *handler); int (*unfreeze_fromhandler)(struct lxc_handler *handler);
bool (*setup_limits)(struct lxc_handler *handler, bool with_devices); bool (*setup_limits)(struct lxc_handler *handler, bool with_devices);
bool (*chown)(struct lxc_handler *handler); bool (*chown)(struct lxc_handler *handler);
bool (*attach)(const char *name, const char *lxcpath, pid_t pid);
const char *name; const char *name;
}; };
...@@ -216,6 +217,7 @@ extern bool cgroup_enter(struct lxc_handler *handler); ...@@ -216,6 +217,7 @@ extern bool cgroup_enter(struct lxc_handler *handler);
extern void cgroup_cleanup(struct lxc_handler *handler); extern void cgroup_cleanup(struct lxc_handler *handler);
extern bool cgroup_create_legacy(struct lxc_handler *handler); extern bool cgroup_create_legacy(struct lxc_handler *handler);
extern char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem); extern char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem);
extern bool lxc_cgroup_attach(const char *name, const char *lxcpath, pid_t pid);
extern int lxc_cgroup_set(const char *filename, const char *value, const char *name, const char *lxcpath); extern int lxc_cgroup_set(const char *filename, const char *value, const char *name, const char *lxcpath);
extern int lxc_cgroup_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath); extern int lxc_cgroup_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath);
extern int lxc_unfreeze_fromhandler(struct lxc_handler *handler); extern int lxc_unfreeze_fromhandler(struct lxc_handler *handler);
......
...@@ -1111,3 +1111,28 @@ int randseed(bool srand_it) ...@@ -1111,3 +1111,28 @@ int randseed(bool srand_it)
return seed; return seed;
} }
uid_t get_ns_uid(uid_t orig)
{
char *line = NULL;
size_t sz = 0;
uid_t nsid, hostid, range;
FILE *f = fopen("/proc/self/uid_map", "r");
if (!f)
return 0;
while (getline(&line, &sz, f) != -1) {
if (sscanf(line, "%u %u %u", &nsid, &hostid, &range) != 3)
continue;
if (hostid <= orig && hostid + range > orig) {
nsid += orig - hostid;
goto found;
}
}
nsid = 0;
found:
fclose(f);
free(line);
return nsid;
}
...@@ -265,4 +265,9 @@ extern int randseed(bool); ...@@ -265,4 +265,9 @@ extern int randseed(bool);
inline static bool am_unpriv(void) { inline static bool am_unpriv(void) {
return geteuid() != 0; return geteuid() != 0;
} }
/*
* parse /proc/self/uid_map to find what @orig maps to
*/
extern uid_t get_ns_uid(uid_t orig);
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment