Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export all host envs with prefix into container #185

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions bin/plash.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ int main(int argc, char *argv[]) {
//
// setup environment variables
//
if (asprintf(&newpath, "%s:%s", bindir, path_env) == -1)
pl_fatal("asprintf");
newpath = pl_sprintf("%s:%s", bindir, path_env);

if (setenv("PYTHONPATH", pylibdir, 1) == -1)
pl_fatal("setenv");
if (setenv("PATH", path_env ? newpath : bindir, 1) == -1)
Expand All @@ -80,8 +80,7 @@ int main(int argc, char *argv[]) {
//
// exec lib/exec/<command>
//
if (asprintf(&libexecfile, "%s/%s", libexecdir, argv[1]) == -1)
pl_fatal("asprintf");
libexecfile = pl_sprintf("%s/%s", libexecdir, argv[1]);
execvp(libexecfile, argv + 1);

if (errno != ENOENT)
Expand Down
7 changes: 3 additions & 4 deletions exec/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ char *get_home_dir() {
}

char *get_plash_data() {
char *plash_data;
if (!(plash_data = getenv("PLASH_DATA"))) {
if (asprintf(&plash_data, "%s/.plashdata", get_home_dir()) == -1)
pl_fatal("asprintf");
char *plash_data = getenv("PLASH_DATA");
if (!plash_data) {
return pl_sprintf("%s/.plashdata", get_home_dir());
}
return plash_data;
}
Expand Down
6 changes: 2 additions & 4 deletions exec/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ void set(char const *linkpath, char *container_id) {

if (chdir(pl_call("mkdtemp")) == -1)
pl_fatal("chdir");
if (asprintf(&nodepath, "..%s", nodepath + strlen(plash_data)) == -1)
pl_fatal("asprintf");
nodepath = pl_sprintf("..%s", nodepath + strlen(plash_data));
if (symlink(nodepath, "link") == -1)
pl_fatal("symlink");
if (rename("link", linkpath) == -1)
Expand All @@ -85,8 +84,7 @@ int main(int argc, char *argv[]) {
pl_fatal("'/' not allowed in map name");

// the location of the symlink for this map key
if (asprintf(&linkpath, "%s/map/%s", plash_data, argv[1]) == -1)
pl_fatal("asprintf");
linkpath = pl_sprintf("%s/map/%s", plash_data, argv[1]);

if (argc == 2) {
get(linkpath);
Expand Down
8 changes: 5 additions & 3 deletions exec/mkdtemp.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@

int main() {
char *tmpdir, *tmpdir_templ;
if (asprintf(&tmpdir_templ, "%s/tmp/plashtmp_%d_%d_XXXXXX", pl_call("data"),
getsid(0), getppid()) == -1)
pl_fatal("asprintf");
tmpdir_templ = pl_sprintf(
"%s/tmp/plashtmp_%d_%d_XXXXXX",
pl_call("data"),
getsid(0),
getppid());
tmpdir = mkdtemp(tmpdir_templ);
if (tmpdir == NULL)
pl_fatal("mkdtemp: %s", tmpdir_templ);
Expand Down
2 changes: 0 additions & 2 deletions exec/run.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ int main(int argc, char *argv[]) {
pl_exec_add("HOME");
pl_exec_add("-e");
pl_exec_add("PLASH_DATA");
pl_exec_add("-E");
pl_exec_add("PLASH_EXPORT");

// mountpoints
pl_exec_add("-m");
Expand Down
46 changes: 23 additions & 23 deletions exec/runopts.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,8 @@
// Set the source path for the next mount (-m) call
//
// -e ENV
// Whitelist environment variable for import into container
// Environment variable to import into container without the prefix
//
// -E ENV
// Whitelist all environment variables specified in given environment
// variable. Separator is ':'
//
// -i
// Start with empty environment. -e and -E implies -i

#define _GNU_SOURCE
#include <assert.h>
#include <errno.h>
Expand All @@ -44,7 +37,8 @@

#include <plash.h>

#define OPTSTRING "c:d:M:m:e:E:i"
#define OPTSTRING "c:d:M:m:e:"
#define HOST_ENVS_PREFIX "HOST_"

char *get_default_root_shell() {
struct passwd *pwd = getpwuid(0);
Expand All @@ -69,7 +63,6 @@ int main(int argc, char *argv[]) {
int opt;
char *changesdir = NULL;
char *container = NULL;
int manage_envs = 0;
while ((opt = getopt(argc, argv, OPTSTRING)) != -1) {
switch (opt) {
case 'c':
Expand All @@ -81,17 +74,14 @@ int main(int argc, char *argv[]) {
case 'm':
if (!(optarg[0] == '/'))
pl_fatal("mount path must be absolute");
break;
case 'M':
if (!(optarg[0] == '/'))
pl_fatal("mount source mount path must be absolute");
case 'i':
case 'e':
case 'E':
manage_envs = 1;
break;
case ':':
printf("asdfasdf\n");
pl_usage();
break;
case '?':
pl_usage();
}
Expand Down Expand Up @@ -121,6 +111,24 @@ int main(int argc, char *argv[]) {
pl_call("mount", container, "mnt",
changesdir); // changesdir is ignored if it is NULL

// add prefix to all envs
for (size_t i = 0; environ[i]; i++) {
environ[i] = pl_sprintf(HOST_ENVS_PREFIX "%s", environ[i]);
}

// take over specified envs from the host
optind = 1; // reset the getopt
char *val;
while ((opt = getopt(argc, argv, OPTSTRING)) != -1) {
switch (opt) {
case 'e':
val = getenv(pl_sprintf(HOST_ENVS_PREFIX "%s", optarg));
if (val){
putenv(pl_sprintf("%s=%s", optarg, val));
}
}
}

//
// mount requested mounts
//
Expand Down Expand Up @@ -173,17 +181,9 @@ int main(int argc, char *argv[]) {
case 'M':
mount_src = optarg;
break;
case 'e':
pl_whitelist_env(optarg);
break;
case 'E':
pl_whitelist_envs_from_env(optarg);
break;
}
}

if (manage_envs)
pl_whitelist_env(NULL);

//
// chroot, then reconstruct working directory
Expand Down
45 changes: 12 additions & 33 deletions lib/plash.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ typedef struct {

} fork_exec_newmap_t;


int pl_fatal(char *format, ...) {
va_list args;
va_start(args, format);
Expand All @@ -46,6 +47,17 @@ int pl_fatal(char *format, ...) {
exit(1);
}

char* pl_sprintf(char *format, ...) {
char *strp = NULL;
va_list args;
va_start(args, format);
va_end(args);
if (vasprintf(&strp, format, args) == -1) {;
pl_fatal("vasprintf");
}
return strp;
}

char *pl_path(const char *relpath) {
char *addedpath, *normalizedpath;
static char *herepath = NULL;
Expand Down Expand Up @@ -111,39 +123,6 @@ int pl_parse_subid(const char *file, const char *query1, const char *query2,
return 0;
}

void pl_whitelist_env(char *env_name) {
char *n, *v, *swap;
static size_t env_counter = 0;
if (!env_name)
environ[env_counter++] = NULL;
else {
for (size_t i = env_counter; environ[i]; i++) {
for (n = env_name, v = environ[i]; *n && *v && *n == *v; n++, v++)
;
if (*v == '=' && *n == 0) {
swap = environ[env_counter];
environ[env_counter] = environ[i];
environ[i] = swap;
env_counter++;
}
}
}
}

void pl_whitelist_envs_from_env(const char *export_env) {
char *str;
char *token;
if ((str = getenv(export_env))) {
str = strdup(str);
token = strtok(str, ":");
while (token) {
pl_whitelist_env(token);
token = strtok(NULL, ":");
}
free(str);
}
}

void pl_bind_mount(const char *src, const char *dst) {
if (0 < mount(src, dst, "none", MS_MGC_VAL | MS_BIND | MS_REC, NULL)) {
if (errno != ENOENT) {
Expand Down
4 changes: 1 addition & 3 deletions lib/plash.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ int pl_fatal(char *format, ...);

char *pl_path(const char *relpath);

void pl_whitelist_env(char *env_name);

void pl_setup_user_ns();

void pl_setup_mount_ns();
Expand All @@ -18,7 +16,7 @@ void pl_unshare_mount();

void pl_unshare_user();

void pl_whitelist_envs_from_env(const char *export_env);
char* pl_sprintf(char *format, ...);

void pl_bind_mount(const char *src, const char *dst);

Expand Down
5 changes: 2 additions & 3 deletions lib/python/plash/macros/shortcuts.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
# latest release.
A=[["from", "alpine:edge"], ["apk"]],
U=[["from", "ubuntu:focal"], ["apt"]],
F=[["from", "fedora:32"], ["dnf"]],
D=[["from", "debian:sid"], ["apt"]],
F=[["from", "fedora:35"], ["dnf"]],
D=[["from", "debian:bullseye"], ["apt"]],
C=[["from", "centos:8"], ["yum"]],
R=[["from", "archlinux:current"], ["pacman"]],
G=[["from", "gentoo:current"], ["emerge"]],
)

for name, macro in ALIASES.items():
Expand Down
3 changes: 0 additions & 3 deletions tests/command/create
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,5 @@ stdout=$(mktemp)
(! plash create 1 false > $stdout)
(! test -s $stdout) # its empty

: PLASH_EXPORT is ignored
test "$(PLASH_EXPORT=A A=a plash create 1 sh -c 'echo MARKER$A' 2>&1 | grep MARKER | grep -v +)" = 'MARKER'

: HOME is exported
test "$(HOME=a plash create 1 sh -c 'echo MARKER$HOME' --invalidate-layer 2>&1 | grep MARKER | grep -v +)" = MARKERa
2 changes: 1 addition & 1 deletion tests/command/import-lxc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -xeu

test_import_lxc () {
plash import-lxc "$1" --dry | xargs curl --head --location --fail | grep "Content-Type: application/x-tar"
plash import-lxc "$1" --dry | xargs curl --head -L --fail | grep "Content-Type: application/x-xz"
}
# test the test
(! test_import_lxc badimagname )
Expand Down
25 changes: 5 additions & 20 deletions tests/command/runopts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ cmp /etc/passwd $tmp
: mount to different location
tmp=$(mktemp)
changesdir=$(mktemp -d)
plash runopts -c 1 -d $changesdir -M /etc/passwd -m /mnt cat /mnt > $tmp
cat $tmp
cmp /etc/passwd $tmp
plash runopts -c 1 -d /tmp/tmp.blo0wTDbzE -M /etc/ -m /mnt ls /mnt/passwd

: no mount namespace pollutions
new=$(plash create 1 ls)
Expand All @@ -42,29 +40,16 @@ test $before = $after
#
# environemnt handling
#
: by default all envs exported
test "$(env | cut -d= -f1)" = "$(plash runopts -c 1 env | cut -d= -f1)"

: no envs exported if -i specified
out="$(plash runopts -i -c 1 printenv)"
test "" = "$out"
: by default all envs exported with a HOST_ prefix
test "$(env | cut -d= -f1 | sed -e 's/^/HOST_/')" = "$(plash runopts -c 1 env | cut -d= -f1)"

: only export whitelisted envs
: exported envs accessible without prefix
test "A=1
B=2" = "$(A=1 B=2 plash runopts -e A -e B -c 1 printenv)"

: only export whitelisted envs by another env
test "A=a" = "$(EXPORT=A A=a plash runopts -c 1 -E EXPORT printenv)"
: only export multiple whitelisted envs by another env
test "A=a
B=b" = "$(EXPORT=A:B A=a B=b plash runopts -c 1 -E EXPORT printenv)"
B=2" = "$(A=1 B=2 plash runopts -e A -e B -c 1 printenv | grep '^A=\|^B=')"

: not existing env to export does succeed
plash runopts -c 1 -e daENV true

: not existing env to export envs succeeds
plash runopts -c 1 -E DAENV true

#
# Exit codes
#
Expand Down
7 changes: 3 additions & 4 deletions tests/macro/shortcuts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ test "$out" = hi

: test pinned down version in shortcuts
plash import-lxc alpine:edge --dry
plash import-lxc ubuntu:bionic --dry
plash import-lxc fedora:31 --dry
plash import-lxc debian:sid --dry
plash import-lxc ubuntu:focal --dry
plash import-lxc fedora:35 --dry
plash import-lxc debian:bullseye --dry
plash import-lxc centos:8 --dry
plash import-lxc archlinux:current --dry
plash import-lxc gentoo:current --dry