[RFC] packet/socket owner match (fireflier) using skfilter

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Fireflier aims at providing per application filtering. That is allowing to 
create rules like: allow apache to listen on port 80 (and only apache, nobody 
else).

A couple of days ago fireflier security module + iptables fireflier match 
module started to work [8].

Before continuing the work on it, I ask for your advice, and comments on what 
I've done so far.
I have marked with [!] the issues that are currently the most important.

0. Getting the patch/code
---------------------
All code/patches is for kernel 2.6.16.1, and iptables 1.3.5

I didn't include the patch inline, since it is quite long (1800+ lines , 
~100k). So I uploaded them here:
http://edwintorok.googlepages.com/fireflier_kernel.html

James Morris's patches [5] didn't apply cleanly to 2.6.16.1, so I had to 
modify them a bit, I have uploaded the actual patches applied
to the kernel, and iptables. (I might have made mistakes in "porting" the 
skfilter patches to 2.6.16, please point them out to me)

For the impatient, a direct link to the download:
http://edwintorok.googlepages.com/fireflier_modules.zip
http://edwintorok.googlepages.com/skfilter_patches.zip

1. Background
-----------------------
The initial approach [1] as pointed out by several ([2],[3])  people was 
fundamentally wrong.

AFAIK there is currently work being done to solve this using SELinux [4], but 
I'd like to have 'per application filtering' even without SELinux, so I
looked at James Morris and Patrick McHardy's skfilter patches [5].

So my idea was, that we use James Morris's patches, but instead of using the 
selinux security context, we use a security context based on the process's 
(its executable's) inode+mountpoint. For this we need some sort of 
auto-labeling. The LSM hooks provide just enough hooks in the right places to 
support this.
I have also written an iptables match target (and appropriate userspace 
libipt_...) based on ipt_owner.c, that matches based on the labels (SIDs) 
provided by fireflier LSM.

A detailed description of why, and how I've done this can be found on the 
wiki[6].

This code is currently working, see the tests I have done:[8]

2. Goals of fireflier LSM module
----------------------------------------
    * auto label each process with its executable's inode+mountpoint, i.e. a 
process's security context = SID based on {mountpoint+inode of its 
executable}
    * auto label each file a process has access to. If multiple processes have 
access to the same file, then create a group SID, containing all the SIDs of 
processes having access it. 
    * If multiple processes have access to the same file, but were launched 
from the same executable, then don't label with group SID (like 10 apache 
processes accessing the same socket: the socket will get the SID of apache)
    * it won't deny any operation, it just labels
    * it is not intended to be used when selinux=1 enabled at boot. If selinux 
is enabled then selinux should be used to provide the security context, and 
not fireflier 

3. Issues with fireflier LSM
-----------------------------------------

3.1 Duplicate code
---------------------
I needed a SID <-> context mapping, and I've seen that SELinux already has 
such a data structure in sidtab.c
There was no way to use that as is, since it had no exported symbols, and 
besides my context structure was different from an SELinux context,
so I copied sidtab.c to fireflier LSM. The problem is that a bug gets fixed in 
sidtab.c, ... it doesn't in fireflier LSM.
How can I use the functionality provided by sidtab.c in my LSM without 
duplicating the code?
I have thought of this solution, but I'm not sure if it is the best:
* create a patch between the selinux sidtab, and fireflier sidtab
* every time sidtab.c is changed in the kernel copy it to fireflier
* apply the patch

Also hooks.c is based on hooks.c from SELinux.

3.2 Capability module doesn't support stacking [!]
-----------------------------------------------
I have to boot with capability.disable=1 in order to be able to load 
fireflier. Otherwise it fails to register (it can't register neither as 
primary, neither as secondary LSM). Can stacking be added to the capability 
module? 

3.3 Fireflier LSM loaded as module [!]
-----------------------------------
Currently fireflier LSM is loaded as a module, and not compiled in the kernel. 
Are there any security issues that might arise from this?
(such as [9])

3.4 Performance
------------------
The SID->context lookup uses hashtable, ok.
But  context->SID lookup uses linear search (through the hash-table), can this 
be improved?
Using another hash-table, that based on the hash of a context maps to a SID 
would solve this, but it needs additional memory.

As far as autolabel.c is concerned I need to do the following: label only 
sockets, and not all inodes, for this I need to provide hook for 
socket_create, and label inodes only there?

