[apparmor] IPC syntax - again

Seth Arnold seth.arnold at canonical.com
Fri Jun 28 23:49:51 UTC 2013

Impressive email, thanks.

I can't begin to address all the open questions you raised, but we have
to start somewhere, so here's my stab at what I felt was most important:


You've very nearly convinced me that for the various forms of on-machine
IPC pairing does not make a lot of sense and the automatic label mechanism
is a better fit.

But TCP and UDP feels like one place where we cannot compromise
pairing. Many services offer vastly dissimilar services on different
ports, even if one event loop in one profile handles all the sockets:

- Python Twisted makes it easy to set up a 'manhole' shell in a service
  with full code-execution privileges; this is different from the services
  it might offer to clients that wouldn't be wide-open code execution.

    network inet tcp subject { address= port=1337 }
        peer { address= },
    network inet tcp subject { address= port=80 }
        peer { address= },

- Erlang connects nodes in a cluster over a socket that gives full
  code-execution privileges, again separate from the services the Erlang
  programs would offer to clients.

    network inet tcp subject { port=4369 } peer { address= },
    network inet tcp subject { port=465 },

- Administrators may configure web servers to provide different
  privileges for data or control structures, and want to restrict access
  to the more-privileged interface to a subset of network-connected

    network inet tcp subject { port=80 iface=eth0 }
        peer ( address= },
    network inet tcp subject { port=80 iface=wlan0 },

- A hypothetical information pump / proxy service -- antivirus, data
  retention compliance servers, privacy scrubber.

    profile internal_face {
    network inet tcp subject { iface=eth0 address= port=80 }
        peer { address= }.
    network inet tcp subject { iface=lo0 address= port=55555 }
        peer { address= port=55556 }

    profile external_face {
    network inet tcp subject { iface=eth1 address= }
        peer { address= }.
    network inet tcp subject { iface=lo0 address= port=55556 }
        peer { address= port=55555 }

I've been thinking about it a bit though; I know we've always wanted to
just write addresses right in profiles like this, but the actual work
to compile down to secmark-capable labels requires full policy compiles.

We've talked about ways around a full policy compile, but support partial
policy reloads with these mechanisms always breaks my brain.

Can we instead treat tcp and udp (and sctp and ..) as labeled shared
objects, just like everything else you've proposed, but with the caveat
that userspace is responsible for putting together the labels?

We can keep the "easy" things entirely in the profiles: bind to ports
and addresses, listen, accept, connect. All these can be done without
full policy compiles. These can provide useful security even without
the extra work to support the pairing that I'm about to suggest.

But if an admin wants to support the pairing, we punt directly to secmark
and either let users write raw iptables commands to mark packets or extend
ufw to know how to add marks to packets. It'll take some thinking to come
up with the best way to get this, but I'm envisioning something like this:


ufw allow from \
    to port 1337 proto tcp mark twisted_manhole
ufw allow to port 80 proto tcp mark twisted_service

profile twisted_server {
  network inet tcp (bind, listen, accept) port 1337,
  network inet tcp (bind, listen, accept) port 80,
  network inet tcp label=twisted_manhole,
  network inet tcp label=twisted_service,


ufw allow from to port 4369 proto tcp mark erlang_cluster
ufw allow to port 465 proto tcp mark erlang_mail

profile erlang {
  network inet tcp port 4369,
  network inet tcp (bind, listen, accept) port 465,
  network inet tcp label=erlang_cluster,
  network inet tcp label=erlang_mail,


ufw allow in on eth0 from to port 80 proto tcp mark web_priv
ufw allow in on wlan0 to port 80 proto tcp mark web_pub

profile www {
  network inet tcp (bind, listen, accept) port 80,
  network inet tcp label=web_priv,
  network inet tcp label=web_pub,

Complicated MAC'd proxy:

ufw allow in on eth0 from \
    to proto tcp mark proxy_in
ufw allow in on lo0 from port 55555 \
    to port 55556 proto tcp mark proxy_middle
ufw allow out on eth1 from \
    to proto tcp mark proxy_out

profile proxy {
  network inet tcp (bind, listen, accept) port 80,
  network inet tcp (connect),
  network inet tcp label=proxy_in,
  network inet tcp label=proxy_out,
  network inet tcp label=proxy_middle,

I might not have the details exactly right -- I'm nearly confident of
that -- but I hope this sketch gives an idea of how we can use ufw to
provide a convenient place to add secmark labels that we then use in
AppArmor profiles.

It's more moving pieces -- and we probably can't give decent error
messages in the case of spelling mistakes, probably can't "learn" these,
and certainly wouldn't ship any of these pairing-by-labels -- but it
does let us provide the functionality that more advanced deployments
will want.

We don't have to use ufw -- standard iptables --selctx can also work --
but ufw is easier for me to understand. ufw can also provide a
convenient location for name <-> number mappings, or perhaps a
convenient interface for managing the mappings.

This also gives us a possibility for a staged deployment: we can get the
"simple" stuff done first -- the bind, listen, accept, connect, sendmsg?,
recvmsg?, that can be decided simply from the contents of a profile -- 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20130628/f34f680c/attachment-0001.pgp>

More information about the AppArmor mailing list