add c->may_control

This is an api function which will return false if the container
is running, and the caller may not talk to its monitor over its
command socket.  Otherwise - if the container is not running, or
the caller may access it - it returns true.

We can use this in several tools early on to prevent the segvs
etc which we currently get.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
Acked-by: Dwight Engen <dwight.engen@oracle.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
This commit is contained in:
Serge Hallyn 2013-09-27 21:01:07 -05:00
parent fe218ca383
commit b494d2ddf7
6 changed files with 93 additions and 2 deletions

View File

@ -291,6 +291,36 @@ out:
return ret; return ret;
} }
int lxc_try_cmd(const char *name, const char *lxcpath)
{
int stopped, ret;
struct lxc_cmd_rr cmd = {
.req = { .cmd = LXC_CMD_GET_INIT_PID },
};
ret = lxc_cmd(name, &cmd, &stopped, lxcpath);
if (stopped)
return 0;
if (ret > 0 && cmd.rsp.ret < 0) {
errno = cmd.rsp.ret;
return -1;
}
if (ret > 0)
return 0;
/*
* At this point we weren't denied access, and the
* container *was* started. There was some inexplicable
* error in the protocol.
* I'm not clear on whether we should return -1 here, but
* we didn't receive a -EACCES, so technically it's not that
* we're not allowed to control the container - it's just not
* behaving.
*/
return 0;
}
/* Implentations of the commands and their callbacks */ /* Implentations of the commands and their callbacks */
/* /*

View File

@ -88,5 +88,6 @@ extern int lxc_cmd_init(const char *name, struct lxc_handler *handler,
const char *lxcpath); const char *lxcpath);
extern int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr, extern int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
struct lxc_handler *handler); struct lxc_handler *handler);
extern int lxc_try_cmd(const char *name, const char *lxcpath);
#endif /* __commands_h */ #endif /* __commands_h */

View File

@ -2592,6 +2592,11 @@ static bool lxcapi_snapshot_restore(struct lxc_container *c, char *snapname, cha
return b; return b;
} }
static bool lxcapi_may_control(struct lxc_container *c)
{
return lxc_try_cmd(c->name, c->config_path) == 0;
}
static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...) static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
{ {
va_list ap; va_list ap;
@ -2711,6 +2716,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
c->snapshot = lxcapi_snapshot; c->snapshot = lxcapi_snapshot;
c->snapshot_list = lxcapi_snapshot_list; c->snapshot_list = lxcapi_snapshot_list;
c->snapshot_restore = lxcapi_snapshot_restore; c->snapshot_restore = lxcapi_snapshot_restore;
c->may_control = lxcapi_may_control;
/* we'll allow the caller to update these later */ /* we'll allow the caller to update these later */
if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, c->config_path)) { if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, c->config_path)) {

View File

@ -223,6 +223,12 @@ struct lxc_container {
* Returns true on success, false on failure. * Returns true on success, false on failure.
*/ */
bool (*snapshot_restore)(struct lxc_container *c, char *snapname, char *newname); bool (*snapshot_restore)(struct lxc_container *c, char *snapname, char *newname);
/*
* Return false if there is a control socket for the container monitor,
* and the caller may not access it. Return true otherwise.
*/
bool (*may_control)(struct lxc_container *c);
}; };
struct lxc_snapshot { struct lxc_snapshot {

View File

@ -19,6 +19,7 @@ lxc_usernic_test_SOURCES = ../lxc/lxc_user_nic.c ../lxc/nl.c
lxc_usernic_test_CFLAGS = -DISTEST lxc_usernic_test_CFLAGS = -DISTEST
lxc_test_snapshot_SOURCES = snapshot.c lxc_test_snapshot_SOURCES = snapshot.c
lxc_test_concurrent_SOURCES = concurrent.c lxc_test_concurrent_SOURCES = concurrent.c
lxc_test_may_control_SOURCES = may_control.c
AM_CFLAGS=-I$(top_srcdir)/src \ AM_CFLAGS=-I$(top_srcdir)/src \
-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \ -DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
@ -31,7 +32,7 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \
lxc-test-destroytest lxc-test-saveconfig lxc-test-createtest \ lxc-test-destroytest lxc-test-saveconfig lxc-test-createtest \
lxc-test-shutdowntest lxc-test-get_item lxc-test-getkeys lxc-test-lxcpath \ lxc-test-shutdowntest lxc-test-get_item lxc-test-getkeys lxc-test-lxcpath \
lxc-test-cgpath lxc-test-clonetest lxc-test-console lxc-usernic-test \ lxc-test-cgpath lxc-test-clonetest lxc-test-console lxc-usernic-test \
lxc-test-snapshot lxc-test-concurrent lxc-test-snapshot lxc-test-concurrent lxc-test-may-control
bin_SCRIPTS = lxc-test-usernic bin_SCRIPTS = lxc-test-usernic
@ -53,4 +54,5 @@ EXTRA_DIST = \
console.c \ console.c \
lxc-test-usernic \ lxc-test-usernic \
snapshot.c \ snapshot.c \
concurrent.c concurrent.c \
may_control.c

46
src/tests/may_control.c Normal file
View File

@ -0,0 +1,46 @@
/* control.c
*
* Copyright © 2013 Canonical, Inc
* Author: Serge Hallyn <serge.hallyn@ubuntu.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <lxc/lxccontainer.h>
void usage(char *me)
{
printf("Usage: %s name [lxcpath]\n", me);
exit(0);
}
int main(int argc, char *argv[])
{
char *lxcpath = NULL, *name;
bool may = false;
struct lxc_container *c;
if (argc < 2)
usage(argv[0]);
name = argv[1];
if (argc == 3)
lxcpath = argv[2];
c = lxc_container_new(name, lxcpath);
if (c)
may = c->may_control(c);
printf("You may%s control %s\n", may ? "" : " not", name);
exit(may ? 0 : 1);
}