mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-15 02:19:39 +00:00
cgmanager: lock around cgmanager-client calls
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
This commit is contained in:
parent
442f5c0fdf
commit
14a666b577
@ -30,6 +30,7 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -53,6 +54,28 @@
|
|||||||
#ifdef HAVE_CGMANAGER
|
#ifdef HAVE_CGMANAGER
|
||||||
lxc_log_define(lxc_cgmanager, lxc);
|
lxc_log_define(lxc_cgmanager, lxc);
|
||||||
|
|
||||||
|
static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
static void lock_mutex(pthread_mutex_t *l)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = pthread_mutex_lock(l)) != 0) {
|
||||||
|
fprintf(stderr, "pthread_mutex_lock returned:%d %s", ret, strerror(ret));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unlock_mutex(pthread_mutex_t *l)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = pthread_mutex_unlock(l)) != 0) {
|
||||||
|
fprintf(stderr, "pthread_mutex_unlock returned:%d %s", ret, strerror(ret));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#include <nih-dbus/dbus_connection.h>
|
#include <nih-dbus/dbus_connection.h>
|
||||||
#include <cgmanager/cgmanager-client.h>
|
#include <cgmanager/cgmanager-client.h>
|
||||||
#include <nih/alloc.h>
|
#include <nih/alloc.h>
|
||||||
@ -78,6 +101,7 @@ static bool cgm_dbus_connect(void)
|
|||||||
DBusConnection *connection;
|
DBusConnection *connection;
|
||||||
dbus_error_init(&dbus_error);
|
dbus_error_init(&dbus_error);
|
||||||
|
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
connection = nih_dbus_connect(CGMANAGER_DBUS_SOCK, cgm_dbus_disconnected);
|
connection = nih_dbus_connect(CGMANAGER_DBUS_SOCK, cgm_dbus_disconnected);
|
||||||
if (!connection) {
|
if (!connection) {
|
||||||
NihError *nerr;
|
NihError *nerr;
|
||||||
@ -86,6 +110,7 @@ static bool cgm_dbus_connect(void)
|
|||||||
nerr->message);
|
nerr->message);
|
||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
dbus_error_free(&dbus_error);
|
dbus_error_free(&dbus_error);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
dbus_connection_set_exit_on_disconnect(connection, FALSE);
|
dbus_connection_set_exit_on_disconnect(connection, FALSE);
|
||||||
@ -99,6 +124,7 @@ static bool cgm_dbus_connect(void)
|
|||||||
nerr = nih_error_get();
|
nerr = nih_error_get();
|
||||||
ERROR("Error opening cgmanager proxy: %s", nerr->message);
|
ERROR("Error opening cgmanager proxy: %s", nerr->message);
|
||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,14 +135,17 @@ static bool cgm_dbus_connect(void)
|
|||||||
ERROR("Error pinging cgroup manager: %s", nerr->message);
|
ERROR("Error pinging cgroup manager: %s", nerr->message);
|
||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
}
|
}
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cgm_dbus_disconnect(void)
|
static void cgm_dbus_disconnect(void)
|
||||||
{
|
{
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
if (cgroup_manager)
|
if (cgroup_manager)
|
||||||
nih_free(cgroup_manager);
|
nih_free(cgroup_manager);
|
||||||
cgroup_manager = NULL;
|
cgroup_manager = NULL;
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cgm_dbus_disconnected(DBusConnection *connection)
|
static void cgm_dbus_disconnected(DBusConnection *connection)
|
||||||
@ -168,6 +197,7 @@ static int send_creds(int sock, int rpid, int ruid, int rgid)
|
|||||||
|
|
||||||
static bool lxc_cgmanager_create(const char *controller, const char *cgroup_path, int32_t *existed)
|
static bool lxc_cgmanager_create(const char *controller, const char *cgroup_path, int32_t *existed)
|
||||||
{
|
{
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
if ( cgmanager_create_sync(NULL, cgroup_manager, controller,
|
if ( cgmanager_create_sync(NULL, cgroup_manager, controller,
|
||||||
cgroup_path, existed) != 0) {
|
cgroup_path, existed) != 0) {
|
||||||
NihError *nerr;
|
NihError *nerr;
|
||||||
@ -175,9 +205,11 @@ static bool lxc_cgmanager_create(const char *controller, const char *cgroup_path
|
|||||||
ERROR("call to cgmanager_create_sync failed: %s", nerr->message);
|
ERROR("call to cgmanager_create_sync failed: %s", nerr->message);
|
||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
ERROR("Failed to create %s:%s", controller, cgroup_path);
|
ERROR("Failed to create %s:%s", controller, cgroup_path);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,6 +217,7 @@ static bool lxc_cgmanager_escape(void)
|
|||||||
{
|
{
|
||||||
pid_t me = getpid();
|
pid_t me = getpid();
|
||||||
int i;
|
int i;
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
for (i = 0; i < nr_subsystems; i++) {
|
for (i = 0; i < nr_subsystems; i++) {
|
||||||
if (cgmanager_move_pid_abs_sync(NULL, cgroup_manager,
|
if (cgmanager_move_pid_abs_sync(NULL, cgroup_manager,
|
||||||
subsystems[i], "/", me) != 0) {
|
subsystems[i], "/", me) != 0) {
|
||||||
@ -193,10 +226,12 @@ static bool lxc_cgmanager_escape(void)
|
|||||||
ERROR("call to cgmanager_move_pid_abs_sync(%s) failed: %s",
|
ERROR("call to cgmanager_move_pid_abs_sync(%s) failed: %s",
|
||||||
subsystems[i], nerr->message);
|
subsystems[i], nerr->message);
|
||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,6 +249,7 @@ static int do_chown_cgroup(const char *controller, const char *cgroup_path,
|
|||||||
|
|
||||||
uid_t caller_nsuid = get_ns_uid(origuid);
|
uid_t caller_nsuid = get_ns_uid(origuid);
|
||||||
|
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0) {
|
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0) {
|
||||||
SYSERROR("Error creating socketpair");
|
SYSERROR("Error creating socketpair");
|
||||||
goto out;
|
goto out;
|
||||||
@ -275,6 +311,7 @@ static int do_chown_cgroup(const char *controller, const char *cgroup_path,
|
|||||||
out:
|
out:
|
||||||
close(sv[0]);
|
close(sv[0]);
|
||||||
close(sv[1]);
|
close(sv[1]);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
if (ret == 1 && *buf == '1')
|
if (ret == 1 && *buf == '1')
|
||||||
return 0;
|
return 0;
|
||||||
return -1;
|
return -1;
|
||||||
@ -296,14 +333,17 @@ static int chown_cgroup_wrapper(void *data)
|
|||||||
static bool lxc_cgmanager_chmod(const char *controller,
|
static bool lxc_cgmanager_chmod(const char *controller,
|
||||||
const char *cgroup_path, const char *file, int mode)
|
const char *cgroup_path, const char *file, int mode)
|
||||||
{
|
{
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
if (cgmanager_chmod_sync(NULL, cgroup_manager, controller,
|
if (cgmanager_chmod_sync(NULL, cgroup_manager, controller,
|
||||||
cgroup_path, file, mode) != 0) {
|
cgroup_path, file, mode) != 0) {
|
||||||
NihError *nerr;
|
NihError *nerr;
|
||||||
nerr = nih_error_get();
|
nerr = nih_error_get();
|
||||||
ERROR("call to cgmanager_chmod_sync failed: %s", nerr->message);
|
ERROR("call to cgmanager_chmod_sync failed: %s", nerr->message);
|
||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,14 +379,17 @@ static bool chown_cgroup(const char *controller, const char *cgroup_path,
|
|||||||
static void cgm_remove_cgroup(const char *controller, const char *path)
|
static void cgm_remove_cgroup(const char *controller, const char *path)
|
||||||
{
|
{
|
||||||
int existed;
|
int existed;
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
if ( cgmanager_remove_sync(NULL, cgroup_manager, controller,
|
if ( cgmanager_remove_sync(NULL, cgroup_manager, controller,
|
||||||
path, CG_REMOVE_RECURSIVE, &existed) != 0) {
|
path, CG_REMOVE_RECURSIVE, &existed) != 0) {
|
||||||
NihError *nerr;
|
NihError *nerr;
|
||||||
nerr = nih_error_get();
|
nerr = nih_error_get();
|
||||||
ERROR("call to cgmanager_remove_sync failed: %s", nerr->message);
|
ERROR("call to cgmanager_remove_sync failed: %s", nerr->message);
|
||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
ERROR("Error removing %s:%s", controller, path);
|
ERROR("Error removing %s:%s", controller, path);
|
||||||
}
|
}
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
if (existed == -1)
|
if (existed == -1)
|
||||||
INFO("cgroup removal attempt: %s:%s did not exist", controller, path);
|
INFO("cgroup removal attempt: %s:%s did not exist", controller, path);
|
||||||
}
|
}
|
||||||
@ -476,14 +519,17 @@ next:
|
|||||||
static bool lxc_cgmanager_enter(pid_t pid, const char *controller,
|
static bool lxc_cgmanager_enter(pid_t pid, const char *controller,
|
||||||
const char *cgroup_path)
|
const char *cgroup_path)
|
||||||
{
|
{
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
if (cgmanager_move_pid_sync(NULL, cgroup_manager, controller,
|
if (cgmanager_move_pid_sync(NULL, cgroup_manager, controller,
|
||||||
cgroup_path, pid) != 0) {
|
cgroup_path, pid) != 0) {
|
||||||
NihError *nerr;
|
NihError *nerr;
|
||||||
nerr = nih_error_get();
|
nerr = nih_error_get();
|
||||||
ERROR("call to cgmanager_move_pid_sync failed: %s", nerr->message);
|
ERROR("call to cgmanager_move_pid_sync failed: %s", nerr->message);
|
||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,14 +571,17 @@ static int cgm_get_nrtasks(void *hdata)
|
|||||||
if (!d || !d->cgroup_path)
|
if (!d || !d->cgroup_path)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
if (cgmanager_get_tasks_sync(NULL, cgroup_manager, subsystems[0],
|
if (cgmanager_get_tasks_sync(NULL, cgroup_manager, subsystems[0],
|
||||||
d->cgroup_path, &pids, &pids_len) != 0) {
|
d->cgroup_path, &pids, &pids_len) != 0) {
|
||||||
NihError *nerr;
|
NihError *nerr;
|
||||||
nerr = nih_error_get();
|
nerr = nih_error_get();
|
||||||
ERROR("call to cgmanager_get_tasks_sync failed: %s", nerr->message);
|
ERROR("call to cgmanager_get_tasks_sync failed: %s", nerr->message);
|
||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
nih_free(pids);
|
nih_free(pids);
|
||||||
return pids_len;
|
return pids_len;
|
||||||
}
|
}
|
||||||
@ -553,6 +602,7 @@ static int cgm_get(const char *filename, char *value, size_t len, const char *na
|
|||||||
cgroup = lxc_cmd_get_cgroup_path(name, lxcpath, controller);
|
cgroup = lxc_cmd_get_cgroup_path(name, lxcpath, controller);
|
||||||
if (!cgroup)
|
if (!cgroup)
|
||||||
return -1;
|
return -1;
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
if (cgmanager_get_value_sync(NULL, cgroup_manager, controller, cgroup, filename, &result) != 0) {
|
if (cgmanager_get_value_sync(NULL, cgroup_manager, controller, cgroup, filename, &result) != 0) {
|
||||||
/*
|
/*
|
||||||
* must consume the nih error
|
* must consume the nih error
|
||||||
@ -563,8 +613,10 @@ static int cgm_get(const char *filename, char *value, size_t len, const char *na
|
|||||||
nerr = nih_error_get();
|
nerr = nih_error_get();
|
||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
free(cgroup);
|
free(cgroup);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
free(cgroup);
|
free(cgroup);
|
||||||
newlen = strlen(result);
|
newlen = strlen(result);
|
||||||
if (!value) {
|
if (!value) {
|
||||||
@ -590,6 +642,7 @@ static int cgm_do_set(const char *controller, const char *file,
|
|||||||
const char *cgroup, const char *value)
|
const char *cgroup, const char *value)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
ret = cgmanager_set_value_sync(NULL, cgroup_manager, controller,
|
ret = cgmanager_set_value_sync(NULL, cgroup_manager, controller,
|
||||||
cgroup, file, value);
|
cgroup, file, value);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@ -599,6 +652,7 @@ static int cgm_do_set(const char *controller, const char *file,
|
|||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
ERROR("Error setting cgroup %s limit %s", file, cgroup);
|
ERROR("Error setting cgroup %s limit %s", file, cgroup);
|
||||||
}
|
}
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,11 +684,13 @@ static void free_subsystems(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
for (i = 0; i < nr_subsystems; i++)
|
for (i = 0; i < nr_subsystems; i++)
|
||||||
free(subsystems[i]);
|
free(subsystems[i]);
|
||||||
free(subsystems);
|
free(subsystems);
|
||||||
subsystems = NULL;
|
subsystems = NULL;
|
||||||
nr_subsystems = 0;
|
nr_subsystems = 0;
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool collect_subsytems(void)
|
static bool collect_subsytems(void)
|
||||||
@ -646,9 +702,12 @@ static bool collect_subsytems(void)
|
|||||||
if (subsystems) // already initialized
|
if (subsystems) // already initialized
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
f = fopen_cloexec("/proc/cgroups", "r");
|
f = fopen_cloexec("/proc/cgroups", "r");
|
||||||
if (!f)
|
if (!f) {
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
while (getline(&line, &sz, f) != -1) {
|
while (getline(&line, &sz, f) != -1) {
|
||||||
char **tmp;
|
char **tmp;
|
||||||
if (line[0] == '#')
|
if (line[0] == '#')
|
||||||
@ -671,6 +730,8 @@ static bool collect_subsytems(void)
|
|||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
|
|
||||||
if (!nr_subsystems) {
|
if (!nr_subsystems) {
|
||||||
ERROR("No cgroup subsystems found");
|
ERROR("No cgroup subsystems found");
|
||||||
return false;
|
return false;
|
||||||
@ -680,6 +741,7 @@ static bool collect_subsytems(void)
|
|||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
free_subsystems();
|
free_subsystems();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -711,6 +773,7 @@ static bool cgm_unfreeze(void *hdata)
|
|||||||
if (!d || !d->cgroup_path)
|
if (!d || !d->cgroup_path)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
lock_mutex(&thread_mutex);
|
||||||
if (cgmanager_set_value_sync(NULL, cgroup_manager, "freezer", d->cgroup_path,
|
if (cgmanager_set_value_sync(NULL, cgroup_manager, "freezer", d->cgroup_path,
|
||||||
"freezer.state", "THAWED") != 0) {
|
"freezer.state", "THAWED") != 0) {
|
||||||
NihError *nerr;
|
NihError *nerr;
|
||||||
@ -718,8 +781,10 @@ static bool cgm_unfreeze(void *hdata)
|
|||||||
ERROR("call to cgmanager_set_value_sync failed: %s", nerr->message);
|
ERROR("call to cgmanager_set_value_sync failed: %s", nerr->message);
|
||||||
nih_free(nerr);
|
nih_free(nerr);
|
||||||
ERROR("Error unfreezing %s", d->cgroup_path);
|
ERROR("Error unfreezing %s", d->cgroup_path);
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
unlock_mutex(&thread_mutex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user