Unverified Commit b5daeddc by Christian Brauner Committed by GitHub

Merge pull request #3657 from brauner/2021-02-05/init_groups

conf: implement lxc.init.groups
parents d71e4764 7fe8120e
...@@ -277,11 +277,6 @@ static int userns_setup_ids(struct attach_context *ctx, ...@@ -277,11 +277,6 @@ static int userns_setup_ids(struct attach_context *ctx,
if (ctx->setup_ns_gid == LXC_INVALID_UID) if (ctx->setup_ns_gid == LXC_INVALID_UID)
ctx->setup_ns_gid = init_ns_gid; ctx->setup_ns_gid = init_ns_gid;
/*
* TODO: we should also parse supplementary groups and use
* setgroups() to set them.
*/
return 0; return 0;
} }
...@@ -360,11 +355,6 @@ static int parse_init_status(struct attach_context *ctx, lxc_attach_options_t *o ...@@ -360,11 +355,6 @@ static int parse_init_status(struct attach_context *ctx, lxc_attach_options_t *o
return log_error_errno(ret, errno, "Failed to get setup ids"); return log_error_errno(ret, errno, "Failed to get setup ids");
userns_target_ids(ctx, options); userns_target_ids(ctx, options);
/*
* TODO: we should also parse supplementary groups and use
* setgroups() to set them.
*/
return 0; return 0;
} }
...@@ -1214,8 +1204,14 @@ __noreturn static void do_attach(struct attach_payload *ap) ...@@ -1214,8 +1204,14 @@ __noreturn static void do_attach(struct attach_payload *ap)
goto on_error; goto on_error;
} }
if (!lxc_setgroups(0, NULL) && errno != EPERM) if ((options->attach_flags & LXC_ATTACH_SETGROUPS) &&
goto on_error; options->groups.size > 0) {
if (!lxc_setgroups(options->groups.list, options->groups.size))
goto on_error;
} else {
if (!lxc_drop_groups() && errno != EPERM)
goto on_error;
}
if (options->namespaces & CLONE_NEWUSER) if (options->namespaces & CLONE_NEWUSER)
if (!lxc_switch_uid_gid(ctx->setup_ns_uid, ctx->setup_ns_gid)) if (!lxc_switch_uid_gid(ctx->setup_ns_uid, ctx->setup_ns_gid))
......
...@@ -31,6 +31,7 @@ enum { ...@@ -31,6 +31,7 @@ enum {
LXC_ATTACH_NO_NEW_PRIVS = 0x00040000, /*!< PR_SET_NO_NEW_PRIVS */ LXC_ATTACH_NO_NEW_PRIVS = 0x00040000, /*!< PR_SET_NO_NEW_PRIVS */
LXC_ATTACH_TERMINAL = 0x00080000, /*!< Allocate new terminal for attached process. */ LXC_ATTACH_TERMINAL = 0x00080000, /*!< Allocate new terminal for attached process. */
LXC_ATTACH_LSM_LABEL = 0x00100000, /*!< Set custom LSM label specified in @lsm_label. */ LXC_ATTACH_LSM_LABEL = 0x00100000, /*!< Set custom LSM label specified in @lsm_label. */
LXC_ATTACH_SETGROUPS = 0x00200000, /*!< Set additional group ids specified in @groups. */
/* We have 16 bits for things that are on by default and 16 bits that /* We have 16 bits for things that are on by default and 16 bits that
* are off by default, that should be sufficient to keep binary * are off by default, that should be sufficient to keep binary
...@@ -52,6 +53,11 @@ enum { ...@@ -52,6 +53,11 @@ enum {
*/ */
typedef int (*lxc_attach_exec_t)(void* payload); typedef int (*lxc_attach_exec_t)(void* payload);
typedef struct lxc_groups_t {
size_t size;
gid_t *list;
} lxc_groups_t;
/*! /*!
* LXC attach options for \ref lxc_container \c attach(). * LXC attach options for \ref lxc_container \c attach().
*/ */
...@@ -72,7 +78,7 @@ typedef struct lxc_attach_options_t { ...@@ -72,7 +78,7 @@ typedef struct lxc_attach_options_t {
* If the current directory does not exist in the container, the root * If the current directory does not exist in the container, the root
* directory will be used instead because of kernel defaults. * directory will be used instead because of kernel defaults.
*/ */
char* initial_cwd; char *initial_cwd;
/*! The user-id to run as. /*! The user-id to run as.
* *
...@@ -92,12 +98,12 @@ typedef struct lxc_attach_options_t { ...@@ -92,12 +98,12 @@ typedef struct lxc_attach_options_t {
lxc_attach_env_policy_t env_policy; lxc_attach_env_policy_t env_policy;
/*! Extra environment variables to set in the container environment */ /*! Extra environment variables to set in the container environment */
char** extra_env_vars; char **extra_env_vars;
/*! Names of environment variables in existing environment to retain /*! Names of environment variables in existing environment to retain
* in container environment. * in container environment.
*/ */
char** extra_keep_env; char **extra_keep_env;
/**@{*/ /**@{*/
/*! File descriptors for stdin, stdout and stderr, /*! File descriptors for stdin, stdout and stderr,
...@@ -117,33 +123,40 @@ typedef struct lxc_attach_options_t { ...@@ -117,33 +123,40 @@ typedef struct lxc_attach_options_t {
/*! lsm label to set. */ /*! lsm label to set. */
char *lsm_label; char *lsm_label;
/*! The additional group GIDs to run with.
*
* If unset all additional groups are dropped.
*/
lxc_groups_t groups;
} lxc_attach_options_t; } lxc_attach_options_t;
/*! Default attach options to use */ /*! Default attach options to use */
#define LXC_ATTACH_OPTIONS_DEFAULT \ #define LXC_ATTACH_OPTIONS_DEFAULT \
{ \ { \
/* .attach_flags = */ LXC_ATTACH_DEFAULT, \ .attach_flags = LXC_ATTACH_DEFAULT, \
/* .namespaces = */ -1, \ .namespaces = -1, \
/* .personality = */ 0xffffffff, \ .personality = 0xffffffff, \
/* .initial_cwd = */ NULL, \ .initial_cwd = NULL, \
/* .uid = */ (uid_t)-1, \ .uid = (uid_t)-1, \
/* .gid = */ (gid_t)-1, \ .gid = (gid_t)-1, \
/* .env_policy = */ LXC_ATTACH_KEEP_ENV, \ .env_policy = LXC_ATTACH_KEEP_ENV, \
/* .extra_env_vars = */ NULL, \ .extra_env_vars = NULL, \
/* .extra_keep_env = */ NULL, \ .extra_keep_env = NULL, \
/* .stdin_fd = */ 0, \ .stdin_fd = 0, \
/* .stdout_fd = */ 1, \ .stdout_fd = 1, \
/* .stderr_fd = */ 2, \ .stderr_fd = 2, \
/* .log_fd = */ -EBADF, \ .log_fd = -EBADF, \
/* .lsm_label = */ NULL, \ .lsm_label = NULL, \
.groups = {}, \
} }
/*! /*!
* Representation of a command to run in a container. * Representation of a command to run in a container.
*/ */
typedef struct lxc_attach_command_t { typedef struct lxc_attach_command_t {
char* program; /*!< The program to run (passed to execvp) */ char *program; /*!< The program to run (passed to execvp) */
char** argv; /*!< The argv pointer of that program, including the program itself in argv[0] */ char **argv; /*!< The argv pointer of that program, including the program itself in argv[0] */
} lxc_attach_command_t; } lxc_attach_command_t;
/*! /*!
......
...@@ -965,7 +965,7 @@ static int cgroup_tree_remove_wrapper(void *data) ...@@ -965,7 +965,7 @@ static int cgroup_tree_remove_wrapper(void *data)
gid_t nsgid = (arg->conf->root_nsgid_map != NULL) ? 0 : arg->conf->init_gid; gid_t nsgid = (arg->conf->root_nsgid_map != NULL) ? 0 : arg->conf->init_gid;
int ret; int ret;
if (!lxc_setgroups(0, NULL) && errno != EPERM) if (!lxc_drop_groups() && errno != EPERM)
return log_error_errno(-1, errno, "Failed to setgroups(0, NULL)"); return log_error_errno(-1, errno, "Failed to setgroups(0, NULL)");
ret = setresgid(nsgid, nsgid, nsgid); ret = setresgid(nsgid, nsgid, nsgid);
...@@ -1574,7 +1574,7 @@ static int chown_cgroup_wrapper(void *data) ...@@ -1574,7 +1574,7 @@ static int chown_cgroup_wrapper(void *data)
uid_t nsuid = (arg->conf->root_nsuid_map != NULL) ? 0 : arg->conf->init_uid; uid_t nsuid = (arg->conf->root_nsuid_map != NULL) ? 0 : arg->conf->init_uid;
gid_t nsgid = (arg->conf->root_nsgid_map != NULL) ? 0 : arg->conf->init_gid; gid_t nsgid = (arg->conf->root_nsgid_map != NULL) ? 0 : arg->conf->init_gid;
if (!lxc_setgroups(0, NULL) && errno != EPERM) if (!lxc_drop_groups() && errno != EPERM)
return log_error_errno(-1, errno, "Failed to setgroups(0, NULL)"); return log_error_errno(-1, errno, "Failed to setgroups(0, NULL)");
ret = setresgid(nsgid, nsgid, nsgid); ret = setresgid(nsgid, nsgid, nsgid);
......
...@@ -88,7 +88,7 @@ static int do_child(void *vargv) ...@@ -88,7 +88,7 @@ static int do_child(void *vargv)
int ret; int ret;
char **argv = (char **)vargv; char **argv = (char **)vargv;
if (!lxc_setgroups(0, NULL) && errno != EPERM) if (!lxc_drop_groups() && errno != EPERM)
return -1; return -1;
/* Assume we want to become root */ /* Assume we want to become root */
......
...@@ -2671,6 +2671,7 @@ struct lxc_conf *lxc_conf_init(void) ...@@ -2671,6 +2671,7 @@ struct lxc_conf *lxc_conf_init(void)
* default to running as UID/GID 0 when using lxc-execute */ * default to running as UID/GID 0 when using lxc-execute */
new->init_uid = 0; new->init_uid = 0;
new->init_gid = 0; new->init_gid = 0;
memset(&new->init_groups, 0, sizeof(lxc_groups_t));
memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup)); memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup));
memset(&new->ns_share, 0, sizeof(char *) * LXC_NS_MAX); memset(&new->ns_share, 0, sizeof(char *) * LXC_NS_MAX);
memset(&new->timens, 0, sizeof(struct timens_offsets)); memset(&new->timens, 0, sizeof(struct timens_offsets));
...@@ -3919,6 +3920,7 @@ void lxc_conf_free(struct lxc_conf *conf) ...@@ -3919,6 +3920,7 @@ void lxc_conf_free(struct lxc_conf *conf)
free(conf->rcfile); free(conf->rcfile);
free(conf->execute_cmd); free(conf->execute_cmd);
free(conf->init_cmd); free(conf->init_cmd);
free(conf->init_groups.list);
free(conf->init_cwd); free(conf->init_cwd);
free(conf->unexpanded_config); free(conf->unexpanded_config);
free(conf->syslog); free(conf->syslog);
...@@ -4282,7 +4284,7 @@ int userns_exec_minimal(const struct lxc_conf *conf, ...@@ -4282,7 +4284,7 @@ int userns_exec_minimal(const struct lxc_conf *conf,
close_prot_errno_disarm(sock_fds[0]); close_prot_errno_disarm(sock_fds[0]);
if (!lxc_setgroups(0, NULL) && errno != EPERM) if (!lxc_drop_groups() && errno != EPERM)
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
ret = setresgid(resgid, resgid, resgid); ret = setresgid(resgid, resgid, resgid);
...@@ -4700,7 +4702,7 @@ int userns_exec_mapped_root(const char *path, int path_fd, ...@@ -4700,7 +4702,7 @@ int userns_exec_mapped_root(const char *path, int path_fd,
if (!lxc_switch_uid_gid(0, 0)) if (!lxc_switch_uid_gid(0, 0))
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
if (!lxc_setgroups(0, NULL)) if (!lxc_drop_groups())
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
ret = fchown(target_fd, 0, st.st_gid); ret = fchown(target_fd, 0, st.st_gid);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/vfs.h> #include <sys/vfs.h>
#include "attach_options.h"
#include "caps.h" #include "caps.h"
#include "compiler.h" #include "compiler.h"
#include "config.h" #include "config.h"
...@@ -413,10 +414,12 @@ struct lxc_conf { ...@@ -413,10 +414,12 @@ struct lxc_conf {
/* init command */ /* init command */
char *init_cmd; char *init_cmd;
/* if running in a new user namespace, the UID/GID that init and COMMAND /* The uid to use for the container. */
* should run under when using lxc-execute */
uid_t init_uid; uid_t init_uid;
/* The gid to use for the container. */
gid_t init_gid; gid_t init_gid;
/* The groups to use for the container. */
lxc_groups_t init_groups;
/* indicator if the container will be destroyed on shutdown */ /* indicator if the container will be destroyed on shutdown */
unsigned int ephemeral; unsigned int ephemeral;
......
...@@ -94,6 +94,7 @@ lxc_config_define(init_cmd); ...@@ -94,6 +94,7 @@ lxc_config_define(init_cmd);
lxc_config_define(init_cwd); lxc_config_define(init_cwd);
lxc_config_define(init_gid); lxc_config_define(init_gid);
lxc_config_define(init_uid); lxc_config_define(init_uid);
lxc_config_define(init_groups);
lxc_config_define(keyring_session); lxc_config_define(keyring_session);
lxc_config_define(log_file); lxc_config_define(log_file);
lxc_config_define(log_level); lxc_config_define(log_level);
...@@ -211,6 +212,7 @@ static struct lxc_config_t config_jump_table[] = { ...@@ -211,6 +212,7 @@ static struct lxc_config_t config_jump_table[] = {
{ "lxc.include", set_config_includefiles, get_config_includefiles, clr_config_includefiles, }, { "lxc.include", set_config_includefiles, get_config_includefiles, clr_config_includefiles, },
{ "lxc.init.cmd", set_config_init_cmd, get_config_init_cmd, clr_config_init_cmd, }, { "lxc.init.cmd", set_config_init_cmd, get_config_init_cmd, clr_config_init_cmd, },
{ "lxc.init.gid", set_config_init_gid, get_config_init_gid, clr_config_init_gid, }, { "lxc.init.gid", set_config_init_gid, get_config_init_gid, clr_config_init_gid, },
{ "lxc.init.groups", set_config_init_groups, get_config_init_groups, clr_config_init_groups, },
{ "lxc.init.uid", set_config_init_uid, get_config_init_uid, clr_config_init_uid, }, { "lxc.init.uid", set_config_init_uid, get_config_init_uid, clr_config_init_uid, },
{ "lxc.init.cwd", set_config_init_cwd, get_config_init_cwd, clr_config_init_cwd, }, { "lxc.init.cwd", set_config_init_cwd, get_config_init_cwd, clr_config_init_cwd, },
{ "lxc.keyring.session", set_config_keyring_session, get_config_keyring_session, clr_config_keyring_session }, { "lxc.keyring.session", set_config_keyring_session, get_config_keyring_session, clr_config_keyring_session },
...@@ -1178,6 +1180,64 @@ static int set_config_init_gid(const char *key, const char *value, ...@@ -1178,6 +1180,64 @@ static int set_config_init_gid(const char *key, const char *value,
return 0; return 0;
} }
static int set_config_init_groups(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
__do_free char *value_dup = NULL;
gid_t *init_groups = NULL;
size_t num_groups = 0;
size_t idx;
char *token;
if (lxc_config_value_empty(value))
return clr_config_init_groups(key, lxc_conf, NULL);
value_dup = strdup(value);
if (!value_dup)
return -ENOMEM;
lxc_iterate_parts(token, value_dup, ",")
num_groups++;
if (num_groups == INT_MAX)
return log_error_errno(-ERANGE, ERANGE, "Excessive number of supplementary groups specified");
/* This means the string wasn't empty and all we found was garbage. */
if (num_groups == 0)
return log_error_errno(-EINVAL, EINVAL, "No valid groups specified %s", value);
idx = lxc_conf->init_groups.size;
init_groups = realloc(lxc_conf->init_groups.list, sizeof(gid_t) * (idx + num_groups));
if (!init_groups)
return ret_errno(ENOMEM);
/*
* Once the realloc() succeeded we need to hand control of the memory
* back to the config otherwise we risk a double-free when
* lxc_conf_free() is called.
*/
lxc_conf->init_groups.list = init_groups;
/* Restore duplicated value so we can call lxc_iterate_parts() again. */
strcpy(value_dup, value);
lxc_iterate_parts(token, value_dup, ",") {
int ret;
gid_t group;
ret = lxc_safe_uint(token, &group);
if (ret)
return log_error_errno(ret, -ret, "Failed to parse group %s", token);
init_groups[idx++] = group;
}
lxc_conf->init_groups.size += num_groups;
return 0;
}
static int set_config_hooks(const char *key, const char *value, static int set_config_hooks(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
...@@ -4278,6 +4338,26 @@ static int get_config_init_gid(const char *key, char *retv, int inlen, ...@@ -4278,6 +4338,26 @@ static int get_config_init_gid(const char *key, char *retv, int inlen,
return lxc_get_conf_int(c, retv, inlen, c->init_gid); return lxc_get_conf_int(c, retv, inlen, c->init_gid);
} }
static int get_config_init_groups(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
int fulllen = 0, len;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
if (c->init_groups.size == 0)
return 0;
for (int i = 0; i < c->init_groups.size; i++)
strprint(retv, inlen, "%s%d", (i > 0) ? "," : "",
c->init_groups.list[i]);
return fulllen;
}
static int get_config_ephemeral(const char *key, char *retv, int inlen, static int get_config_ephemeral(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
...@@ -4964,6 +5044,14 @@ static inline int clr_config_init_gid(const char *key, struct lxc_conf *c, ...@@ -4964,6 +5044,14 @@ static inline int clr_config_init_gid(const char *key, struct lxc_conf *c,
return 0; return 0;
} }
static inline int clr_config_init_groups(const char *key, struct lxc_conf *c,
void *data)
{
c->init_groups.size = 0;
free_disarm(c->init_groups.list);
return 0;
}
static inline int clr_config_ephemeral(const char *key, struct lxc_conf *c, static inline int clr_config_ephemeral(const char *key, struct lxc_conf *c,
void *data) void *data)
{ {
......
...@@ -3660,7 +3660,7 @@ static int clone_update_rootfs(struct clone_update_data *data) ...@@ -3660,7 +3660,7 @@ static int clone_update_rootfs(struct clone_update_data *data)
/* update hostname in rootfs */ /* update hostname in rootfs */
/* we're going to mount, so run in a clean namespace to simplify cleanup */ /* we're going to mount, so run in a clean namespace to simplify cleanup */
(void)lxc_setgroups(0, NULL); (void)lxc_drop_groups();
if (setgid(0) < 0) { if (setgid(0) < 0) {
ERROR("Failed to setgid to 0"); ERROR("Failed to setgid to 0");
......
...@@ -1111,7 +1111,7 @@ static int do_start(void *data) ...@@ -1111,7 +1111,7 @@ static int do_start(void *data)
/* Drop groups only after we switched to a valid gid in the new /* Drop groups only after we switched to a valid gid in the new
* user namespace. * user namespace.
*/ */
if (!lxc_setgroups(0, NULL) && if (!lxc_drop_groups() &&
(handler->am_root || errno != EPERM)) (handler->am_root || errno != EPERM))
goto out_warn_father; goto out_warn_father;
...@@ -1406,12 +1406,21 @@ static int do_start(void *data) ...@@ -1406,12 +1406,21 @@ static int do_start(void *data)
* we switched to root in the new user namespace further above. Only * we switched to root in the new user namespace further above. Only
* drop groups if we can, so ensure that we have necessary privilege. * drop groups if we can, so ensure that we have necessary privilege.
*/ */
if (lxc_list_empty(&handler->conf->id_map)) if (lxc_list_empty(&handler->conf->id_map)) {
#if HAVE_LIBCAP #if HAVE_LIBCAP
if (lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE)) if (lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE))
#endif #endif
if (!lxc_setgroups(0, NULL)) {
goto out_warn_father; if (handler->conf->init_groups.size > 0) {
if (!lxc_setgroups(handler->conf->init_groups.list,
handler->conf->init_groups.size))
goto out_warn_father;
} else {
if (!lxc_drop_groups())
goto out_warn_father;
}
}
}
if (!lxc_switch_uid_gid(new_uid, new_gid)) if (!lxc_switch_uid_gid(new_uid, new_gid))
goto out_warn_father; goto out_warn_father;
......
...@@ -374,7 +374,7 @@ int btrfs_snapshot_wrapper(void *data) ...@@ -374,7 +374,7 @@ int btrfs_snapshot_wrapper(void *data)
const char *src; const char *src;
struct rsync_data_char *arg = data; struct rsync_data_char *arg = data;
(void)lxc_setgroups(0, NULL); (void)lxc_drop_groups();
if (setgid(0) < 0) { if (setgid(0) < 0) {
ERROR("Failed to setgid to 0"); ERROR("Failed to setgid to 0");
......
...@@ -35,7 +35,7 @@ int lxc_rsync_exec_wrapper(void *data) ...@@ -35,7 +35,7 @@ int lxc_rsync_exec_wrapper(void *data)
if (!lxc_switch_uid_gid(0, 0)) if (!lxc_switch_uid_gid(0, 0))
return -1; return -1;
if (!lxc_setgroups(0, NULL)) if (!lxc_drop_groups())
return -1; return -1;
return lxc_rsync_exec(args->src, args->dest); return lxc_rsync_exec(args->src, args->dest);
...@@ -96,7 +96,7 @@ int lxc_rsync(struct rsync_data *data) ...@@ -96,7 +96,7 @@ int lxc_rsync(struct rsync_data *data)
if (!lxc_switch_uid_gid(0, 0)) if (!lxc_switch_uid_gid(0, 0))
return -1; return -1;
if (!lxc_setgroups(0, NULL)) if (!lxc_drop_groups())
return -1; return -1;
src = lxc_storage_get_path(orig->dest, orig->type); src = lxc_storage_get_path(orig->dest, orig->type);
......
...@@ -461,7 +461,7 @@ int storage_destroy_wrapper(void *data) ...@@ -461,7 +461,7 @@ int storage_destroy_wrapper(void *data)
{ {
struct lxc_conf *conf = data; struct lxc_conf *conf = data;
(void)lxc_setgroups(0, NULL); (void)lxc_drop_groups();
if (setgid(0) < 0) { if (setgid(0) < 0) {
SYSERROR("Failed to setgid to 0"); SYSERROR("Failed to setgid to 0");
......
...@@ -1444,14 +1444,32 @@ bool lxc_switch_uid_gid(uid_t uid, gid_t gid) ...@@ -1444,14 +1444,32 @@ bool lxc_switch_uid_gid(uid_t uid, gid_t gid)
} }
/* Simple convenience function which enables uniform logging. */ /* Simple convenience function which enables uniform logging. */
bool lxc_setgroups(int size, gid_t list[]) bool lxc_drop_groups(void)
{ {
if (setgroups(size, list) < 0) { int ret;
SYSERROR("Failed to setgroups()");
return false; ret = setgroups(0, NULL);
if (ret)
return log_error_errno(false, errno, "Failed to drop supplimentary groups");
NOTICE("Dropped supplimentary groups");
return ret == 0;
}
bool lxc_setgroups(gid_t list[], size_t size)
{
int ret;
ret = setgroups(size, list);
if (ret)
return log_error_errno(false, errno, "Failed to set supplimentary groups");
if (size > 0 && lxc_log_trace()) {
for (size_t i = 0; i < size; i++)
TRACE("Setting supplimentary group %d", list[i]);
} }
NOTICE("Dropped additional groups");
NOTICE("Set supplimentary groups");
return true; return true;
} }
......
...@@ -156,7 +156,8 @@ __hidden extern bool task_blocks_signal(pid_t pid, int signal); ...@@ -156,7 +156,8 @@ __hidden extern bool task_blocks_signal(pid_t pid, int signal);
* If LXC_INVALID_{G,U}ID is passed then the set{g,u}id() will not be called. * If LXC_INVALID_{G,U}ID is passed then the set{g,u}id() will not be called.
*/ */
__hidden extern bool lxc_switch_uid_gid(uid_t uid, gid_t gid); __hidden extern bool lxc_switch_uid_gid(uid_t uid, gid_t gid);
__hidden extern bool lxc_setgroups(int size, gid_t list[]); __hidden extern bool lxc_setgroups(gid_t list[], size_t size);
__hidden extern bool lxc_drop_groups(void);
/* Find an unused loop device and associate it with source. */ /* Find an unused loop device and associate it with source. */
__hidden extern int lxc_prepare_loop_dev(const char *source, char *loop_dev, int flags); __hidden extern int lxc_prepare_loop_dev(const char *source, char *loop_dev, int flags);
......
...@@ -324,7 +324,54 @@ if ENABLE_SECCOMP ...@@ -324,7 +324,54 @@ if ENABLE_SECCOMP
lxc_test_device_add_remove_SOURCES += ../lxc/seccomp.c ../lxc/lxcseccomp.h lxc_test_device_add_remove_SOURCES += ../lxc/seccomp.c ../lxc/lxcseccomp.h
endif endif
lxc_test_getkeys_SOURCES = getkeys.c lxc_test_getkeys_SOURCES = getkeys.c
lxc_test_get_item_SOURCES = get_item.c lxc_test_get_item_SOURCES = get_item.c \
../lxc/af_unix.c ../lxc/af_unix.h \
../lxc/caps.c ../lxc/caps.h \
../lxc/cgroups/cgfsng.c \
../lxc/cgroups/cgroup.c ../lxc/cgroups/cgroup.h \
../lxc/cgroups/cgroup2_devices.c ../lxc/cgroups/cgroup2_devices.h \
../lxc/cgroups/cgroup_utils.c ../lxc/cgroups/cgroup_utils.h \
../lxc/commands.c ../lxc/commands.h \
../lxc/commands_utils.c ../lxc/commands_utils.h \
../lxc/conf.c ../lxc/conf.h \
../lxc/confile.c ../lxc/confile.h \
../lxc/confile_utils.c ../lxc/confile_utils.h \
../lxc/error.c ../lxc/error.h \
../lxc/file_utils.c ../lxc/file_utils.h \
../include/netns_ifaddrs.c ../include/netns_ifaddrs.h \
../lxc/initutils.c ../lxc/initutils.h \
../lxc/log.c ../lxc/log.h \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
../lxc/parse.c ../lxc/parse.h \
../lxc/process_utils.c ../lxc/process_utils.h \
../lxc/ringbuf.c ../lxc/ringbuf.h \
../lxc/start.c ../lxc/start.h \
../lxc/state.c ../lxc/state.h \
../lxc/storage/btrfs.c ../lxc/storage/btrfs.h \
../lxc/storage/dir.c ../lxc/storage/dir.h \
../lxc/storage/loop.c ../lxc/storage/loop.h \
../lxc/storage/lvm.c ../lxc/storage/lvm.h \
../lxc/storage/nbd.c ../lxc/storage/nbd.h \
../lxc/storage/overlay.c ../lxc/storage/overlay.h \
../lxc/storage/rbd.c ../lxc/storage/rbd.h \
../lxc/storage/rsync.c ../lxc/storage/rsync.h \
../lxc/storage/storage.c ../lxc/storage/storage.h \
../lxc/storage/storage_utils.c ../lxc/storage/storage_utils.h \
../lxc/storage/zfs.c ../lxc/storage/zfs.h \
../lxc/sync.c ../lxc/sync.h \
../lxc/string_utils.c ../lxc/string_utils.h \
../lxc/terminal.c ../lxc/terminal.h \
../lxc/utils.c ../lxc/utils.h \
../lxc/uuid.c ../lxc/uuid.h \
$(LSM_SOURCES)
if ENABLE_SECCOMP
lxc_test_get_item_SOURCES += ../lxc/seccomp.c ../lxc/lxcseccomp.h
endif
lxc_test_list_SOURCES = list.c lxc_test_list_SOURCES = list.c
lxc_test_locktests_SOURCES = locktests.c \ lxc_test_locktests_SOURCES = locktests.c \
../lxc/af_unix.c ../lxc/af_unix.h \ ../lxc/af_unix.c ../lxc/af_unix.h \
......
...@@ -29,15 +29,38 @@ ...@@ -29,15 +29,38 @@
#include "lxc/state.h" #include "lxc/state.h"
#include "lxctest.h" #include "lxctest.h"
#include "utils.h"
#ifndef HAVE_STRLCPY
#include "include/strlcpy.h"
#endif
#define MYNAME "lxctest1" #define MYNAME "lxctest1"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int ret; int fd_log, ret;
struct lxc_container *c; struct lxc_container *c = NULL;
int fret = EXIT_FAILURE; int fret = EXIT_FAILURE;
char v1[2], v2[256], v3[2048]; char v1[2], v2[256], v3[2048];
struct lxc_log log = {};
char template[sizeof(P_tmpdir"/attach_XXXXXX")];
(void)strlcpy(template, P_tmpdir"/attach_XXXXXX", sizeof(template));
fd_log = lxc_make_tmpfile(template, false);
if (fd_log < 0) {
lxc_error("Failed to create temporary log file for container %s\n", MYNAME);
exit(EXIT_FAILURE);
}
log.name = MYNAME;
log.file = template;
log.level = "TRACE";
log.prefix = "get_item";
log.quiet = false;
log.lxcpath = NULL;
if (lxc_log_init(&log))
goto out;
if ((c = lxc_container_new("testxyz", NULL)) == NULL) { if ((c = lxc_container_new("testxyz", NULL)) == NULL) {
fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME);
...@@ -136,6 +159,59 @@ int main(int argc, char *argv[]) ...@@ -136,6 +159,59 @@ int main(int argc, char *argv[])
} }
printf("lxc.init_gid returned %d %s\n", ret, v2); printf("lxc.init_gid returned %d %s\n", ret, v2);
if (c->set_config_item(c, "lxc.init.groups", "10,20,foo,40")) {
fprintf(stderr, "%d: managed to set lxc.init.groups to '10,20,foo,40'\n", __LINE__);
goto out;
}
if (!c->set_config_item(c, "lxc.init.groups", "10,20,30,40")) {
fprintf(stderr, "%d: managed to set lxc.init.groups to '10,20,30,40'\n", __LINE__);
goto out;
}
ret = c->get_config_item(c, "lxc.init.groups", v2, 255);
if (ret < 0) {
fprintf(stderr, "%d: failed to get lxc.init.groups\n", __LINE__);
goto out;
}
ret = strcmp("10,20,30,40", v2);
printf("%d: lxc.init.groups returned %d %s\n", __LINE__, ret, v2);
if (ret != 0) {
goto out;
}
if (!c->set_config_item(c, "lxc.init.groups", "50,60,70,80")) {
fprintf(stderr, "%d: failed to set lxc.init.groups to '50,60,70,80'\n", __LINE__);
goto out;
}
ret = c->get_config_item(c, "lxc.init.groups", v2, 255);
if (ret < 0) {
fprintf(stderr, "%d: failed to get lxc.init.groups\n", __LINE__);
goto out;
}
ret = strcmp("10,20,30,40,50,60,70,80", v2);
printf("%d: lxc.init.groups returned %d %s\n", __LINE__, ret, v2);
if (ret != 0) {
goto out;
}
if (!c->set_config_item(c, "lxc.init.groups", "")) {
fprintf(stderr, "%d: failed to set lxc.init.groups to ''\n", __LINE__);
goto out;
}
ret = c->get_config_item(c, "lxc.init.groups", v2, 255);
if (ret < 0) {
fprintf(stderr, "%d: failed to get lxc.init.groups\n", __LINE__);
goto out;
}
ret = strcmp("", v2);
printf("%d: lxc.init.groups returned %d %s\n", __LINE__, ret, v2);
if (ret != 0) {
goto out;
}
#define HNAME "hostname1" #define HNAME "hostname1"
// demonstrate proper usage: // demonstrate proper usage:
char *alloced; char *alloced;
...@@ -619,6 +695,17 @@ out: ...@@ -619,6 +695,17 @@ out:
c->destroy(c); c->destroy(c);
lxc_container_put(c); lxc_container_put(c);
} }
if (fret != EXIT_SUCCESS) {
char buf[4096];
ssize_t buflen;
while ((buflen = read(fd_log, buf, 1024)) > 0) {
buflen = write(STDERR_FILENO, buf, buflen);
if (buflen <= 0)
break;
}
close(fd_log);
}
(void)unlink(template);
exit(fret); exit(fret);
} }
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