3.5 Testing
------------
I will have to implement auto-test, that test the labels are properly applied. 
For this purpose I have created a debugging mode, where I create files
in debugfs (it currently only creates them, that is it leaks memory, I'll fix 
this later).
Is there a recommended way to do such tests? How is SELinux being tested?



4. Issues with fireflier iptables match
----------------------------------------
This is what it can currently handle:
iptables -t skfilter -A SOCKET -m fireflier_match --inode-owner 
81949 --dev-owner /dev/root -j ACCEPT

4.1 No group matching yet [!]
--------------------------
It currently matches against individual SIDs only, and can't match against 
groups. (in case a socket has a group SID, it won't be matched by the rule)
I have thought of several [7] solutions, but I am not sure which one is the 
Right Way to do it. 
IMHO solution II ([7]) would be the appropriate one:
* if a packet arrives on a socket having a group SID, and the rule tells to 
match on a SID contained in that group, then:
   * mark the packet, that it has been matched by the SID (of this rule)
   * if the packet has been marked that is has been matched by all SIDs in the 
group, then the packet is allowed to pass (i.e. matched by the rule)

The problems are:
* Can I do packet marking outside the mangle table? (in the skfilter table)?
* What would the performance penalty be to mark packets?
* How much memory would this need?
* How do I do the actual packet marking?

4.2 Duplicate code
-------------------------

I haven't included the fireflier match inside ipt_owner.c, because I wanted it 
to be installed as easy as possible, and this means, that
both the LSM module, and math module are compiled outside of the kernel tree 
currently.

What would I need to do in order to have this merged in the kernel tree? What 
conditions does the module (patch) have to meet?
Should I create a patch that can be applied with patch-o-matic-ng?

4.3 Performance benchmark
---------------------------
What is recommended way to profile an iptables match module? What tests do you 
suggest?

4.4. Testing
--------------------
I'd like to implement auto-tests for the iptables module too.
Besides testing saving/loading the rules, I'd like to test if it actually 
works. I am thinking of doing this:
* start up 3 processes:
  - program A that forks itself, and listens on a non-shared socket (lets say 
port 80, apache)
  - program B, and C share a socket with the 3rd one (lets say port 25, 
postfix)
  - program D that doesn't fork (and listens on port 22, sshd)
* create rules that match on different scenarios:
  - dst port 80, apache inode => this has to match
  - dst port 25, inode of B => this mustn't match
  - dst port 25, inode of C => this should match (if using solution II[7])
  - dst port 22, inode of B => mustn't match
  - dst port 22, inode of D => has to match
and so on
Is there a "standard" way to run such tests?

4.5 IPV6
---------
Currently the fireflier module is IPv4 only, is there anything I have to look 
out for when I "port" it to ipv6?
Should I do this now? I see that ip|ip6|arp_tables are being moved to 
x_tables, does it mean that ipv4 and ipv6 are going to be "unified"?
Do I have to do anything to support x_tables?

5. Use of the kernel API [!]
----------------------

Are the functions I used in the 2 modules part of a stable kernel API? Did I 
use functions/structures that a driver isn't supposed to use?
Are there any plans to remove a feature I used in my modules?

P.S.: there are hard coded path in some files, that is going to be fixed in a 
later version

I am waiting for your advice/suggestions/comments.

(note: although some of the pages on the wiki were last updated on April the 
1st, they are not an April's fool joke)

Thanks in advance,
Edwin

[1] http://www.uwsg.iu.edu/hypermail/linux/kernel/0602.2/0701.html
[2] http://www.uwsg.iu.edu/hypermail/linux/kernel/0602.2/0709.html
[3] http://www.uwsg.iu.edu/hypermail/linux/kernel/0602.2/0725.html
[4] http://www.uwsg.iu.edu/hypermail/linux/kernel/0602.2/0792.html
[5] http://www.uwsg.iu.edu/hypermail/linux/kernel/0602.2/1310.html
[6] http://fireflier.isgeeky.com/wiki/Kernel_module
[7]http://fireflier.isgeeky.com/wiki/Kernel_module#Multiple_programs_accessing_a_socket
[8] http://fireflier.isgeeky.com/wiki/Ipt_fireflier_test
[9]http://www.derkeiler.com/Mailing-Lists/securityfocus/bugtraq/2004-12/0390.html
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux