[lxc-users] Fwd: Security consequences of lxc.id_map not mapping a specific uid and gid

Serge Hallyn serge.hallyn at ubuntu.com
Fri Dec 12 15:55:01 UTC 2014


Quoting Christian Brauner (christianvanbrauner at gmail.com):
> > Quoting Christian Brauner (christianvanbrauner at gmail.com):
> > > Hello,
> > > 
> > > I run unprivileged containers and I want them to have access to video and
> > > sound devices. Hence, I  the following in my ~/.config/lxc/default.conf as
> > > suggested on Stéphane's blog:
> > > 
> > >     # Container specific configuration
> > >     lxc.id_map = u 1001 101001 64535
> > >     lxc.id_map = g 1001 101001 64535
> > >     # uid and gid 1000 isn’t translated so that the container can access the
> > >     # X socket and dri and snd and video0 devices
> > >     lxc.id_map = u 0 100000 1000
> > >     lxc.id_map = g 0 100000 1000
> > >     lxc.id_map = u 1000 1000 1
> > >     lxc.id_map = g 1000 1000 1
> > > 
> > > I was wondering compared to an unprivileged container where I simply
> > > map:
> > > 
> > >     lxc.id_map=u 0 100000 65536
> > >     lxc.id_map=g 0 100000 65536
> > > 
> > > 1) Am I significantly more vulnerable when I preserve the uid/gid of my
> > > unprivileged user on the host for my user in the container?
> > 
> > That depends on the threats you worry about, I guess.  Short answer is
> > yes.  So if you run a browser as that user in the container, and the
> > browser succumbs to say a malicous flash binary, the binary has the
> > rights to further proceed on the system with your uid.
> > 
> > I do believe it's worthwhile, still.  First, there's a huge difference
> > in what it can do as a next step if it's your uid, versus if it is running
> > as the host's root uid.  Secondly, it will at this point still be confined
> > by apparmor and namespacing.  Now if you next bind-mount your host user's
> > homedir into the container, then you should be ready to kiss anything in
> > your homedir goodbye.  But if you don't do that, then the fact that the
> > exploit is running as your uid shouldn't be all *that* bad.  Probably
> > the easiest next step for it would be to exploit ownership of the X dir,
> > i.e. to snoop your keyboard.
> > 
> > > 2) And is there a different solution which would allow me to grant
> > > access to the sound and video devices in /dev/snd and /dev/dri to the
> > > user in my unprivileged container while still preserving the standard
> > > mapping:
> > > 
> > >     lxc.id_map=u 0 100000 65536
> > >     lxc.id_map=g 0 100000 65536
> > 
> > You could forward sound devices using pulseaudio over the network
> > instead.  Similarly you could forward X session to 10.0.3.1:0, but
> > that will get you slower video.
> > 
> 
> I actually found a nicer solution. I use setfacl to set permissions on
> specific devices to specific user. Let's say I wanted my container user

Excellent.

Of course that still allows the container to 'own' your kbd/display :)
But not using your host userid still seems worthwhile.

