Commit 3d5e9f48 by Christian Seiler Committed by Serge Hallyn

attach: implement remaining options of lxc_attach_set_environment

This patch implements the extra_env and extra_keep options of lxc_attach_set_environment. The Python implementation, the C container API and the lxc-attach utility are able to utilize this feature; lxc-attach has gained two new command line options for this. Signed-off-by: 's avatarChristian Seiler <christian@iwakd.de> Acked-by: 's avatarSerge E. Hallyn <serge.hallyn@ubuntu.com>
parent d7a09c63
...@@ -254,23 +254,72 @@ int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx) ...@@ -254,23 +254,72 @@ int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx)
int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char** extra_env, char** extra_keep) int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char** extra_env, char** extra_keep)
{ {
/* TODO: implement extra_env, extra_keep
* Rationale:
* - extra_env is an array of strings of the form
* "VAR=VALUE", which are to be set (after clearing or not,
* depending on the value of the policy variable)
* - extra_keep is an array of strings of the form
* "VAR", which are extra environment variables to be kept
* around after clearing (if that is done, otherwise, the
* remain anyway)
*/
(void) extra_env;
(void) extra_keep;
if (policy == LXC_ATTACH_CLEAR_ENV) { if (policy == LXC_ATTACH_CLEAR_ENV) {
char **extra_keep_store = NULL;
char *path_env;
size_t n;
int path_kept = 0;
if (extra_keep) {
size_t count, i;
for (count = 0; extra_keep[count]; count++);
extra_keep_store = calloc(count, sizeof(char *));
if (!extra_keep_store) {
SYSERROR("failed to allocate memory for storing current "
"environment variable values that will be kept");
return -1;
}
for (i = 0; i < count; i++) {
char *v = getenv(extra_keep[i]);
if (v) {
extra_keep_store[i] = strdup(v);
if (!extra_keep_store[i]) {
SYSERROR("failed to allocate memory for storing current "
"environment variable values that will be kept");
while (i > 0)
free(extra_keep_store[--i]);
free(extra_keep_store);
return -1;
}
if (strcmp(extra_keep[i], "PATH") == 0)
path_kept = 1;
}
/* calloc sets entire array to zero, so we don't
* need an else */
}
}
if (clearenv()) { if (clearenv()) {
SYSERROR("failed to clear environment"); SYSERROR("failed to clear environment");
/* don't error out though */ return -1;
}
if (extra_keep_store) {
size_t i;
for (i = 0; extra_keep[i]; i++) {
if (extra_keep_store[i])
setenv(extra_keep[i], extra_keep_store[i], 1);
free(extra_keep_store[i]);
}
free(extra_keep_store);
}
/* always set a default path; shells and execlp tend
* to be fine without it, but there is a disturbing
* number of C programs out there that just assume
* that getenv("PATH") is never NULL and then die a
* painful segfault death. */
if (!path_kept) {
n = confstr(_CS_PATH, NULL, 0);
path_env = malloc(n);
if (path_env) {
confstr(_CS_PATH, path_env, n);
setenv("PATH", path_env, 1);
free(path_env);
}
/* don't error out, this is just an extra service */
} }
} }
...@@ -279,6 +328,24 @@ int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char** extra ...@@ -279,6 +328,24 @@ int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char** extra
return -1; return -1;
} }
/* set extra environment variables */
if (extra_env) {
for (; *extra_env; extra_env++) {
/* duplicate the string, just to be on
* the safe side, because putenv does not
* do it for us */
char *p = strdup(*extra_env);
/* we just assume the user knows what they
* are doing, so we don't do any checks */
if (!p) {
SYSERROR("failed to allocate memory for additional environment "
"variables");
return -1;
}
putenv(p);
}
}
return 0; return 0;
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h>
#include "attach.h" #include "attach.h"
#include "arguments.h" #include "arguments.h"
...@@ -44,6 +45,8 @@ static const struct option my_longopts[] = { ...@@ -44,6 +45,8 @@ static const struct option my_longopts[] = {
/* TODO: decide upon short option names */ /* TODO: decide upon short option names */
{"clear-env", no_argument, 0, 500}, {"clear-env", no_argument, 0, 500},
{"keep-env", no_argument, 0, 501}, {"keep-env", no_argument, 0, 501},
{"keep-var", required_argument, 0, 502},
{"set-var", required_argument, 0, 'v'},
LXC_COMMON_OPTIONS LXC_COMMON_OPTIONS
}; };
...@@ -52,6 +55,32 @@ static signed long new_personality = -1; ...@@ -52,6 +55,32 @@ static signed long new_personality = -1;
static int namespace_flags = -1; static int namespace_flags = -1;
static int remount_sys_proc = 0; static int remount_sys_proc = 0;
static lxc_attach_env_policy_t env_policy = LXC_ATTACH_KEEP_ENV; static lxc_attach_env_policy_t env_policy = LXC_ATTACH_KEEP_ENV;
static char **extra_env = NULL;
static ssize_t extra_env_size = 0;
static char **extra_keep = NULL;
static ssize_t extra_keep_size = 0;
static int add_to_simple_array(char ***array, ssize_t *capacity, char *value)
{
ssize_t count = 0;
if (*array)
for (; (*array)[count]; count++);
/* we have to reallocate */
if (count >= *capacity - 1) {
ssize_t new_capacity = ((count + 1) / 32 + 1) * 32;
char **new_array = realloc((void*)*array, sizeof(char *) * new_capacity);
if (!new_array)
return -1;
memset(&new_array[count], 0, sizeof(char*)*(new_capacity - count));
*array = new_array;
*capacity = new_capacity;
}
(*array)[count] = value;
return 0;
}
static int my_parser(struct lxc_arguments* args, int c, char* arg) static int my_parser(struct lxc_arguments* args, int c, char* arg)
{ {
...@@ -81,6 +110,20 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg) ...@@ -81,6 +110,20 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
case 501: /* keep-env */ case 501: /* keep-env */
env_policy = LXC_ATTACH_KEEP_ENV; env_policy = LXC_ATTACH_KEEP_ENV;
break; break;
case 502: /* keep-var */
ret = add_to_simple_array(&extra_keep, &extra_keep_size, arg);
if (ret < 0) {
lxc_error(args, "memory allocation error");
return -1;
}
break;
case 'v':
ret = add_to_simple_array(&extra_env, &extra_env_size, arg);
if (ret < 0) {
lxc_error(args, "memory allocation error");
return -1;
}
break;
} }
return 0; return 0;
...@@ -113,14 +156,18 @@ Options :\n\ ...@@ -113,14 +156,18 @@ Options :\n\
mount namespace when using -s in order to properly\n\ mount namespace when using -s in order to properly\n\
reflect the correct namespace context. See the\n\ reflect the correct namespace context. See the\n\
lxc-attach(1) manual page for details.\n\ lxc-attach(1) manual page for details.\n\
--clear-env\n\ --clear-env Clear all environment variables before attaching.\n\
Clear all environment variables before attaching.\n\
The attached shell/program will start with only\n\ The attached shell/program will start with only\n\
container=lxc set.\n\ container=lxc set.\n\
--keep-env\n\ --keep-env Keep all current enivornment variables. This\n\
Keep all current enivornment variables. This\n\
is the current default behaviour, but is likely to\n\ is the current default behaviour, but is likely to\n\
change in the future.\n", change in the future.\n\
-v, --set-var Set an additional variable that is seen by the\n\
attached program in the container. May be specified\n\
multiple times.\n\
--keep-var Keep an additional environment variable. Only\n\
applicable if --clear-env is specified. May be used\n\
multiple times.\n",
.options = my_longopts, .options = my_longopts,
.parser = my_parser, .parser = my_parser,
.checker = NULL, .checker = NULL,
...@@ -153,6 +200,8 @@ int main(int argc, char *argv[]) ...@@ -153,6 +200,8 @@ int main(int argc, char *argv[])
attach_options.namespaces = namespace_flags; attach_options.namespaces = namespace_flags;
attach_options.personality = new_personality; attach_options.personality = new_personality;
attach_options.env_policy = env_policy; attach_options.env_policy = env_policy;
attach_options.extra_env_vars = extra_env;
attach_options.extra_keep_env = extra_keep;
if (my_args.argc) { if (my_args.argc) {
command.program = my_args.argv[0]; command.program = my_args.argv[0];
......
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