On Aug 12, 2007, at 15:41:46, Casey Schaufler wrote:
If you have no interest in categorizing the SELinux access vectors,
then how do you expect to categorize the LSM hooks, which are almost
1-to-1 mapped with the SELinux access vectors?
Well yes, but a simplified policy is useless if it uses no LSM
hooks. I will write you a Perl script which will generate a complete
and functionally equivalent SELinux policy (assuming I have enough
free time) given a file with your policy language. But I can do this
if and only if you tell me which of the SELinux access vectors you
care about (In other words, which of the LSM hooks you want to
require "read", "write", or "execute" privileges for). With such a
little script you could write all the "simplified" policy you want,
without having to change the kernel code at all.
My point is your policy format is SO simple it doesn't even need the
SELinux MLS code to handle it. From the way you've described it the
base policy (~200 lines) would be *identical* regardless of the
entries in your policy language, and the rest could be generated by a
script directly from the "C Unclass rx"-type stuff.
Yes, precisely. For most of that functionality there are existing
attributes and types defined in the reference policy to make custom
policy much easier. Furthermore, there are interface files which
allow me to say something like "Let this program spawn an Apache
daemon in the right domain" with a single line. If I only want to do
that when the "httpd" module is loaded I can put the line in an
"optional" block. A policy for a basic network daemon with a couple
log files, a config file, and a little database is all of 30 lines,
maybe 50 if you throw in comments.
No, generally the only reason to use MAC is when it's security-
critical (system compromise, classified data, critical
infrastructure, etc). Denying users access to games during the
workday is hardly "security-critical". If that system's CPU time was
exclusively needed for a life support machine during the day then
maybe, but that's what renice or realtime scheduling are for and why
the hell are you installing games on a heart monitor?
How does it require more forethought? When I want to turn it on, I
write and load the 5 line policy then add the cronjobs. Yours
involves giving cron unconditional permission to write to your
security database (always a bad idea) and then adding similar cronjobs.
Hmm, looking at this again the current policy language doesn't have a
way of delegating access to boolean values, so there's no way to let
cron directly poke at booleans right now. You could do it with this
shell script:
#! /bin/sh
now=$(date +'%H%M')
if [ 800 -le "$now" -a 1700 -ge "$now" ]; then
setsebool can_play_games false
else
setsebool can_play_games true
fi
Label that script as games_changer_exec_t then use this bit of policy
type_transition cron_t games_changer_exec_t:process games_changer_t;
can_setbool(games_changer_t);
Once you have written a policy specific to the game you want to allow
or disallow, you would just put that policy inside of the
conditional. As a simple policy example for the ping program (from
an older refpolicy, now a bit out of date, but still useful as an
example):
## The ping domain
type ping_t, domain, privlog;
## Daemons, sysadmins, and users may assume the ping type if allowed
below
role system_r types ping_t;
role sysadm_r types ping_t;
in_user_role(ping_t)
## The ping binary
type ping_exec_t, file_type, sysadmfile, exec_type;
## Allow the sysadmin and init scripts to run ping
domain_auto_trans(sysadm_t, ping_exec_t, ping_t)
domain_auto_trans(initrc_t, ping_exec_t, ping_t)
## Boolean controlling user access to ping
bool user_ping false;
if (user_ping) {
domain_auto_trans(unpriv_userdomain, ping_exec_t, ping_t)
allow ping_t { ttyfile ptyfile }:chr_file rw_file_perms;
}
## Allow ping to do what it needs to do
uses_shlib(ping_t)
can_network(ping_t)
can_ypbind(ping_t)
## Allow additional permissions that ping needs to operate
allow ping_t etc_t:file { getattr read };
allow ping_t self:unix_stream_socket create_socket_perms;
allow ping_t self:rawip_socket { create ioctl read write bind getopt
setopt };
allow ping_t netif_type:netif { rawip_send rawip_recv };
allow ping_t node_type:node { rawip_send rawip_recv };
allow ping_t self:capability { net_raw setuid };
## Allow ping to poke at the terminal
allow ping_t admin_tty_type:chr_file rw_file_perms;
allow ping_t { userdomain privfd kernel_t }:fd use;
## Ping wants to get FS attributes and look in /var but doesn't need to
dontaudit ping_t fs_t:filesystem getattr;
dontaudit ping_t var_t:dir search;
It should be pretty clear what every part of the policy is there for;
basically that's the minimum necessary set of permissions for ping to
run, with an optional boolean to control user pings. There's also a
macro to give your arbitrary process the ability to run ping, such as
for the "heartbeat" daemon for example.
Well, under SELinux, all 3 of those processes go through the special
purpose PAM module to get their labels changed. Are you planning to
modify *every* daemon to have special type-changing code? Hell, most
don't even have setuid/chroot support and that's all of 15 lines of
code and is supported in every UNIX/Linux distro released in the last
10 years (or more). Besides, why allow the program (say, "ping") to
change its own label when the policy could forcibly change it for
you. The label change is NOT just to *give* permissions, it's also
to take them away. For example, when I run "ping", the process gains
raw network access but loses access to almost every user file and
disables LD_PRELOAD, etc, making it a thousand times harder to
compromise it from the inside too.
Sorry for being unclear. Assume s/type/label/g; the question still
stands.
"People have been burning witches for decades, that must be the right
thing to do"
The fact that something is commonly done does not make it right,
especially when there is a significantly more secure alternative
available.
The beauty of fine granularity is that you can ignore it without
changing code. If you don't want to use the "user" and "role"
portions, then just set them to always be "allusers" and "allroles"
and be done with it. If you don't want MLS then just define one
sensitivity (s0) and no categories. Likewise if want your system to
use only 8 types then only define 8 types. It's just that easy!
Admittedly your policy can't then deal with most of the real-world
situations (like logging in or running the "passwd" command), but
that's your choice.
Which part do you think is bad? The fact that the policy is
guaranteed to be non-overrideable, or the fact that you can even
prevent changing the security policy from the policy? If you really
want a root-hole in the policy then you can write one, see the
"unconfined_t" in the "targeted" policy.
So how would you secure a system moving data between 3 TS/SCI
compartments and a Secret network? You can say "no one wanted
to...", but we have a couple million dollars worth of business that
says they do.
"Linux privilege mechanisms" covers no less than 20,000 lines of
code, including DAC, capabilities, LSM, namespaces, keyrings, and
more. Please be more specific here.
It still is in SELinux too. The only difference is that in SELinux
*all* of the possible ways to downgrade classified information are
listed for you in the policy file for easy analysis; one of the most
common complaints about SUID binaries in UNIX is that they aren't all
listed in one place for easy auditing. Moreover, you can see exactly
how the information may be downgraded. For example, in one policy I
use, I can prove that specific components of our guard software have
permission to move data from a category such as "Secret:NukeTesting"
to just "Secret", but cannot access "TopSecret". I can also verify
that the program itself cannot modify the levels it has access to,
even though it does have permissions to move data between them. It
doesn't make you immune to flaws, but it lets you vastly limit the
damage any given flaw can accomplish.
The WHOLE POINT of a mandatory access control system is to protect
against *poorly* written programs. If we can verify the kernel (~8
million lines), and the policy (~8,000 lines), then we've saved
ourselves from having to audit all of userspace (~80+ million
lines). Seems a worthy goal to me.
And by extension you have no way of saying "The apache log files
can't be modified after they are written." That feature is part of
virtually every MAC system anybody's ever made, precisely because you
can't really trust audit logs without it.
Firstly because it's interesting, and secondly because it's related
to my work (which of course comes back to point 1) :-D.
Cheers,
Kyle Moffett
-