Commit 57d116ab by Serge Hallyn

create_run_template: tell the template what caller's uid was mapped to

conf.c/conf.h: have replaced bool hostid_is_mapped() with int mapped_hostid() which returns the mapped uid for the caller's uid on the host, or -1 if none create_run_template: pass caller's uid into template. lxc-ubuntu-cloud: 1. accept --mapped-uid argument 2. don't write to devices cgroup - not allowed. 3. if running in userns, use $HOME/.cache 4. chown cached files to the uid to which our caller was mapped 5. ignore /dev when extracting rootfs in a userns Changelog: nov 5: remove debugging INFO line. Signed-off-by: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com> Acked-by: 's avatarStéphane Graber <stgraber@ubuntu.com>
parent b9d957c3
...@@ -2912,7 +2912,7 @@ uid_t get_mapped_rootid(struct lxc_conf *conf) ...@@ -2912,7 +2912,7 @@ uid_t get_mapped_rootid(struct lxc_conf *conf)
return (uid_t)-1; return (uid_t)-1;
} }
bool hostid_is_mapped(int id, struct lxc_conf *conf) int mapped_hostid(int id, struct lxc_conf *conf)
{ {
struct lxc_list *it; struct lxc_list *it;
struct id_map *map; struct id_map *map;
...@@ -2921,9 +2921,9 @@ bool hostid_is_mapped(int id, struct lxc_conf *conf) ...@@ -2921,9 +2921,9 @@ bool hostid_is_mapped(int id, struct lxc_conf *conf)
if (map->idtype != ID_TYPE_UID) if (map->idtype != ID_TYPE_UID)
continue; continue;
if (id >= map->hostid && id < map->hostid + map->range) if (id >= map->hostid && id < map->hostid + map->range)
return true; return (id - map->hostid) + map->nsid;
} }
return false; return -1;
} }
int find_unmapped_nsuid(struct lxc_conf *conf) int find_unmapped_nsuid(struct lxc_conf *conf)
......
...@@ -362,7 +362,7 @@ extern void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf); ...@@ -362,7 +362,7 @@ extern void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf);
extern uid_t get_mapped_rootid(struct lxc_conf *conf); extern uid_t get_mapped_rootid(struct lxc_conf *conf);
extern int find_unmapped_nsuid(struct lxc_conf *conf); extern int find_unmapped_nsuid(struct lxc_conf *conf);
extern bool hostid_is_mapped(int id, struct lxc_conf *conf); extern int mapped_hostid(int id, struct lxc_conf *conf);
extern int chown_mapped_root(char *path, struct lxc_conf *conf); extern int chown_mapped_root(char *path, struct lxc_conf *conf);
extern int ttys_shift_ids(struct lxc_conf *c); extern int ttys_shift_ids(struct lxc_conf *c);
#endif #endif
...@@ -917,20 +917,27 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet ...@@ -917,20 +917,27 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
* If we're running the template in a mapped userns, then * If we're running the template in a mapped userns, then
* we prepend the template command with: * we prepend the template command with:
* lxc-usernsexec <-m map1> ... <-m mapn> -- * lxc-usernsexec <-m map1> ... <-m mapn> --
* and we append "--mapped-uid x", where x is the mapped uid
* for our geteuid()
*/ */
if (geteuid() != 0 && !lxc_list_empty(&conf->id_map)) { if (geteuid() != 0 && !lxc_list_empty(&conf->id_map)) {
int n2args = 1; int n2args = 1;
char txtuid[20];
char **n2 = malloc(n2args * sizeof(*n2)); char **n2 = malloc(n2args * sizeof(*n2));
struct lxc_list *it; struct lxc_list *it;
struct id_map *map; struct id_map *map;
if (!n2) {
SYSERROR("out of memory");
exit(1);
}
newargv[0] = tpath; newargv[0] = tpath;
tpath = "lxc-usernsexec"; tpath = "lxc-usernsexec";
n2[0] = "lxc-usernsexec"; n2[0] = "lxc-usernsexec";
lxc_list_for_each(it, &conf->id_map) { lxc_list_for_each(it, &conf->id_map) {
map = it->elem; map = it->elem;
n2args += 2; n2args += 2;
n2 = realloc(n2, n2args * sizeof(*n2)); n2 = realloc(n2, n2args * sizeof(char *));
if (!n2) if (!n2)
exit(1); exit(1);
n2[n2args-2] = "-m"; n2[n2args-2] = "-m";
...@@ -943,15 +950,15 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet ...@@ -943,15 +950,15 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
if (ret < 0 || ret >= 200) if (ret < 0 || ret >= 200)
exit(1); exit(1);
} }
bool hostid_mapped = hostid_is_mapped(geteuid(), conf); int hostid_mapped = mapped_hostid(geteuid(), conf);
int extraargs = hostid_mapped ? 1 : 3; int extraargs = hostid_mapped >= 0 ? 1 : 3;
n2 = realloc(n2, (nargs + n2args + extraargs) * sizeof(*n2)); n2 = realloc(n2, (nargs + n2args + extraargs) * sizeof(char *));
if (!n2) if (!n2)
exit(1); exit(1);
if (!hostid_mapped) { if (hostid_mapped < 0) {
int free_id = find_unmapped_nsuid(conf); hostid_mapped = find_unmapped_nsuid(conf);
n2[n2args++] = "-m"; n2[n2args++] = "-m";
if (free_id < 0) { if (hostid_mapped < 0) {
ERROR("Could not find free uid to map"); ERROR("Could not find free uid to map");
exit(1); exit(1);
} }
...@@ -961,7 +968,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet ...@@ -961,7 +968,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
exit(1); exit(1);
} }
ret = snprintf(n2[n2args-1], 200, "u:%d:%d:1", ret = snprintf(n2[n2args-1], 200, "u:%d:%d:1",
free_id, geteuid()); hostid_mapped, geteuid());
if (ret < 0 || ret >= 200) { if (ret < 0 || ret >= 200) {
ERROR("string too long"); ERROR("string too long");
exit(1); exit(1);
...@@ -970,6 +977,20 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet ...@@ -970,6 +977,20 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
n2[n2args++] = "--"; n2[n2args++] = "--";
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
n2[i + n2args] = newargv[i]; n2[i + n2args] = newargv[i];
n2args += nargs;
// Finally add "--mapped-uid $uid" to tell template what to chown
// cached images to
n2args += 2;
n2 = realloc(n2, n2args * sizeof(char *));
if (!n2) {
SYSERROR("out of memory");
exit(1);
}
// note n2[n2args-1] is NULL
n2[n2args-3] = "--mapped-uid";
snprintf(txtuid, 20, "%d", hostid_mapped);
n2[n2args-2] = txtuid;
n2[n2args-1] = NULL;
free(newargv); free(newargv);
newargv = n2; newargv = n2;
} }
......
...@@ -80,7 +80,11 @@ lxc.cap.drop = sys_module mac_admin mac_override sys_time ...@@ -80,7 +80,11 @@ lxc.cap.drop = sys_module mac_admin mac_override sys_time
#lxc.hook.mount = /usr/share/lxc/hooks/mountcgroups #lxc.hook.mount = /usr/share/lxc/hooks/mountcgroups
lxc.hook.clone = ${CLONE_HOOK_FN} lxc.hook.clone = ${CLONE_HOOK_FN}
EOF
# can't write to devices.deny without CAP_SYS_ADMIN in init-user-ns
if [ $in_userns -ne 1 ]; then
cat <<EOF >> $path/config
lxc.cgroup.devices.deny = a lxc.cgroup.devices.deny = a
# Allow any mknod (but not using the node) # Allow any mknod (but not using the node)
lxc.cgroup.devices.allow = c *:* m lxc.cgroup.devices.allow = c *:* m
...@@ -109,6 +113,7 @@ lxc.cgroup.devices.allow = c 10:228 rwm ...@@ -109,6 +113,7 @@ lxc.cgroup.devices.allow = c 10:228 rwm
# kvm # kvm
lxc.cgroup.devices.allow = c 10:232 rwm lxc.cgroup.devices.allow = c 10:232 rwm
EOF EOF
fi
cat <<EOF > $path/fstab cat <<EOF > $path/fstab
proc proc proc nodev,noexec,nosuid 0 0 proc proc proc nodev,noexec,nosuid 0 0
...@@ -123,6 +128,7 @@ EOF ...@@ -123,6 +128,7 @@ EOF
# that in the kernel, but not right now. So let's just bind # that in the kernel, but not right now. So let's just bind
# mount the files from the host. # mount the files from the host.
if [ $in_userns -eq 1 ]; then if [ $in_userns -eq 1 ]; then
mkdir -p $rootfs/dev/pts
for dev in null tty urandom console; do for dev in null tty urandom console; do
touch $rootfs/dev/$dev touch $rootfs/dev/$dev
echo "/dev/$dev dev/$dev none bind 0 0" >> $path/fstab echo "/dev/$dev dev/$dev none bind 0 0" >> $path/fstab
...@@ -161,13 +167,14 @@ EOF ...@@ -161,13 +167,14 @@ EOF
return 0 return 0
} }
options=$(getopt -o a:hp:r:n:Fi:CLS:T:ds:u: -l arch:,help,rootfs:,path:,release:,name:,flush-cache,hostid:,auth-key:,cloud,no_locales,tarball:,debug,stream:,userdata: -- "$@") options=$(getopt -o a:hp:r:n:Fi:CLS:T:ds:u: -l arch:,help,rootfs:,path:,release:,name:,flush-cache,hostid:,auth-key:,cloud,no_locales,tarball:,debug,stream:,userdata:,mapped-uid: -- "$@")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
usage $(basename $0) usage $(basename $0)
exit 1 exit 1
fi fi
eval set -- "$options" eval set -- "$options"
mapped_uid=-1
# default release is precise, or the systems release if recognized # default release is precise, or the systems release if recognized
release=precise release=precise
if [ -f /etc/lsb-release ]; then if [ -f /etc/lsb-release ]; then
...@@ -224,11 +231,13 @@ do ...@@ -224,11 +231,13 @@ do
-u|--userdata) cloneargs[${#cloneargs[@]}]="--userdata=$2"; shift 2;; -u|--userdata) cloneargs[${#cloneargs[@]}]="--userdata=$2"; shift 2;;
-C|--cloud) cloneargs[${#cloneargs[@]}]="--cloud"; shift 1;; -C|--cloud) cloneargs[${#cloneargs[@]}]="--cloud"; shift 1;;
-S|--auth-key) cloneargs[${#cloneargs[@]}]="--auth-key=$2"; shift 2;; -S|--auth-key) cloneargs[${#cloneargs[@]}]="--auth-key=$2"; shift 2;;
--mapped-uid) mapped_uid=$2; shift 2;;
--) shift 1; break ;; --) shift 1; break ;;
*) break ;; *) break ;;
esac esac
done done
echo "mapped_uid is .$mapped_uid."
cloneargs=( "--name=$name" "${cloneargs[@]}" ) cloneargs=( "--name=$name" "${cloneargs[@]}" )
if [ $debug -eq 1 ]; then if [ $debug -eq 1 ]; then
...@@ -296,6 +305,8 @@ type wget ...@@ -296,6 +305,8 @@ type wget
# determine the url, tarball, and directory names # determine the url, tarball, and directory names
# download if needed # download if needed
cache="$STATE_DIR/cache/lxc/cloud-$release" cache="$STATE_DIR/cache/lxc/cloud-$release"
STATE_DIR="$HOME/.cache/lxc/"
cache="$HOME/.cache/lxc/cloud-$release"
mkdir -p $cache mkdir -p $cache
...@@ -371,7 +382,11 @@ do_extract_rootfs() { ...@@ -371,7 +382,11 @@ do_extract_rootfs() {
echo "Extracting container rootfs" echo "Extracting container rootfs"
mkdir -p $rootfs mkdir -p $rootfs
cd $rootfs cd $rootfs
if [ $in_userns -eq 1 ]; then
tar --anchored --exclude="dev/*" --numeric-owner -xpzf "$cache/$filename"
else
tar --numeric-owner -xpzf "$cache/$filename" tar --numeric-owner -xpzf "$cache/$filename"
fi
} }
if [ -n "$tarball" ]; then if [ -n "$tarball" ]; then
...@@ -388,6 +403,12 @@ copy_configuration $path $rootfs $name $arch $release ...@@ -388,6 +403,12 @@ copy_configuration $path $rootfs $name $arch $release
"$CLONE_HOOK_FN" "${cloneargs[@]}" "$rootfs" "$CLONE_HOOK_FN" "${cloneargs[@]}" "$rootfs"
if [ $mapped_uid -ne -1 ]; then
chown $mapped_uid $path/config
chown -R $mapped_uid $STATE_DIR
chown -R $mapped_uid $cache
fi
echo "Container $name created." echo "Container $name created."
exit 0 exit 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