return path;
}
+static bool cgfs_escape(void)
+{
+ struct cgroup_meta_data *md;
+ int i;
+ bool ret = false;
+
+ md = lxc_cgroup_load_meta();
+ if (!md)
+ return false;
+
+ for (i = 1; i <= md->maximum_hierarchy; i++) {
+ struct cgroup_hierarchy *h = md->hierarchies[i];
+ struct cgroup_mount_point *mp;
+ char *tasks;
+ FILE *f;
+ int written;
+
+ if (!h) {
+ WARN("not escaping hierarchy %d", i);
+ continue;
+ }
+
+ mp = lxc_cgroup_find_mount_point(h, "/", true);
+ if (!mp)
+ goto out;
+
+ tasks = cgroup_to_absolute_path(mp, "/", "tasks");
+ if (!tasks)
+ goto out;
+
+ f = fopen(tasks, "a");
+ free(tasks);
+ if (!f)
+ goto out;
+
+ written = fprintf(f, "%d\n", getpid());
+ fclose(f);
+ if (written < 0) {
+ SYSERROR("writing tasks failed\n");
+ goto out;
+ }
+ }
+
+ ret = true;
+out:
+ lxc_cgroup_put_meta(md);
+ return ret;
+}
+
static bool cgfs_unfreeze(void *hdata)
{
struct cgfs_data *d = hdata;
.create_legacy = cgfs_create_legacy,
.get_cgroup = cgfs_get_cgroup,
.canonical_path = cgfs_canonical_path,
+ .escape = cgfs_escape,
.get = lxc_cgroupfs_get,
.set = lxc_cgroupfs_set,
.unfreeze = cgfs_unfreeze,
* be in "/lxc/c1" rather than "/user/..../c1"
* called internally with connection already open
*/
-static bool lxc_cgmanager_escape(void)
+static bool cgm_escape(void)
{
- bool ret = true;
+ bool ret = true, cgm_needs_disconnect = false;
pid_t me = getpid();
char **slist = subsystems;
int i;
+ if (!cgroup_manager) {
+ if (!cgm_dbus_connect()) {
+ ERROR("Error connecting to cgroup manager");
+ return false;
+ }
+ cgm_needs_disconnect = true;
+ }
+
+
if (cgm_all_controllers_same)
slist = subsystems_inone;
}
}
+ if (cgm_needs_disconnect)
+ cgm_dbus_disconnect();
+
return ret;
}
goto err1;
// root; try to escape to root cgroup
- if (geteuid() == 0 && !lxc_cgmanager_escape())
+ if (geteuid() == 0 && !cgm_escape())
goto err2;
cgm_dbus_disconnect();
.create_legacy = NULL,
.get_cgroup = cgm_get_cgroup,
.canonical_path = cgm_canonical_path,
+ .escape = cgm_escape,
.get = cgm_get,
.set = cgm_set,
.unfreeze = cgm_unfreeze,
return NULL;
}
+bool cgroup_escape(void)
+{
+ if (ops)
+ return ops->escape();
+ return false;
+}
+
const char *cgroup_canonical_path(struct lxc_handler *handler)
{
if (geteuid()) {
bool (*create_legacy)(void *hdata, pid_t pid);
const char *(*get_cgroup)(void *hdata, const char *subsystem);
const char *(*canonical_path)(void *hdata);
+ bool (*escape)(void);
int (*set)(const char *filename, const char *value, const char *name, const char *lxcpath);
int (*get)(const char *filename, char *value, size_t len, const char *name, const char *lxcpath);
bool (*unfreeze)(void *hdata);
extern bool cgroup_create_legacy(struct lxc_handler *handler);
extern int cgroup_nrtasks(struct lxc_handler *handler);
extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem);
+extern bool cgroup_escape(void);
/*
* Currently, this call only makes sense for privileged containers.