* If we're running the template in a mapped userns, then
* we prepend the template command with:
* 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)) {
int n2args = 1;
+ char txtuid[20];
char **n2 = malloc(n2args * sizeof(*n2));
struct lxc_list *it;
struct id_map *map;
+ if (!n2) {
+ SYSERROR("out of memory");
+ exit(1);
+ }
newargv[0] = tpath;
tpath = "lxc-usernsexec";
n2[0] = "lxc-usernsexec";
lxc_list_for_each(it, &conf->id_map) {
map = it->elem;
n2args += 2;
- n2 = realloc(n2, n2args * sizeof(*n2));
+ n2 = realloc(n2, n2args * sizeof(char *));
if (!n2)
exit(1);
n2[n2args-2] = "-m";
if (ret < 0 || ret >= 200)
exit(1);
}
- bool hostid_mapped = hostid_is_mapped(geteuid(), conf);
- int extraargs = hostid_mapped ? 1 : 3;
- n2 = realloc(n2, (nargs + n2args + extraargs) * sizeof(*n2));
+ int hostid_mapped = mapped_hostid(geteuid(), conf);
+ int extraargs = hostid_mapped >= 0 ? 1 : 3;
+ n2 = realloc(n2, (nargs + n2args + extraargs) * sizeof(char *));
if (!n2)
exit(1);
- if (!hostid_mapped) {
- int free_id = find_unmapped_nsuid(conf);
+ if (hostid_mapped < 0) {
+ hostid_mapped = find_unmapped_nsuid(conf);
n2[n2args++] = "-m";
- if (free_id < 0) {
+ if (hostid_mapped < 0) {
ERROR("Could not find free uid to map");
exit(1);
}
exit(1);
}
ret = snprintf(n2[n2args-1], 200, "u:%d:%d:1",
- free_id, geteuid());
+ hostid_mapped, geteuid());
if (ret < 0 || ret >= 200) {
ERROR("string too long");
exit(1);
n2[n2args++] = "--";
for (i = 0; i < nargs; 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);
newargv = n2;
}
#lxc.hook.mount = /usr/share/lxc/hooks/mountcgroups
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
# Allow any mknod (but not using the node)
lxc.cgroup.devices.allow = c *:* m
# kvm
lxc.cgroup.devices.allow = c 10:232 rwm
EOF
+ fi
cat <<EOF > $path/fstab
proc proc proc nodev,noexec,nosuid 0 0
# that in the kernel, but not right now. So let's just bind
# mount the files from the host.
if [ $in_userns -eq 1 ]; then
+ mkdir -p $rootfs/dev/pts
for dev in null tty urandom console; do
touch $rootfs/dev/$dev
echo "/dev/$dev dev/$dev none bind 0 0" >> $path/fstab
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
usage $(basename $0)
exit 1
fi
eval set -- "$options"
+mapped_uid=-1
# default release is precise, or the systems release if recognized
release=precise
if [ -f /etc/lsb-release ]; then
-u|--userdata) cloneargs[${#cloneargs[@]}]="--userdata=$2"; shift 2;;
-C|--cloud) cloneargs[${#cloneargs[@]}]="--cloud"; shift 1;;
-S|--auth-key) cloneargs[${#cloneargs[@]}]="--auth-key=$2"; shift 2;;
+ --mapped-uid) mapped_uid=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
+echo "mapped_uid is .$mapped_uid."
cloneargs=( "--name=$name" "${cloneargs[@]}" )
if [ $debug -eq 1 ]; then
# determine the url, tarball, and directory names
# download if needed
cache="$STATE_DIR/cache/lxc/cloud-$release"
+STATE_DIR="$HOME/.cache/lxc/"
+cache="$HOME/.cache/lxc/cloud-$release"
mkdir -p $cache
echo "Extracting container rootfs"
mkdir -p $rootfs
cd $rootfs
- tar --numeric-owner -xpzf "$cache/$filename"
+ if [ $in_userns -eq 1 ]; then
+ tar --anchored --exclude="dev/*" --numeric-owner -xpzf "$cache/$filename"
+ else
+ tar --numeric-owner -xpzf "$cache/$filename"
+ fi
}
if [ -n "$tarball" ]; then
"$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."
exit 0