> which I assigned uid 1000 in the container (i.e. 101000 as seen from the
> host) to access the Xsocket, sound, video and framebuffer devices. Then
> I would do:
>     setfacl -R -m "u:101000:r" /tmp/.X11-unix/X0
>     setfacl -R -m "u:101000:rw" /dev/snd/*
>     setfacl -R -m "u:101000:rw" /dev/dri/*
>     setfacl -R -m "u:101000:rw" /dev/video0
>     setfacl -R -m "u:101000:rw" /dev/fb0
> This way the container user can only access  exactly those files/devices
> I make available and not everything that my local user on the host has
> access to.
> 
> 
> > > 3) During container bootup of e.g. Debian Wheezy/Stable is constantly
> > > complaining in the following manner (log output below) and I would like to
> > > now if this can be avoided:
> > > 
> > > 
> > > 
> > > INIT: version 2.88 booting
> > > Using makefile-style concurrent boot in runlevel S.
> > > Cleaning up temporary files... /tmp.
> > > mount: permission denied
> > > mount: permission denied
> > > mount: permission denied
> > > mount: permission denied
> > > mount: permission denied
> > > Mount point '/dev/console' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/full' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/null' does not exist. Skipping mount. ... (warning).
> > 
> > Hm, that's interesting.  The /dev/full (etc) bind mount entries should
> > end in ",create=file" which should prevent this.
> > 
> > Could you show the container configuration file (and any files which are
> > lxc.included, recursively)?
> > 
> Yes, of course:
> 
> 1) config:
> 
>     # Template used to create this container:
>     # /usr/share/lxc/templates/lxc-download
>     # Parameters passed to the template: -d debian -r wheezy -a amd64
>     # For additional config options, please look at
>     # lxc.container.conf(5)
> 
>     # Distribution configuration
>     lxc.include = /usr/share/lxc/config/debian.common.conf
>     lxc.include = /usr/share/lxc/config/debian.userns.conf
>     lxc.arch = x86_64
> 
>     # Container specific configuration
>     lxc.id_map = u 0 100000 65536
>     lxc.id_map = g 0 100000 65536
>     lxc.rootfs = /home/chb/.local/share/lxc/stable/rootfs
>     lxc.utsname = stable
> 
>     # Network configuration
>     lxc.network.type = veth
>     lxc.network.flags = up
>     lxc.network.link = br0
>     lxc.network.name = eth0
>     lxc.network.hwaddr = 00:16:3e:3a:f1:12
>     lxc.network.mtu = 1500
>     lxc.network.ipv4.gateway = 192.168.200.1
>     lxc.network.ipv4 = 192.168.200.12/24
> 
> 
>     # Bind mounts
>     lxc.mount.entry=/tmp/.X11-unix tmp/.X11-unix none ro,bind,optional,create=dir
>     lxc.mount.entry=/dev/snd dev/snd none bind,optional,create=dir
>     lxc.mount.entry=/dev/dri dev/dri none bind,optional,create=dir
>     lxc.mount.entry=/dev/video0 dev/video0 none bind,optional,create=file
>     lxc.mount.entry=/dev/fb0 dev/fb0 none bind,optional,create=file
> 
> 2) /usr/share/lxc/config/debian.common.conf:
> 
>     # Default pivot location
>     lxc.pivotdir = lxc_putold
>     
>     # Default mount entries
>     lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0
>     lxc.mount.entry = sysfs sys sysfs defaults 0 0
>     lxc.mount.entry = /sys/fs/fuse/connections sys/fs/fuse/connections none
>     bind,optional 0 0
>     
>     # Default console settings
>     lxc.tty = 4
>     lxc.pts = 1024
>     
>     # Default capabilities
>     lxc.cap.drop = sys_module mac_admin mac_override sys_time
>     
>     # When using LXC with apparmor, the container will be confined by
>     # default.
>     # If you wish for it to instead run unconfined, copy the following line
>     # (uncommented) to the container's configuration file.
>     #lxc.aa_profile = unconfined
>     
>     # To support container nesting on an Ubuntu host while retaining most of
>     # apparmor's added security, use the following two lines instead.
>     #lxc.aa_profile = lxc-container-default-with-nesting
>     #lxc.hook.mount = /usr/share/lxc/hooks/mountcgroups
>     
>     # If you wish to allow mounting block filesystems, then use the
>     # following
>     # line instead, and make sure to grant access to the block device and/or
>     # loop
>     # devices below in lxc.cgroup.devices.allow.
>     #lxc.aa_profile = lxc-container-default-with-mounting
>     
>     # Default cgroup limits
>     lxc.cgroup.devices.deny = a
>     ## Allow any mknod (but not using the node)
>     lxc.cgroup.devices.allow = c *:* m
>     lxc.cgroup.devices.allow = b *:* m
>     ## /dev/null and zero
>     lxc.cgroup.devices.allow = c 1:3 rwm
>     lxc.cgroup.devices.allow = c 1:5 rwm
>     ## consoles
>     lxc.cgroup.devices.allow = c 5:0 rwm
>     lxc.cgroup.devices.allow = c 5:1 rwm
>     ## /dev/{,u}random
>     lxc.cgroup.devices.allow = c 1:8 rwm
>     lxc.cgroup.devices.allow = c 1:9 rwm
>     ## /dev/pts/*
>     lxc.cgroup.devices.allow = c 5:2 rwm
>     lxc.cgroup.devices.allow = c 136:* rwm
>     ## rtc
>     lxc.cgroup.devices.allow = c 254:0 rm
>     ## fuse
>     lxc.cgroup.devices.allow = c 10:229 rwm
>     ## tun
>     lxc.cgroup.devices.allow = c 10:200 rwm
>     ## full
>     lxc.cgroup.devices.allow = c 1:7 rwm
>     ## hpet
>     lxc.cgroup.devices.allow = c 10:228 rwm
>     ## kvm
>     lxc.cgroup.devices.allow = c 10:232 rwm
>     ## To use loop devices, copy the following line to the container's
>     ## configuration file (uncommented).
>     #lxc.cgroup.devices.allow = b 7:* rwm
>     
>     # Blacklist some syscalls which are not safe in privileged
>     # containers
>     lxc.seccomp = /usr/share/lxc/config/common.seccomp
> 
> 3) /user/share/lxc/config/debian.userns.conf:
> 
>     # CAP_SYS_ADMIN in init-user-ns is required for cgroup.devices
>     lxc.cgroup.devices.deny =
>     lxc.cgroup.devices.allow =
>     
>     # Extra bind-mounts for userns
>     lxc.mount.entry = /dev/console dev/console none bind,create=file 0 0
>     lxc.mount.entry = /dev/full dev/full none bind,create=file 0 0
>     lxc.mount.entry = /dev/null dev/null none bind,create=file 0 0
>     lxc.mount.entry = /dev/random dev/random none bind,create=file 0 0
>     lxc.mount.entry = /dev/tty dev/tty none bind,create=file 0 0
>     lxc.mount.entry = /dev/urandom dev/urandom none bind,create=file 0 0
>     lxc.mount.entry = /dev/zero dev/zero none bind,create=file 0 0
>     
>     # Default seccomp policy is not needed for unprivileged containers, and
>     # non-root users cannot use seccmp without NNP anyway.
>     lxc.seccomp =
> 
> Last but not least:
> I got rid of the alsa amixer and chown X socket warnings by disabling
> the scripts "alsa-utils" and "x11-common" in /etc/init.d/ on Debian
> Squeeze via update-rc.d / insserv.
> 
> Christian
> 
> > > Mount point '/dev/random' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/tty' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/urandom' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/zero' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/video0' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/fb0' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/console' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/tty1' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/tty2' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/tty3' does not exist. Skipping mount. ... (warning).
> > > Mount point '/dev/tty4' does not exist. Skipping mount. ... (warning).
> > > udev requires hotplug support, not started ... failed!
> > >  failed!
> > > Activating lvm and md swap...done.
> > > Checking file systems...fsck from util-linux 2.20.1
> > > done.
> > > Mounting local filesystems...done.
> > > /etc/init.d/mountall.sh: 59: kill: Illegal number: 4 1
> > > Activating swapfile swap...done.
> > > Cleaning up temporary files....
> > > Setting kernel variables ...done.
> > > Configuring network interfaces...done.
> > > Cleaning up temporary files....
> > > Setting up ALSA...Invalid card number.
> > > Usage: amixer <options> [command]
> > > Available options:
> > >   -h,--help       this help
> > >   -c,--card N     select the card
> > >   -D,--device N   select the device, default 'default'
> > >   -d,--debug      debug mode
> > >   -n,--nocheck    do not perform range checking
> > >   -v,--version    print version of this program
> > >   -q,--quiet      be quiet
> > >   -i,--inactive   show also inactive controls
> > >   -a,--abstract L select abstraction level (none or basic)
> > >   -s,--stdin      Read and execute commands from stdin sequentially
> > > Available commands:
> > >   scontrols       show all mixer simple controls
> > >   scontents  show contents of all mixer simple controls (default command)
> > >   sset sID P      set contents for one mixer simple control
> > >   sget sID        get contents for one mixer simple control
> > >   controls        show all controls for given card
> > >   contents        show contents of all controls for given card
> > >   cset cID P      set control contents for one control
> > >   cget cID        get control contents for one control
> > > 
> > > 
> > > Best,
> > > Christian
> > > 
> > > System Information:
> > > 
> > > Arch Linux with user namespace supported kernel.
> > > lxc 1.0.7
> > > 
> > > this script:
> > > 
> > > cgroups are created with printf '\n\033[42mCreating cgroup
> > > hierarchy\033[m\n\n' &&
> > > for d in /sys/fs/cgroup/*; do
> > >         f=$(basename $d)
> > >         echo "looking at $f"
> > >         if [ "$f" = "cpuset" ]; then
> > >                 echo 1 | sudo tee -a $d/cgroup.clone_children;
> > >         elif [ "$f" = "memory" ]; then
> > >                 echo 1 | sudo tee -a $d/memory.use_hierarchy;
> > >         fi
> > >         sudo mkdir -p $d/$USER
> > >         sudo chown -R $USER $d/$USER
> > >         # add current process to cgroup
> > >         echo $$ > $d/$USER/tasks
> > > done
> > 
> > > _______________________________________________
> > > lxc-users mailing list
> > > lxc-users at lists.linuxcontainers.org
> > > http://lists.linuxcontainers.org/listinfo/lxc-users
> > 
> > 
> 
> 
> > _______________________________________________
> > lxc-users mailing list
> > lxc-users at lists.linuxcontainers.org
> > http://lists.linuxcontainers.org/listinfo/lxc-users
> 
> _______________________________________________
> lxc-users mailing list
> lxc-users at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-users


More information about the lxc-users mailing list