Public bug reported:

Now that AppArmor policy namespaces and profile stacking is in place, I
noticed odd stdout buffering behavior when running confined processes
via lxc exec. Much more data stdout data is buffered before getting
flushed when the program is confined by an AppArmor profile inside of
the container.

I see that lxd is calling openpty(3) in the host environment, using the
returned fd as stdout, and then executing the command inside of the
container. This results in an AppArmor denial because the file
descriptor returned by openpty(3) originates outside of the namespace
used by the container.

The denial is likely from glibc calling fstat(), from inside the
container, on the file descriptor associated with stdout to make a
decision on how much buffering to use. The fstat() is denied by AppArmor
and glibc ends up handling the buffering differently than it would if
the fstat() would have been successful.

Steps to reproduce (using an up-to-date 16.04 amd64 VM):

Create a 16.04 container
$ lxc launch ubuntu-daily:16.04 x

Run tcpdump in one terminal and generate traffic in another terminal (wget 
google.com)
$ lxc exec x -- tcpdump -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
<Packet dump>
47 packets captured
48 packets received by filter
1 packet dropped by kernel
<ctrl-c>

Note that everything above <Packet dump> was printed immediately because
it was printed to stderr. <Packet dump>, which is printed to stdout, was
not printed until you pressed ctrl-c and the buffers were flushed thanks
to the program terminating. Also, this AppArmor denial shows up in the
logs:

audit: type=1400 audit(1478902710.025:440): apparmor="DENIED"
operation="getattr" info="Failed name lookup - disconnected path"
error=-13 namespace="root//lxd-x_<var-lib-lxd>"
profile="/usr/sbin/tcpdump" name="dev/pts/12" pid=15530 comm="tcpdump"
requested_mask="r" denied_mask="r" fsuid=165536 ouid=165536

Now run tcpdump unconfined and take note that <Packet dump> is printed 
immediately, before you terminate tcpdump. Also, there are no AppArmor denials.
$ lxc exec x -- aa-exec -p unconfined -- tcpdump -i eth0
...

Now run tcpdump confined but in lxc exec's non-interactive mode and note that 
<Package dump> is printed immediately and no AppArmor denials are present. 
(Looking at the lxd code in lxd/container_exec.go, openpty(3) is only called in 
interactive mode)
$ lxc exec x --mode=non-interactive -- tcpdump -i eth0
...

Applications that manually call fflush(stdout) are not affected by this
as manually flushing stdout works fine. The problem seems to be caused
by glibc not being able to fstat() the /dev/pts/12 fd from the host's
namespace.

** Affects: lxd (Ubuntu)
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1641236

Title:
  Confined processes inside container cannot fully access host pty
  device passed in by lxc exec

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/lxd/+bug/1641236/+subscriptions

-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to