Thread (9 messages) 9 messages, 4 authors, 2017-06-16
STALE3272d

[PATCH RFC] Smack: More sanity in the use of Netlabel

From: paul@paul-moore.com (Paul Moore)
Date: 2017-06-14 22:31:28

On Tue, Jun 13, 2017 at 5:24 PM, Casey Schaufler [off-list ref] wrote:
On 6/13/2017 8:37 AM, Paul Moore wrote:
quoted
I'll refrain from commenting on any details in the Smack code, but I
thought it might be worth mentioning/asking two things:

* I know I've brought this up before and you punted, but since you are
reworking the code I figured it is worth mentioning again: I would
really recommend leveraging the NetLabel caching mechanism.  All of my
measurements are old, but the performance improvement for SELinux was
significant; not only do you get to bypass the CIPSO/CALIPSO option
parsing, but you get to bypass any of the secattr-to-LSM conversions
necessary.
I haven't forgotten about the caching, I'm just having
trouble working out how to use it. In particular, I think
(but I'm not completely sure) that having two labels, one
for incoming and one for outgoing, on each socket makes
using the caching mechanism difficult.
The NetLabel cache is just a LSM specified blob that gets associated
with the protocol specific packet label.  In SELinux it lets us jump
straight from the CIPSO/CALIPSO option to the secid which is a big
win.  I would imagine you could do something similar with a pointer to
a smack_known struct.
Smack does not compose or parse packet options
except when labels are introduced ("imported" in Smack
terms) to the system. The label/secid/CIPSO triple is
computed the first time the label is seen and maintained
as long as the system runs. When a packet comes in the
CIPSO is looked up in the list. When a packet is to be
sent the CIPSO is taken from the list entry pointed to
by the socket (smk_out) label.
Well, call it what you want but I see a linear cost
list_for_each_entry() in smack_from_secattr() that could probably be
bypassed by utilizing the cache.  Not to mention the cost involved in
parsing the category bitmap.

This is what I was talking about when I talked about secattr-to-LSM conversions.
Does caching work with address selectors? It doesn't look
like it does, but I can only wrap my brain around so much.
Yep.  We're talking high level so I won't bother with the details, but
the cache works anytime you ask NetLabel to go from the wire-label to
the secattr-label.
quoted
* It sounds like the main motivation for this change is to help enable
LSM stacking for the per-packet access controls.
It's a major motivator, but while I was looking at the existing
code I became quite dissatisfied with what's there.
quoted
With that in mind
would you care to share your current thinking/plans for that?  The
proper context (SELinux joke, hardy har har) should help us comment on
the ideas/designs in this patch.
In conversations in Toronto last year we agreed that the only thing
that makes sense is that all security modules need to agree on the
packet labeling for a packet to be sent.
To be clear, "agree on the packet labeling" means two basic things.

* The global configuration: outbound traffic maps, protocol
definitions (e.g. CIPSO DOIs)

* The per-packet label as seen by the NetLabel kAPI (e.g. struct
netlbl_lsm_secattr)
There are exactly three ways that this can happen:

        1. Everyone agrees the packet should be unlabeled.
Yep.  Although very uninteresting.
        2. Everyone agrees to a common labeling
Yep.  See above for what I think that needs to mean.
        3. Everyone has their own idea on the labeling,
           and they just happen to match.
...
I am of the opinion that case #3 is so far fetched that it
might be ignored. If you agree on the labeling that much I'm
willing to bet that one of the security modules is redundant.
Getting the label granularity to match that closely between
modules would be a major configuration accomplishment. If it
happens occasionally, great, but SELinux's use of just the
MLS component and Smack's spelling out the label in category
bits aren't coming together coincidentally very often. You
can increase the cases where the two agree with Smack's
ability to explicitly assign a CIPSO value for a Smack label,
but I don't see a complete system working that way.
Let's agree to just throw out option #3.  Admins might get lucky and
have it work once in a great while, but it is far from a general
solution and not something I could ever recommend.
On a local interface you can use Tag 6 to send a secid. If
you can create a secid that represents a SELinux context
and Smack label pair (or whatever combination of modules
you like) you can achieve case #2 locally. This is very good
news for Smack, because local enforcement is critical.
And, we need to have a mapped secid solution for SO_PEERSEC
anyway.
I think eventually we are going to need either a mapping layer for
secids (ungh) or a LSM framework mechanism that allows LSMs to
allocate new secids and have each stacked LSM setup the right state
internally.  I haven't thought enough about the second option to
figure out if it is even feasible, but it saves us the extra layer of
abstraction.
Which brings us to case #1, unlabeled packets. If the
system can detect that no one wants a label on a packet
it can happily be sent. If a packet arrives unlabeled,
and everyone knows what they want to do in that case,
there's nothing to worry about. SELinux typically allows
unlabeled packets to be delivered and sends packets
unlabeled. Smack sends packets with CIPSO unless the
sender has the "ambient" label. Smack will also send
unlabeled packets to "single label" hosts.
If you solve the two "agree on packet labeling" concerns I mentioned
above this just works.

While unlabeled traffic obviously needs to work, it isn't really a
specific use case we need to worry about at the moment.  Solve the
general problem and this should "just work".
So, if Smack defines 0.0.0.0/32 as single label floor ("_")
(unlabeled) and 127.0.0.1 as CIPSO,tag6 with appropriate
Netlabel address selectors you should have a situation
where you agree on local labeling by case #2 and everyone
else by case #3 for typical configurations. If you define
0.0.0.0/32 with the web ("@") label you get uncontrolled
network behavior for Smack, as well as SELinux. If you
want to send CIPSO to the world "0.0.0.0/32 -CIPSO" will
do that for Smack, and good luck with matching up your
labeling a'la #1.

If there is a mechanism for mapping the sending labels into
a single u32 secid we can label locally. If we can agree to
send packets unlabeled we also have no issue, but there needs
to be a way to detect that before a packet can be sent. Finally,
if we're going to insist on sending a labeled packet off box
there has to be a way to detect the unlikely possibility of
agreement. All of which seems doable.
Without nitpicking the ideas above, I do agree it all seems doable at
the moment.

-- 
paul moore
www.paul-moore.com
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help