Smack: Simplified Mandatory Access Control Kernel
Subsystems (2)
Casey Schaufler
maintainerPATCH 1/1 Smack: Simplified Mandatory Access Control Kernel
From: Casey Schaufler <[email protected]>
Smack is the Simplified Mandatory Access Control Kernel.
Smack implements mandatory access control (MAC) using labels attached to tasks and data containers, including files, SVIPC, and other tasks. Smack is a kernel based scheme that requires an absolute minimum of application support and a very small amount of configuration data.
Smack is implemented as a clean LSM. It requires no external code changes and the patch modifies only the Kconfig and Makefile in the security directory. Smack uses extended attributes and provides a set of general mount options, borrowing technics used elsewhere. Smack uses netlabel for CIPSO labeling. Smack provides a pseudo-filesystem smackfs that is used for manipulation of system Smack attributes.
Smack provides mandatory access controls based on the label attached to a task and the label attached to the object it is attempting to access. Smack labels are deliberately short (1-7 characters) text strings. Single character labels using special characters are reserved for system use. The only operation applied to Smack labels is equality comparison. No wildcards or expressions, regular or otherwise, are used.
A file always gets the Smack label of the task that created it.
Smack defines and uses these labels:
"*" - pronounced "star"
"_" - pronounced "floor"
"^" - pronounced "hat"
"?" - pronounced "huh"The access rules enforced by Smack are, in order:
1. Any access requested by a task labeled "*" is denied.
2. A read or execute access requested by a task labeled "^" is permitted.
3. A read or execute access requested on an object labeled "_" is permitted.
4. Any access requested on an object labeled "*" is permitted.
5. Any access requested by a task on an object with the same label is permitted.
6. Any access requested that is explicitly defined in the loaded rule set is permitted.
7. Any other access is denied.
Rules may be explicitly defined by writing subject,object,access triples to /smack/load.
Smack rule sets can be easily defined that describe Bell&LaPadula sensitivity, Biba integrity, and a variety of interesting configurations. Smack rule sets can be modified on the fly to accomodate changes in the operating environment or even the time of day.
Some practical use cases:
Hierarchical levels. The less common of the two usual uses for MLS systems is to define hierarchical levels, often unclassified, confidential, secret, and so on. To set up smack to support this, these rules could be defined:
C Unclass rx S C rx S Unclass rx TS S rx TS C rx TS Unclass rx
A TS process can read S, C, and Unclass data, but cannot write it. An S process can read C and Unclass. Note that specifying that TS can read S and S can read C does not imply TS can read C, it has to be explicitly stated.
Non-hierarchical categories. This is the more common of the usual uses for an MLS system. Since the default rule is that a subject cannot access an object with a different label no access rules are required to implement compartmentalization.
A case that the Bell & LaPadula policy does not allow is demonstrated with this Smack access rule:
A case that Bell&LaPadula does not allow that Smack does:
ESPN ABC r
ABC ESPN rOn my portable video device I have two applications, one that shows ABC programming and the other ESPN programming. ESPN wants to show me sport stories that show up as news, and ABC will only provide minimal information about a sports story if ESPN is covering it. Each side can look at the other's info, neither can change the other. Neither can see what FOX is up to, which is just as well all things considered.
Another case that I especially like:
SatData Guard w
Guard Publish w
A program running with the Guard label opens a UDP socket and accepts messages sent by a program running with a SatData label. The Guard program inspects the message to ensure it is wholesome and if it is sends it to a program running with the Publish label. This program then puts the information passed in an appropriate place. Note that the Guard program cannot write to a Publish file system object because file system semanitic require read as well as write.
The four cases (categories, levels, mutual read, guardbox) here are all quite real, and problems I've been asked to solve over the years. The first two are easy to do with traditonal MLS systems while the last two you can't without invoking privilege, at least for a while.
--- security/Kconfig | 1 security/Makefile | 2 security/smack/Kconfig | 10 security/smack/Makefile | 8 security/smack/smack.h | 246 +++++ security/smack/smack_access.c | 113 ++ security/smack/smack_lsm.c | 1989 ++++++++++++++++++++++++++++++++++++++++++ security/smack/smackfs.c | 994 ++++++++++++++++++++ 8 files changed, 3363 insertions(+)
security/Kconfig +1 -0
@@ -94,6 +94,7 @@ config SECURITY_ROOTPLUG If you are unsure how to answer this question, answer N. source security/selinux/Kconfig +source security/smack/Kconfig endmenu
security/Makefile +2 -0
@@ -4,6 +4,7 @@ obj-$(CONFIG_KEYS) += keys/ subdir-$(CONFIG_SECURITY_SELINUX) += selinux +subdir-$(CONFIG_SECURITY_SMACK) += smack # if we don't select a security model, use the default capabilities ifneq ($(CONFIG_SECURITY),y)
@@ -14,5 +15,6 @@ endif obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o # Must precede capability.o in order to stack properly. obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o +obj-$(CONFIG_SECURITY_SMACK) += commoncap.o smack/built-in.o obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o
security/smack/Kconfig +10 -0
@@ -0,0 +1,10 @@ +config SECURITY_SMACK + bool "Simplified Mandatory Access Control Kernel Support" + depends on NETLABEL && SECURITY_NETWORK + default n + help + This selects the Simplified Mandatory Access Control Kernel. + SMACK is useful for sensitivity, integrity, and a variety + of other madatory security schemes. + If you are unsure how to answer this question, answer N. +
security/smack/Makefile +8 -0
@@ -0,0 +1,8 @@ +# +# Makefile for the SMACK LSM +# + +obj-$(CONFIG_SECURITY_SMACK) := smack.o + +smack-y := smack_lsm.o smack_access.o smackfs.o +
security/smack/smack_access.c +113 -0
113 lines not on this page · raw message
security/smack/smackfs.c +994 -0
994 lines not on this page · raw message
security/smack/smack.h +246 -0
246 lines not on this page · raw message
security/smack/smack_lsm.c +1989 -0
1,609 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
Quoted 1 line
+extern struct
smk_list_entry*smack_list;
any reason to invent your own list rather than just using list.h?
security/smack/smackfs.c line 23
Quoted 7 lines
security/smack/smackfs.c +7
-0+ +#include <linux/kernel.h> +#include <linux/vmalloc.h> +#include <linux/security.h> +#include <linux/mutex.h> +#include <net/netlabel.h> +#include "../../net/netlabel/netlabel_domainhash.h"
can't you move this header to include/ instead?
security/smack/smackfs.c line 240
Quoted 5 lines
security/smack/smackfs.c +5
-0+ +static struct file_operations smk_load_ops = { + .read = smk_read_load, + .write = smk_write_load, +};
make that a const please
security/smack/smackfs.c line 279
Quoted 9 lines
security/smack/smackfs.c +9
-0+ + doip =kmalloc (sizeof (struct cipso_v4_doi ),GFP_KERNEL ); +if (doip ==NULL ) +panic ("smack: Failed to initialize cipso DOI.\n" ); + doip->map.std =NULL ; + + ndmp =kmalloc (sizeof (struct netlbl_dom_map ),GFP_KERNEL ); +if (ndmp ==NULL ) +panic ("smack: Failed to initialize cipso ndmp.\n" );
is panic() really the right thing here? It's usually considered quite rude ;)
security/smack/smackfs.c line 478
Quoted 4 lines
security/smack/smackfs.c +4
-0+static struct file_operations smk_cipso_ops = { + .read = smk_read_cipso, + .write = smk_write_cipso, +};
another candidate for const
Review
Quoted 2 lines
(quoted diff) +2
-0+static void *smackfs_follow_link(struct dentry *dentry, struct nameidata *nd) +{
this one deserves a comment; are you implementing magic symlinks here?
Casey Schaufler
maintainerQuoted 3 lines · --- Arjan van de Ven
Quoted 1 line
+extern struct
smk_list_entry*smack_list;any reason to invent your own list rather than just using
list.h?
The list.h mechanisms are fine, but heavier than I require. I'm willing to give in on it, but I don't see an advantage.
Quoted 9 lines
security/smack/smackfs.c line 23
Quoted 7 lines
security/smack/smackfs.c +7
-0+ +#include <linux/kernel.h> +#include <linux/vmalloc.h> +#include <linux/security.h> +#include <linux/mutex.h> +#include <net/netlabel.h> +#include "../../net/netlabel/netlabel_domainhash.h" can't you move this header to
include/instead?
Paul Moore, the developer of netlabel, promised to work out the right solution for this with me at a future date. He doesn't want to move the header, and I respect that.
Quoted 7 lines
security/smack/smackfs.c line 240
Quoted 5 lines
security/smack/smackfs.c +5
-0+ +static struct file_operations smk_load_ops = { + .read = smk_read_load, + .write = smk_write_load, +};make that a const please
Will do.
Quoted 5 lines
Quoted 5 lines
security/smack/smackfs.c +5
-0+ + doip =kmalloc (sizeof (struct cipso_v4_doi ),GFP_KERNEL ); +if (doip ==NULL ) +panic ("smack: Failed to initialize cipso DOI.\n" ); + doip->map.std =NULL ;
Quoted 8 lines
security/smack/smackfs.c line 279
Quoted 4 lines
security/smack/smackfs.c +4
-0+ + ndmp =kmalloc (sizeof (struct netlbl_dom_map ),GFP_KERNEL ); +if (ndmp ==NULL ) +panic ("smack: Failed to initialize cipso ndmp.\n" );is
panic()really the right thing here? It's usually considered quite rude ;)
It's really early in start-up and if you're out of memory at that point you are not going very far into the future.
Quoted 6 lines
security/smack/smackfs.c line 478
Quoted 4 lines
security/smack/smackfs.c +4
-0+static struct file_operations smk_cipso_ops = { + .read = smk_read_cipso, + .write = smk_write_cipso, +};another candidate for const
Will do that, too.
Quoted 6 lines
Quoted 1 line
+static void *smackfs_follow_link(struct dentry *dentry, struct nameidata
*nd)
Quoted 1 line
+{
this one deserves a comment; are you implementing magic symlinks here?
Yup.
Casey Schaufler
[email protected]
Quoted 11 lines · Casey Schaufler (on Sat, 11 Aug 2007 12:56:42 -0700 (PDT)) wrote:
Quoted 8 lines · --- Arjan van de Ven
security/smack/smackfs.c line 23
Quoted 6 lines
security/smack/smackfs.c +6
-0+#include <linux/kernel.h> +#include <linux/vmalloc.h> +#include <linux/security.h> +#include <linux/mutex.h> +#include <net/netlabel.h> +#include "../../net/netlabel/netlabel_domainhash.h" can't you move this header to
include/instead?
Quoted 3 lines
Paul Moore, the developer of netlabel, promised to work out the right solution for this with me at a future date. He doesn't want to move the header, and I respect that.
foo.c has
#include "netlabel_domainhash.h"
Makefile has CFLAGS_foo.o += -I$(srctree)/net/netlabel
I prefer to use -I $(srctree)/net/netlabel for readability but '-I ' breaks on SuSE builds for some reason that I cannot be bothered working out. -I$(srctree)/net/netlabel works.
Quoted 13 lines
Quoted 4 lines
Quoted 4 lines
security/smack/smackfs.c +4
-0+ doip =kmalloc (sizeof (struct cipso_v4_doi ),GFP_KERNEL ); +if (doip ==NULL ) +panic ("smack: Failed to initialize cipso DOI.\n" ); + doip->map.std =NULL ;Quoted 8 lines
security/smack/smackfs.c line 279
Quoted 4 lines
security/smack/smackfs.c +4
-0+ + ndmp =kmalloc (sizeof (struct netlbl_dom_map ),GFP_KERNEL ); +if (ndmp ==NULL ) +panic ("smack: Failed to initialize cipso ndmp.\n" );is
panic()really the right thing here? It's usually considered quite rude ;)
Quoted 2 lines
It's really early in start-up and if you're out of memory at that point you are not going very far into the future.
Not to mention that you might end up running with an insecure system. Security must be failsafe.
Quoted 1 line · Casey Schaufler
Smack implements mandatory access control (MAC) using labels attached to tasks and data containers, including files, SVIPC, and other tasks. Smack is a kernel based scheme that requires an absolute minimum of application support and a very small amount of configuration data.
For starters, we would appear to already have a very capable labelling system which can do *all* of this, completely and without exceptions, in a much more flexible way. Admittedly it's more complicated, but one does have to have complexity in order to handle everything from CD burning in X, to Apache daemons, to only allowing Top-Secret-level logins over the IPsec tunnel on the Top Secret network, etc. Do you see any particular reason this couldn't be implemented as a very *very* simplified SELinux wrapper? For example, this set of rules basically defines your described "read-vs-write-vs-exec" policy as best I can figure out:
user uu roles rr;
role rr types { star floor hat huh };
define(r',
allow $1 $2:file { read getattr };
allow $1 $2:socket { read getattr getopt recvfrom recv_msg }; allow $1 $2:ipc { getattr read associate unix_read };
## List of more "read" allow rules for different types of objects... ## ')
define(w',
allow $1 $2:file { ioctl write create setattr lock append unlink link rename swapon quotaon mounton };
allow $1 $2:socket { ioctl write create setattr lock append bind connect listen accept setopt shutdown sendto send_msg name_bind }; allow $1 $2:ipc { create destroy setattr write unix_write };
## List of more "write" allow rules for different types of objects... ##
')
define(x',
allow $1 $2:file { execute };
allow $1 $2:dir { search };
## List of more "execute" allow rules for different types of objects... ## ')
And now to describe these rules:
Quoted 8 lines
Smack defines and uses these labels:
"*" - pronounced "star"
"_" - pronounced "floor"
"^" - pronounced "hat"
"?" - pronounced "huh"The access rules enforced by Smack are, in order:
Quoted 11 lines
1. Any access requested by a task labeled "*" is denied.
2. A read or execute access requested by a task labeled "^" is permitted.
3. A read or execute access requested on an object labeled "_" is permitted.
4. Any access requested on an object labeled "*" is permitted.
5. Any access requested by a task on an object with the same label is permitted.
6. Any access requested that is explicitly defined in the loaded rule set is permitted.
7. Any other access is denied.
## These are calls to the above macros which plug in the necessary arguments r(hat, {*})x(hat, {*})r(~{star}, floor)x(~{star}, floor)r(~{star}, star)w(~{star}, star)x(~{star}, star)r(~{star}, self)w(~{star}, self)x(~{star}, self)
## Include your "loaded rule set" here ##
Quoted 1 line
Rules may be explicitly defined by writing subject,object,access triples to /smack/load.
Maybe worth a little utility to convert a file full of "subject,object,access" triples to an appropriate SELinux policy would be appropriate?
Quoted 1 line
Smack rule sets can be easily defined that describe Bell&LaPadula sensitivity, Biba integrity, and a variety of interesting configurations. Smack rule sets can be modified on the fly to accomodate changes in the operating environment or even the time of day.
SELinux can do this as well. It even includes support for conditional policy:
bool foo_can_do_logging true;
if (foo_can_do_logging) {
allow foo_t foo_log_t:file { create read getattr append };
}The SELinux tools also have support for policy modules, so you can extend the policy without modifying the base system. Plus the stuff has been very heavily tested and even supports X (as soon as the beta X code gets improved and merged in the upstream X.org codebase).
Quoted 11 lines
Some practical use cases:
Hierarchical levels. The less common of the two usual uses for MLS systems is to define hierarchical levels, often unclassified, confidential, secret, and so on. To set up smack to support this, these rules could be defined:
C Unclass rx S C rx S Unclass rx TS S rx TS C rx TS Unclass rx
Quoted 4 lines
A TS process can read S, C, and Unclass data, but cannot write it. An S process can read C and Unclass. Note that specifying that TS can read S and S can read C does not imply TS can read C, it has to be explicitly stated.
The big problem here is the duplication. Say you have a locked-down Apache configuration and you want to run 2 apache processes, one at Secret and one at Top-Secret. Under your model you have to copy-paste the policy and make sure to apply fixes/changes to both places. Under SELinux, you can have processes as:
system_u:system_r:httpd_t:Secret:UFOSightings,AlienDissection
system_u:system_r:httpd_t:TopSecret:NukeTests
They can only read and write objects for which multiple conditions are true: First, the object must match the Bell-Padula model with respect to the sensitivities and categories ("Secret:UFOSightings,AlienDissection", etc) *and* it must also be objects that httpd_t is allowed to read/write. That also includes network traffic, and your firewall can appropriately label data over a given IPsec link as one classification level while data over the raw network is labeled as another. Oh, and you can tweak the MLS constraints of the Bell-Padula model as necessary too.
Quoted 6 lines
Another case that I especially like:
SatData Guard w
Guard Publish wA program running with the Guard label opens a UDP socket and accepts messages sent by a program running with a SatData label. The Guard program inspects the message to ensure it is wholesome and if it is sends it to a program running with the Publish label. This program then puts the information passed in an appropriate place. Note that the Guard program cannot write to a Publish file system object because file system semanitic require read aswell as write.
This is exactly what my company does, but the ability to restrict *exactly* what mechanisms are used is important. You restrict against file-system access implicitly, whereas SELinux does it explicitly:
allow foo_t foo_sock_t:socket { .... };
versus:
allow foo_t foo_log_t:file { ... };
With SELinux you can also allow your program to create files labelled as "log files" in one directory in one type and "transfer files" in another directory in a completely different type.
Quoted 1 line
The four cases (categories, levels, mutual read, guardbox) here are all quite real, and problems I've been asked to solve over the years. The first two are easy to do with traditonal MLS systems while the last two you can't without invoking privilege, at least for a while.
I'm proud to say that the software of the company I work for does not need any extra privilege at all (aside from binding to ports <1024) to run under SELinux with strict MLS. Under Trusted Solaris and such we needed all sorts of dirty privilege hacks to relabel the files consistently, but under SELinux the policy does all the relabeling for us, we don't need to do a thing.
Cheers,
Kyle Moffett
Casey Schaufler
maintainerQuoted 9 lines · --- Kyle Moffett
Quoted 5 lines · Casey Schaufler
Smack implements mandatory access control (MAC) using labels attached to tasks and data containers, including files, SVIPC, and other tasks. Smack is a kernel based scheme that requires an absolute minimum of application support and a very small amount of configuration data.
For starters, we would appear to already have a very capable labelling system
I am not going to argue that SELinux is not a capable labelling system. SELinux is a fine implementation of of Type Enforcement.
Quoted 2 lines
which can do *all* of this, completely and without exceptions,
That's quite a strong assertion.
Quoted 1 line
in a much more flexible way.
Indeed, SELinux provides tremendous flexibility.
Quoted 1 line
Admittedly it's more complicated,
Yes, it is.
Quoted 4 lines
but one does have to have complexity in order to handle everything from CD burning in X, to Apache daemons, to only allowing Top-Secret-level logins over the IPsec tunnel on the Top Secret network, etc.
I do not agree with you. The MLS systems from the 1990's could do all that (except the IPsec tunnel, the function of which was preceeded by TSIG interfaces and protocols) without the complexity required by SELinux policy.
Quoted 2 lines
Do you see any particular reason this couldn't be implemented as a very *very* simplified SELinux wrapper?
I would be interested to see the attempt made, but I have no interest in doing so myself. I think that some of the reasons will come out as we progress through your examples.
Quoted 6 lines
For
example, this set of rules basically defines your described "read-vs- write-vs-exec" policy as best I can figure out:user uu roles rr;
Quoted 8 lines
role rr types { star floor hat huh };
define(
r',
allow $1 $2:file { read getattr };
allow $1 $2:socket { read getattr getopt recvfromrecv_msg}; allow $1 $2:ipc { getattr read associateunix_read};
## List of more "read" allow rules for different types of objects... ## ')
It would be instructive for those who are not well versed in the nuances of SELinux policy if you actually spelled out the whole thing, rather than using "## and more ##". Part of the point of Smack is the makeup of the full list that would be required here.
Quoted 8 lines
define(
w',
allow $1 $2:file { ioctl write create setattr lock append unlink link rename swapon quotaon mounton };
allow $1 $2:socket { ioctl write create setattr lock append bind connect listen accept setopt shutdown sendtosend_msgname_bind}; allow $1 $2:ipc { create destroy setattr writeunix_write}; ## List of more "write" allow rules for different types of objects... ## ')
Again, I suggest you present the complete list.
Quoted 6 lines
define(
x',
allow $1 $2:file { execute };
allow $1 $2:dir { search };
## List of more "execute" allow rules for different types of objects... ##
')
Here too.
Quoted 22 lines
And now to describe these rules:
Quoted 8 lines
Smack defines and uses these labels:
"*" - pronounced "star"
"_" - pronounced "floor"
"^" - pronounced "hat"
"?" - pronounced "huh"The access rules enforced by Smack are, in order:
Quoted 11 lines
1. Any access requested by a task labeled "*" is denied.
2. A read or execute access requested by a task labeled "^" is permitted.
3. A read or execute access requested on an object labeled "_" is permitted.
4. Any access requested on an object labeled "*" is permitted.
5. Any access requested by a task on an object with the same label is permitted.
6. Any access requested that is explicitly defined in the loaded rule set is permitted.
7. Any other access is denied.
Quoted 13 lines
## These are calls to the above macros which plug in the necessary arguments
r(hat, {*})x(hat, {*})r(~{star}, floor)x(~{star}, floor)r(~{star}, star)w(~{star}, star)x(~{star}, star)r(~{star}, self)w(~{star}, self)x(~{star}, self)
## Include your "loaded rule set" here ##
What would that look like?
Quoted 6 lines
Quoted 2 lines
Rules may be explicitly defined by writing subject,object,access triples to /smack/load.
Maybe worth a little utility to convert a file full of "subject,object,access" triples to an appropriate SELinux policy would be appropriate?
Maybe. It would at least be educational for comparisons by those looking to choose between the schemes.
Quoted 6 lines
Quoted 5 lines
Smack rule sets can be easily defined that describe Bell&LaPadula sensitivity, Biba integrity, and a variety of interesting configurations. Smack rule sets can be modified on the fly to accomodate changes in the operating environment or even the time of day.
Quoted 7 lines
SELinux can do this as well. It even includes support for conditional policy:
bool
foo_can_do_loggingtrue;if (foo_can_do_logging) { allow foo_t foo_log_t:file { create read getattr append }; }
You have to build the booleans into the policy in advance.
Quoted 2 lines
The SELinux tools also have support for policy modules, so you can extend the policy without modifying the base system.
And that's a good thing, but you still have to compile and reload your policy, and maybe relabel you filesystem when you do so.
Quoted 1 line
Plus the stuff has been very heavily tested
It does have the advantage of maturity.
Quoted 2 lines
and even supports X (as soon as the beta
X code gets improved and merged in the upstream X.org codebase).
The MLS systems of the 1990s did that, and having done MLS X myself I can assure you that although it has an interesting set of issues to address (object definition in particular) and a programming model that is very different from the kernel it's not that big a deal.
Quoted 19 lines
Quoted 14 lines
Some practical use cases:
Hierarchical levels. The less common of the two usual uses for MLS systems is to define hierarchical levels, often unclassified, confidential, secret, and so on. To set up smack to support this, these rules could be defined:
C Unclass rx S C rx S Unclass rx TS S rx TS C rx TS Unclass rxQuoted 4 lines
A TS process can read S, C, and Unclass data, but cannot write it. An S process can read C and Unclass. Note that specifying that TS can read S and S can read C does not imply TS can read C, it has to be explicitly stated.
Quoted 5 lines
The big problem here is the duplication. Say you have a locked-down Apache configuration and you want to run 2 apache processes, one at Secret and one at Top-Secret. Under your model you have to copy- paste the policy and make sure to apply fixes/changes to both places.
I'm sorry, but I don't understand your point at all.
Quoted 4 lines
Under SELinux, you can have processes as:
system_u:system_r:httpd_t:Secret:UFOSightings,AlienDissection system_u:system_r:httpd_t:TopSecret:NukeTests
Quoted 9 lines
They can only read and write objects for which multiple conditions are true: First, the object must match the Bell-Padula model with respect to the sensitivities and categories ("Secret:UFOSightings,AlienDissection", etc) *and* it must also be objects that
httpd_tis allowed to read/write. That also includes network traffic, and your firewall can appropriately label data over a given IPsec link as one classification level while data over the raw network is labeled as another. Oh, and you can tweak the MLS constraints of the Bell-Padula model as necessary too.
Ok.
Quoted 18 lines
Quoted 5 lines
Another case that I especially like:
SatData Guard w
Guard Publish wQuoted 8 lines
A program running with the Guard label opens a UDP socket and accepts messages sent by a program running with a SatData label. The Guard program inspects the message to ensure it is wholesome and if it is sends it to a program running with the Publish label. This program then puts the information passed in an appropriate place. Note that the Guard program cannot write to a Publish file system object because file system semanitic require read aswell as write.
This is exactly what my company does, but the ability to restrict *exactly* what mechanisms are used is important. You restrict against file-system access implicitly, whereas SELinux does it explicitly:
Quoted 7 lines
allow foo_t foo_sock_t:socket { .... }; versus: allow foo_t foo_log_t:file { ... };With SELinux you can also allow your program to create files labelled as "log files" in one directory in one type and "transfer files" in another directory in a completely different type.
I would be very interested to see the policy that your guard box uses.
Quoted 9 lines
Quoted 5 lines
The four cases (categories, levels, mutual read, guardbox) here are all quite real, and problems I've been asked to solve over the years. The first two are easy to do with traditonal MLS systems while the last two you can't without invoking privilege, at least for a while.
I'm proud to say that the software of the company I work for does not need any extra privilege at all (aside from binding to ports <1024) to run under SELinux with strict MLS.
That is an aspect of SELinux that has its dark side. While you are not explicitly violating a policy (e.g. requiring a capability) you are doing things that some of us would argue ought to require a capability. SELinux integrates privilege into the policy mechanism.
Smack does not. Smack is designed to use traditional Linux mechanisms for privilege.
Quoted 4 lines
Under Trusted Solaris and such
we needed all sorts of dirty privilege hacks to relabel the files consistently, but under SELinux the policy does all the relabeling for us, we don't need to do a thing.
Yeah. Well, you won't like Smack then. Implicit relabeling of processes and files does not happen. This is a major philisophical difference.
Casey Schaufler
[email protected]
Quoted 3 lines · Casey Schaufler
Quoted 1 line
[SELinux...] which can do *all* of this, completely and without exceptions,
That's quite a strong assertion.
It is, but I stand by it. If anyone can point out some portion of this which *cannot* be implemented as SELinux policy I will humbly step completely out of this discussion.
Quoted 3 lines
Quoted 1 line
but one does have to have complexity in order to handle everything from CD burning in X, to Apache daemons, to only allowing Top-Secret-level logins over the IPsec tunnel on the Top Secret network, etc.
I do not agree with you. The MLS systems from the 1990's could do all that (except the IPsec tunnel, the function of which was preceeded by TSIG interfaces and protocols) without the complexity required by SELinux policy.
No, most/all of the MLS systems from the 1990s did not integrate Bell-LaPadula, Type Enforcement, and Role-Based-Access-Control together. In addition, none of the MLS systems from the 1990s had modifiable constraints the way SELinux does (for example I can modify the fundamental policy to allow a process whose domain has the "i_am_special" attribute to override the BLP model for certain target types in certain special situations, all depending on how I apply that attribute and those types).
Quoted 6 lines
Quoted 6 lines
For example, this set of rules basically defines your described "read-vs-write-vs-exec" policy as best I can figure out:
user uu roles rr;
role rr types { star floor hat huh };
Quoted 8 lines
Quoted 6 lines
define(
r',
allow $1 $2:file { read getattr };
allow $1 $2:socket { read getattr getopt recvfromrecv_msg}; allow $1 $2:ipc { getattr read associateunix_read};
## List of more "read" allow rules for different types of objects... ## ')It would be instructive for those who are not well versed in the nuances of SELinux policy if you actually spelled out the whole thing, rather than using "## and more ##". Part of the point of Smack is the makeup of the full list that would be required here.
Well, yes, but how exactly do you define "read", "write", and "execute" for the full list of SELinux object classes found here:
http://www.tresys.com/selinux/obj_perms_help.html
I was considering compiling the complete list, but such an exercise would take me at least an hour to do properly and which categories individual permissions should be placed in could be argued for weeks. The SELinux reference policy doesn't even completely qualify all of those things with MLS restrictions, and they're the ones who got the hooks implemented originally.
Specifically, do you classify the bind() syscall as a "read" or a "write" operation. How would you classify accept()? In order to support the full range of security controls that Linux has hooks for, you would need to identify a list of how to define "read", "write", and "execute" for every object-class in that massive list. Furthermore you would need to ensure that the definitions work for every process. From the variations between different portions of the SELinux ref policy, I contend that there is no single definition of "read", or "write" which works for all usages of a given object-class.
Quoted 36 lines
Quoted 22 lines
And now to describe these rules:
Quoted 8 lines
Smack defines and uses these labels:
"*" - pronounced "star"
"_" - pronounced "floor"
"^" - pronounced "hat"
"?" - pronounced "huh"The access rules enforced by Smack are, in order:
Quoted 11 lines
1. Any access requested by a task labeled "*" is denied.
2. A read or execute access requested by a task labeled "^" is permitted.
3. A read or execute access requested on an object labeled "_" is permitted.
4. Any access requested on an object labeled "*" is permitted.
5. Any access requested by a task on an object with the same label is permitted.
6. Any access requested that is explicitly defined in the loaded rule set is permitted.
7. Any other access is denied.Quoted 13 lines
## These are calls to the above macros which plug in the necessary arguments
r(hat, {*})x(hat, {*})r(~{star}, floor)x(~{star}, floor)r(~{star}, star)w(~{star}, star)x(~{star}, star)r(~{star}, self)w(~{star}, self)x(~{star}, self)
## Include your "loaded rule set" here ##
Quoted 1 line
What would that look like?
The same kind of thing as the r, x, and w above, with occasional "type my_type_t; role rr types my_type_t;" to declare a type before use. If you wanted to add support for attributes which apply to multiple types, you could put those after a comma after the "type my_type_t" portion of the type declaration.
Quoted 10 lines
Quoted 8 lines
Quoted 1 line
Smack rule sets can be easily defined that describe Bell&LaPadula sensitivity, Biba integrity, and a variety of interesting configurations. Smack rule sets can be modified on the fly to accomodate changes in the operating environment or even the time of day.
SELinux can do this as well. It even includes support for conditional policy:
bool
foo_can_do_loggingtrue;if (foo_can_do_logging) { allow foo_t foo_log_t:file { create read getattr append }; }You have to build the booleans into the policy in advance.
Well, yes, but a policy which completely ignores
Quoted 3 lines
Quoted 1 line
The SELinux tools also have support for policy modules, so you can extend the policy without modifying the base system.
And that's a good thing, but you still have to compile and reload your policy, and maybe relabel you filesystem when you do so.
What exactly prevents you from having to "reload" and "relabel the filesystem" when using your system? When you change the meaning of new types, you clearly would need to first reload the policy then relaunch programs or relabel files to take advantage of the new types, otherwise they would be categorically ignored by the system.
The only difference is the "compile" step, which converts from a reasonably modifiable language into a binary format which the kernel can efficiently parse. I suspect you'd get shot down instantly if you tried to stuff the policy compiler in the kernel too.
Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Some practical use cases:
Hierarchical levels. The less common of the two usual uses for MLS systems is to define hierarchical levels, often unclassified, confidential, secret, and so on. To set up smack to support this, these rules could be defined:
C Unclass rx S C rx S Unclass rx TS S rx TS C rx TS Unclass rx
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
A TS process can read S, C, and Unclass data, but cannot write it. An S process can read C and Unclass. Note that specifying that TS can read S and S can read C does not imply TS can read C, it has to be explicitly stated.
The big problem here is the duplication. Say you have a locked-down Apache configuration and you want to run 2 apache processes, one at Secret and one at Top-Secret. Under your model you have to copy-paste the policy and make sure to apply fixes/changes to both places.
I'm sorry, but I don't understand your point at all.
Ok, let's say you want to use your model to restrict Apache and MySQL running at the same classification level. You have to define combined labels, such as:
S_Apache S_MySQL rx
[...]
Now if you want to run an apache/mysql pair at TS, you have to copy all those rules and substitute "S_" with "TS_". With SELinux, you don't have to do anything other than define new labels for the secret-web-docs and the top-secret-web-docs folders, because the Apache *type-enforcement* policy is completely independent from the MLS levels. You can write a 5-line policy to label 2 slightly different initscripts with different range-transitions. The only difference between them will be the paths inside and the labels on them. The rest of apache's policy stays the same.
Quoted 8 lines
Quoted 6 lines
This is exactly what my company does, but the ability to restrict *exactly* what mechanisms are used is important. You restrict against file-system access implicitly, whereas SELinux does it explicitly:
allow foo_t foo_sock_t:socket { .... }; versus: allow foo_t foo_log_t:file { ... };With SELinux you can also allow your program to create files labelled as "log files" in one directory in one type and "transfer files" in another directory in a completely different type.
I would be very interested to see the policy that your guard box uses.
Unfortunately that's still considered company-proprietary information at the moment, although that's likely to change at some point in the future. We're not all that different from the httpd policies and similar stuff found in the SELinux "refpolicy" available from tresys' website.
Quoted 3 lines
Quoted 1 line
I'm proud to say that the software of the company I work for does not need any extra privilege at all (aside from binding to ports <1024) to run under SELinux with strict MLS.
That is an aspect of SELinux that has its dark side. While you are not explicitly violating a policy (e.g. requiring a capability) you are doing things that some of us would argue ought to require a capability. SELinux integrates privilege into the policy mechanism.
How does "moving data around a system" require root privileges? Why should it? Admittedly, moving data from "TopSecret" to "Secret" requires a process labeled with a range including at least "S-TS" *and* with the MLS "read-to-clearance" attribute, but you can be as stingy with that attribute as you like. That attribute is explicitly given its magic abilities in the mlsconstrain rules defined in the policy file itself, so it's also possible to do information flow analysis on it.
Quoted 5 lines
Smack does not. Smack is designed to use traditional Linux mechanisms for privilege.
Quoted 1 line
Under Trusted Solaris and such we needed all sorts of dirty privilege hacks to relabel the files consistently, but under SELinux the policy does all the relabeling for us, we don't need to do a thing.
Yeah. Well, you won't like Smack then. Implicit relabeling of processes and files does not happen. This is a major philisophical difference.
Here's an argument for why implicit labeling is good and explicit labeling is bad: If your process wants to label things explicitly it needs special privileges to do so, and it can abuse those privileges. Under SELinux the labeling is implicit *AND* the transitions are entirely within the policy. This means that you can do information flow analysis (as I described above) and it *ALSO* means that the program cannot possibly "abuse" its privileges because it has none. When httpd creates a file in its log directory that file is created with httpd_log_t and it is limited to being able to append to the file *only*. So when your apache gets compromised, the attacker has NO WAY to modify the logs, and you can prove this with a 60-second study of the policy. In fact, on my companies productions systems I can *PROVE* that the only way to get audit data out of the system is via a local TTY by interacting with system_u:object_r:local_login_t:SystemLow-SystemHigh to log in with a process of someluser:auditreview_r:auditreview_t:SystemHigh, which may read the audit files, or otherluser:auditadmin_r:auditadmin_t:SystemHigh, which may read and delete the audit files. I can even prove that no process on the system is allowed to modify the files after they are created, barring a kernel-level vulnerability.
So the implicit labeling of files actually restricts every process *FURTHER*. They no longer have even an inkling of a choice about file labeling, and that's a GOOD thing. The only remaining extension we need to really thoroughly lock down our systems is to allow last-path-component matching in type-transitions and allow rules (EG: When "vipw" creates a file named "passwd" in an "etc_t" directory, it is automatically labeled "etc_passwd_t") From what I understand Stephen Smalley and others are thinking that over even now. I'll do it myself as soon as I get time at work beyond prepping systems for shipping to clients if they haven't finished it by them.
Cheers,
Kyle Moffett
Casey Schaufler
maintainerQuoted 9 lines · --- Kyle Moffett
Quoted 4 lines · Casey Schaufler
Quoted 2 lines
[SELinux...] which can do *all* of this, completely and without exceptions,
That's quite a strong assertion.
It is, but I stand by it. If anyone can point out some portion of this which *cannot* be implemented as SELinux policy I will humbly step completely out of this discussion.
Ok. I accept that you believe that this.
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
but one does have to have complexity in order to handle everything from CD burning in X, to Apache daemons, to only allowing Top- Secret-level logins over the IPsec tunnel on the Top Secret network, etc.
Quoted 7 lines
Quoted 4 lines
I do not agree with you. The MLS systems from the 1990's could do all that (except the IPsec tunnel, the function of which was preceeded by TSIG interfaces and protocols) without the complexity required by SELinux policy.
No, most/all of the MLS systems from the 1990s did not integrate Bell- LaPadula, Type Enforcement, and Role-Based-Access-Control together.
Err, that wasn't the claim I was refuting. I was refuting the claim that performing those actions required complexity. The claim I was refering to said nothing about any of those features or anything about their integration.
Quoted 6 lines
In addition, none of the MLS systems from the 1990s had modifiable constraints the way SELinux does (for example I can modify the fundamental policy to allow a process whose domain has the "
i_am_special" attribute to override the BLP model for certain target types in certain special situations, all depending on how I apply that attribute and those types).
That's fine, but hardly relevent to the fact that the 1990's systems performed the list of functions.
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
For example, this set of rules basically defines your described "read-vs-write-vs-exec" policy as best I can figure out:
user uu roles rr;
role rr types { star floor hat huh };
define(
r',
allow $1 $2:file { read getattr };
allow $1 $2:socket { read getattr getopt recvfromrecv_msg}; allow $1 $2:ipc { getattr read associateunix_read}; ## List of more "read" allow rules for different types of objects... ##
')
Quoted 8 lines
Quoted 4 lines
It would be instructive for those who are not well versed in the nuances of SELinux policy if you actually spelled out the whole thing, rather than using "## and more ##". Part of the point of Smack is the makeup of the full list that would be required here.
Well, yes, but how exactly do you define "read", "write", and "execute" for the full list of SELinux object classes found here:
http://www.tresys.com/selinux/obj_perms_help.html
Smack is designed to treat objects as consistantly as is reasonable. The list of object classes defined by SELinux is great for a system designed to treat accesses with the highest possible granularity. This is not a design goal for Smack.
Quoted 4 lines
I was considering compiling the complete list, but such an exercise would take me at least an hour to do properly and which categories individual permissions should be placed in could be argued for weeks.
I will be happy to consider your arguement when you are willing to present the complete argument.
Quoted 3 lines
The SELinux reference policy doesn't even completely qualify all of those things with MLS restrictions, and they're the ones who got the hooks implemented originally.
That doesn't help your case any.
Quoted 2 lines
Specifically, do you classify the
bind()syscall as a "read" or a "write" operation.
Neither. Bind attaches a name (port number) to a socket (which is a data structure that is part of your process) from a global namespace. No objects are involved, hence no accesses.
Quoted 1 line
How would you classify
accept()?
I don't. Accept happens after a TCP connection has been established. The access control is all mediated long before the accept'er finds out about it.
Quoted 8 lines
In order to
support the full range of security controls that Linux has hooks for, you would need to identify a list of how to define "read", "write", and "execute" for every object-class in that massive list. Furthermore you would need to ensure that the definitions work for every process. From the variations between different portions of the SELinux ref policy, I contend that there is no single definition of "read", or "write" which works for all usages of a given object-class.
There certainly isn't in SELinux. I don't subscribe the the list of SELinux object classes. We can argue a long time over whether a socket is an object or not, and it won't help any real world application one bit.
Quoted 36 lines
Quoted 36 lines
Quoted 35 lines
And now to describe these rules:
Quoted 8 lines
Smack defines and uses these labels:
"*" - pronounced "star"
"_" - pronounced "floor"
"^" - pronounced "hat"
"?" - pronounced "huh"The access rules enforced by Smack are, in order:
Quoted 11 lines
1. Any access requested by a task labeled "*" is denied.
2. A read or execute access requested by a task labeled "^" is permitted.
3. A read or execute access requested on an object labeled "_" is permitted.
4. Any access requested on an object labeled "*" is permitted.
5. Any access requested by a task on an object with the same label is permitted.
6. Any access requested that is explicitly defined in the loaded rule set is permitted.
7. Any other access is denied.## These are calls to the above macros which plug in the necessary arguments
r(hat, {*})x(hat, {*})r(~{star}, floor)x(~{star}, floor)r(~{star}, star)w(~{star}, star)x(~{star}, star)r(~{star}, self)w(~{star}, self)x(~{star}, self)
## Include your "loaded rule set" here ##
Quoted 7 lines
Quoted 1 line
What would that look like?
The same kind of thing as the r, x, and w above, with occasional "type
my_type_t; role rr typesmy_type_t;" to declare a type before use. If you wanted to add support for attributes which apply to multiple types, you could put those after a comma after the "typemy_type_t" portion of the type declaration.
Well, I'm interested in seeing the actual code, not "the same kind of thing" as arguement.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 5 lines
Smack rule sets can be easily defined that describe Bell&LaPadula sensitivity, Biba integrity, and a variety of interesting configurations. Smack rule sets can be modified on the fly to accomodate changes in the operating environment or even the time of day.
SELinux can do this as well. It even includes support for conditional policy:
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
bool
foo_can_do_loggingtrue;if (foo_can_do_logging) { allow foo_t foo_log_t:file { create read getattr append }; }You have to build the booleans into the policy in advance.
Well, yes, but a policy which completely ignores
This sentence no verb.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
The SELinux tools also have support for policy modules, so you can extend the policy without modifying the base system.
And that's a good thing, but you still have to compile and reload your policy, and maybe relabel you filesystem when you do so.
What exactly prevents you from having to "reload" and "relabel the filesystem" when using your system?
Good question. First, changing Smack rules is no big deal. They can be added or changed one by one as required while the system is running, and there are uses that exploit that. One example is to put the label "Game" on certain programs and:
at 8:00am "Worker Game no"
at 5:00pm "Worker Game x"
Thus Worker processes can access Game files only during off hours.
As far as relabeling the file system goes, the rules apply to processes and objects, not to programs. The label on a program describes who can access it, it will run with the label of the process that exec's it. A change in the rules does not require a change to the labels on the file system for things to work according to the rules of engagement.
Quoted 4 lines
When you change the meaning of
new types, you clearly would need to first reload the policy then relaunch programs or relabel files to take advantage of the new types, otherwise they would be categorically ignored by the system.
I'm sorry, but again, I don't know what you mean by "changing the meaning of new types".
Quoted 3 lines
The only difference is the "compile" step, which converts from a reasonably modifiable language into a binary format which the kernel can efficiently parse.
I think you may be making assumptions about the behavior of Smack based on what SELinux does that don't hold. I hesitate to call a Smack rule list a language.
Quoted 2 lines
I suspect you'd get shot down instantly if
you tried to stuff the policy compiler in the kernel too.
Heavens, I should hope so!
Smack rule specifications are really really basic, just the subject label, the object label, and the access permitted. There are no wildcards, no expressions (regular or otherwise) and they apply to all objects. Only the labels are taken into account on an access check, not the userid, the current directory, the time of day, or the binary involved. Oh, there is a capability to override the check, but that's just basic Linux behavior and I wouldn't want to muck that up.
Quoted 27 lines
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Some practical use cases:
Hierarchical levels. The less common of the two usual uses for MLS systems is to define hierarchical levels, often unclassified, confidential, secret, and so on. To set up smack to support this, these rules could be defined:
C Unclass rx S C rx S Unclass rx TS S rx TS C rx TS Unclass rxA TS process can read S, C, and Unclass data, but cannot write it. An S process can read C and Unclass. Note that specifying that TS can read S and S can read C does not imply TS can read C, it has to be explicitly stated.
Quoted 7 lines
Quoted 5 lines
The big problem here is the duplication. Say you have a locked- down Apache configuration and you want to run 2 apache processes, one at Secret and one at Top-Secret. Under your model you have to copy-paste the policy and make sure to apply fixes/changes to both places.
I'm sorry, but I don't understand your point at all.
Quoted 8 lines
Ok, let's say you want to use your model to restrict Apache and MySQL running at the same classification level. You have to define combined labels, such as:
S_ApacheS_MySQLrx
[...]Now if you want to run an apache/mysql pair at TS, you have to copy all those rules and substitute "S_" with "
TS_".
There is only one rule to copy. I think most sysadmins can insert a "T" with sufficient confidence that this is not going to be a major issue.
Quoted 3 lines
With SELinux, you
don't have to do anything other than define new labels for the secret- web-docs and the top-secret-web-docs folders,
Which if you actually write out the change is going to require more than inserting a "T".
Quoted 19 lines
because the Apache
*type-enforcement* policy is completely independent from the MLS levels. You can write a 5-line policy to label 2 slightly different initscripts with different range-transitions. The only difference between them will be the paths inside and the labels on them. The rest of apache's policy stays the same.Quoted 12 lines
Quoted 11 lines
This is exactly what my company does, but the ability to restrict *exactly* what mechanisms are used is important. You restrict against file-system access implicitly, whereas SELinux does it explicitly:
allow foo_t foo_sock_t:socket { .... }; versus: allow foo_t foo_log_t:file { ... };With SELinux you can also allow your program to create files labelled as "log files" in one directory in one type and "transfer files" in another directory in a completely different type.
Quoted 7 lines
Quoted 1 line
I would be very interested to see the policy that your guard box uses.
Unfortunately that's still considered company-proprietary information at the moment, although that's likely to change at some point in the future. We're not all that different from the httpd policies and similar stuff found in the SELinux "refpolicy" available from tresys' website.
I think there's a rule against using proprietary information that you can't share in a friendly debate on the LKML.
Quoted 10 lines
Quoted 8 lines
Quoted 3 lines
I'm proud to say that the software of the company I work for does
not need any extra privilege at all (aside from binding to ports
<1024) to run under SELinux with strict MLS.That is an aspect of SELinux that has its dark side. While you are not explicitly violating a policy (e.g. requiring a capability) you are doing things that some of us would argue ought to require a capability. SELinux integrates privilege into the policy mechanism.
How does "moving data around a system" require root privileges?
Hmm. You snuck the adjective "root" into the discussion when it wasn't there before.
Quoted 4 lines
Why should it? Admittedly, moving data from "TopSecret" to "Secret" requires a process labeled with a range including at least "S-TS" *and* with the MLS "read-to-clearance" attribute, but you can be as stingy with that attribute as you like.
Yup. And plenty of people like you think that is really spiffy.
Quoted 4 lines
That attribute is explicitly
given its magic abilities in the mlsconstrain rules defined in the policy file itself, so it's also possible to do information flow analysis on it.
I much prefer strait-up process capabilities to magic attributes. Call me old fashioned if you want to.
Quoted 8 lines
Quoted 8 lines
Smack does not. Smack is designed to use traditional Linux mechanisms for privilege.
Quoted 4 lines
Under Trusted Solaris and such we needed all sorts of dirty privilege hacks to relabel the files consistently, but under SELinux the policy does all the relabeling for us, we don't need to do a thing.
Quoted 8 lines
Quoted 3 lines
Yeah. Well, you won't like Smack then. Implicit relabeling of processes and files does not happen. This is a major philisophical difference.
Here's an argument for why implicit labeling is good and explicit labeling is bad: If your process wants to label things explicitly it needs special privileges to do so, and it can abuse those privileges.
With privilege comes responsibility, and there has to be some effort made to ensure that privileged programs behave correctly.
Quoted 5 lines
Under SELinux the labeling is implicit *AND* the transitions are entirely within the policy. This means that you can do information flow analysis (as I described above) and it *ALSO* means that the program cannot possibly "abuse" its privileges because it has none.
It means you have not only the program to worry about being written correctly, but the policy as well.
Quoted 6 lines
When httpd creates a file in its log directory that
file is created withhttpd_log_tand it is limited to being able to append to the file *only*. So when your apache gets compromised, the attacker has NO WAY to modify the logs, and you can prove this with a 60-second study of the policy. In fact, on my companies productions systems I can *PROVE* that the only way to get audit data out of the
Quoted 8 lines
system is via a local TTY by interacting with system_u:object_r:local_login_t:SystemLow-SystemHigh to log in with a process of someluser:auditreview_r:auditreview_t:SystemHigh, which may read the audit files, or otherluser:auditadmin_r:auditadmin_t:SystemHigh, which may read and delete the audit files. I can even prove that no process on the system is allowed to modify the files after they are created, barring a kernel-level vulnerability.
Good. That is as it should be.
Quoted 3 lines
So the implicit labeling of files actually restricts every process *FURTHER*. They no longer have even an inkling of a choice about file labeling, and that's a GOOD thing.
That's true about Smack, you know. The process has no choice about the label that the files gte.
Quoted 5 lines
The only remaining extension
we need to really thoroughly lock down our systems is to allow last- path-component matching in type-transitions and allow rules (EG:
When "vipw" creates a file named "passwd" in an "etc_t" directory, it is automatically labeled "etc_passwd_t")
Hey, and AppArmor does that today!
Quoted 4 lines
From what I understand
Stephen Smalley and others are thinking that over even now. I'll do it myself as soon as I get time at work beyond prepping systems for shipping to clients if they haven't finished it by them.
You might want to review the archives on how that experiment ended up before saying much more about it.
Thank you for your comments. I hope that I have made the behavior and value of Smack clearer in responding to them.
Casey Schaufler
[email protected]
Linus and AKPM pulled from CC, I'm sure they're bored to tears by now ;-).
Quoted 11 lines · Casey Schaufler
Quoted 4 lines · --- Kyle Moffett
Quoted 1 line · Casey Schaufler
It would be instructive for those who are not well versed in the nuances of SELinux policy if you actually spelled out the whole thing, rather than using "## and more ##". Part of the point of Smack is the makeup of the full list that would be required here.
Well, yes, but how exactly do you define "read", "write", and "execute" for the full list of SELinux object classes found here: http://www.tresys.com/selinux/obj_perms_help.html
Smack is designed to treat objects as consistantly as is reasonable. The list of object classes defined by SELinux is great for a system designed to treat accesses with the highest possible granularity. This is not a design goal for Smack.
Quoted 1 line
I was considering compiling the complete list, but such an exercise would take me at least an hour to do properly and which categories individual permissions should be placed in could be argued for weeks.
I will be happy to consider your arguement when you are willing to present the complete argument.
Here's my complete argument:
Regardless of how you categorize "read", "write", "execute", and "doesnt-need-protection" in your policy language, I can write an SELinux policy and a list of labels which expresses that policy. Moreover, without too much work I can probably write a Perl script to do it for you. On the other hand I can only do that if you tell me exactly how you want to categorize those things, though. In my personal opinion they cannot be reasonably categorized without breaking all sorts of tools or leaving gaping holes; precisely the reason that SELinux uses such a fine-grained list.
Quoted 3 lines
Quoted 1 line
Specifically, do you classify the
bind()syscall as a "read" or a "write" operation.Neither. Bind attaches a name (port number) to a socket (which is a data structure that is part of your process) from a global namespace. No objects are involved, hence no accesses.
So "bind()" doesn't present a security hole at all and any program may bind to any port? Sounds fun! I'm sure lots of crackers would love to get ahold of an account on such a web-server; what havoc they could wreak! Even the <1024 restriction doesn't sufficiently limit things these days, as many critical services use ports >=1024.
Quoted 31 lines
Quoted 31 lines
Quoted 31 lines
Quoted 30 lines
And now to describe these rules:
Quoted 8 lines
Smack defines and uses these labels:
"*" - pronounced "star"
"_" - pronounced "floor"
"^" - pronounced "hat"
"?" - pronounced "huh"The access rules enforced by Smack are, in order:
Quoted 7 lines
1. Any access requested by a task labeled "*" is denied.
2. A read or execute access requested by a task labeled "^" is permitted.
3. A read or execute access requested on an object labeled "_" is permitted.
4. Any access requested on an object labeled "*" is permitted.
5. Any access requested by a task on an object with the same label is permitted.
6. Any access requested that is explicitly defined in the loaded rule set is permitted.
7. Any other access is denied.## These are calls to the above macros which plug in the necessary arguments
r(hat, {*})x(hat, {*})r(~{star}, floor)x(~{star}, floor)r(~{star}, star)w(~{star}, star)x(~{star}, star)r(~{star}, self)w(~{star}, self)x(~{star}, self)
## Include your "loaded rule set" here ##
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
What would that look like?
The same kind of thing as the r, x, and w above, with occasional "type
my_type_t; role rr typesmy_type_t;" to declare a type before use. If you wanted to add support for attributes which apply to multiple types, you could put those after a comma after the "typemy_type_t" portion of the type declaration.Well, I'm interested in seeing the actual code, not "the same kind of thing" as arguement.
Ok, you want sample policy to match your "MLS" sample? For convenience here's one more macro:
define(rx',r($1',$2') x($1',$2')')
type unclass;
type c;
type s;
type ts;rx(c, unclass)rx(s, c)rx(s, unclass)rx(ts, s)rx(ts, c)rx(ts, unclass)
In case you don't have the policy you typed into your email, it looks almost identical with a few exceptions for slightly modified syntax:
Quoted 16 lines
C Unclass rx S C rx S Unclass rx TS S rx TS C rx TS Unclass rxQuoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 1 line
Smack rule sets can be easily defined that describe Bell&LaPadula sensitivity, Biba integrity, and a variety of interesting configurations. Smack rule sets can be modified on the fly to accomodate changes in the operating environment or even the time of day.
SELinux can do this as well. It even includes support for conditional policy:
bool
foo_can_do_loggingtrue;if (foo_can_do_logging) { allow foo_t foo_log_t:file { create read getattr append }; }
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
You have to build the booleans into the policy in advance.
Well, yes, but a policy which completely ignores
This sentence no verb.
Whoops, I think I must have smashed the delete key or something while sending. Here's the paragraphs which got elided:
Well, yes, but a policy which completely ignores future expandability can't be expanded upon regardless. It would also be very hard to add new policy without a lot of duplication under your system. On the other hand, with SELinux you can very easily add attribute-based policy so adding new capabilities is as simple as sticking existing attributes on newly defined types. For example:
type my_log_t, file_type, log_file;
type my_log_daemon, daemon;
Right there I just gave permission for the logrotate to recycle files labelled my_log_t, which the sysadmin and audit admin can also read (and the audit admin can delete). I also gave permission for my daemon to send SIGCHLD to init, and for init/initscripts to send it a SIGTERM/SIGQUIT. All without writing a SINGLE policy rule. Basically all of those existing behaviors are found in allow rules built on the "file_type", "log_file", and "daemon" attributes.
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
Quoted 1 line
The SELinux tools also have support for policy modules, so you can extend the policy without modifying the base system.
And that's a good thing, but you still have to compile and reload your policy, and maybe relabel you filesystem when you do so.
Quoted 8 lines
Quoted 1 line
What exactly prevents you from having to "reload" and "relabel the filesystem" when using your system?
Good question. First, changing Smack rules is no big deal. They can be added or changed one by one as required while the system is running, and there are uses that exploit that. One example is to put the label "Game" on certain programs and:
at 8:00am "Worker Game no"
at 5:00pm "Worker Game x"Thus Worker processes can access Game files only during off hours.
This is fundamentally broken: First of all we have no fd revoke support yet, so all a user has to do is start the game at 5:05pm just before they leave, then leave it running in the background during the day for them to play at leisure. Secondly, you can already do the same thing with DAC and a PAM groups-from-time-of-day module, I don't see why such a thing is special enough to need MAC. Thirdly, I could do exactly the same thing with an SELinux boolean and a cronjob (once we get proper revoke support):
## Rule to allow cron to tweak the "can_play_games" boolean value if (can_play_games) {
## Insert game-playing allow rules here
}
Then in cron:
0 8 * * * root setsebool can_play_games false
0 17 * * * root setsebool can_play_games true
Quoted 1 line
As far as relabeling the file system goes, the rules apply to processes and objects, not to programs. The label on a program describes who can access it, it will run with the label of the process that exec's it. A change in the rules does not require a change to the labels on the file system for things to work according to the rules of engagement.
By this logic, every program will always have the same label, unless you recode every program to explicitly change it when it starts; precisely the thing that the SELinux type transitions were designed to avoid.
Quoted 3 lines
Quoted 1 line
When you change the meaning of new types, you clearly would need to first reload the policy then relaunch programs or relabel files to take advantage of the new types, otherwise they would be categorically ignored by the system.
I'm sorry, but again, I don't know what you mean by "changing the meaning of new types".
Oh, say something like "Oh, drat, I wanted this daemon to run as some other type". Unless you relabel the files and relaunch the daemon the system will have no idea how the system will change. And if you let arbitrary root processes relabel things on the fly then you've lost all the security advantages to a MAC system.
Quoted 1 line
I think you may be making assumptions about the behavior of Smack based on what SELinux does that don't hold. I hesitate to call a Smack rule list a language.
Well, it's a syntactic construction to describe an idea, ergo it's a language.
Quoted 3 lines
Quoted 1 line
I suspect you'd get shot down instantly if you tried to stuff the policy compiler in the kernel too.
Smack rule specifications are really really basic, just the subject label, the object label, and the access permitted. There are no wildcards, no expressions (regular or otherwise) and they apply to all objects. Only the labels are taken into account on an access check, not the userid, the current directory, the time of day, or the binary involved. Oh, there is a capability to override the check, but that's just basic Linux behavior and I wouldn't want to muck that up.
I think you may be making assumptions about the behaviour of SELinux based on what other OSes do which don't hold:
(a) SELinux does not care about user id, current directory, time of day, etc. It cares solely about 3 things:
the Subject, the Object, and the Action. For example, if an init script attempts to execute the apache binary then SELinux gets the following data for parameters: subject="system_u:system_r:initrc_t:SystemLow-SystemHigh" object="system_u:object_r:httpd_exec_t:SystemLow" action="file->execute".
(b) SELinux does NOT have a capability which overrides it. If you want to do something that the policy categorically does not allow, you have 2 choices: change the policy or disable SELinux. You can also use a policy which disables both of those options
Quoted 7 lines
Quoted 5 lines
Ok, let's say you want to use your model to restrict Apache and MySQL running at the same classification level. You have to define combined labels, such as:
S_ApacheS_MySQLrx
[...]Now if you want to run an apache/mysql pair at TS, you have to copy all those rules and substitute "S_" with "
TS_".There is only one rule to copy. I think most sysadmins can insert a "T" with sufficient confidence that this is not going to be a major issue.
Which means that for every new category/level-alteration you have to modify a significant portion of your policy. With SELinux I get to either add 2 lines to a local policy module or run a couple "semanage" commands.
Quoted 3 lines
Quoted 1 line
With SELinux, you don't have to do anything other than define new labels for the secret-web-docs and the top-secret-web-docs folders,
Which if you actually write out the change is going to require more than inserting a "T".
Umm, how so? Any of these will work:
* The security administrator creates my /www_S and /www_TS
folders, labels them, and remembers not to run "restorecon" on those folders.
* The security administrator loads a local policy module with just
an fc file containing:
/www_S(/.*)? system_u:object_r:web_docs_t:Secret
/www_TS(/.*)? system_u:object_r:web_docs_t:TopSecret * The security administrator runs these commands:
semanage fcontext -a -r Secret-Secret -s system_u -tweb_docs_t '/www_S(/.*)?'
semanage fcontext -a -r TopSecret-TopSecret -s system_u -tweb_docs_t '/www_TS(/.*)?'
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
This is exactly what my company does, but the ability to restrict *exactly* what mechanisms are used is important. You restrict against file-system access implicitly, whereas SELinux does it explicitly:
allow foo_t foo_sock_t:socket { .... }; versus: allow foo_t foo_log_t:file { ... };
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
With SELinux you can also allow your program to create files labelled as "log files" in one directory in one type and "transfer files" in another directory in a completely different type.
I would be very interested to see the policy that your guard box uses.
Unfortunately that's still considered company-proprietary information at the moment, although that's likely to change at some point in the future. We're not all that different from the httpd policies and similar stuff found in the SELinux "refpolicy" available from tresys' website.
I think there's a rule against using proprietary information that you can't share in a friendly debate on the LKML.
Well, you were the one who asked. It's mostly irrelevant to the discussion since the *same* kind of stuff is found in almost every module in the tresys-distributed refpolicy.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
I'm proud to say that the software of the company I work for does not need any extra privilege at all (aside from binding to ports <1024) to run under SELinux with strict MLS.
That is an aspect of SELinux that has its dark side. While you are not explicitly violating a policy (e.g. requiring a capability) you are doing things that some of us would argue ought to require a capability. SELinux integrates privilege into the policy mechanism.
How does "moving data around a system" require root privileges?
Hmm. You snuck the adjective "root" into the discussion when it wasn't there before.
Ok, fine, how does "moving data around a system" require anything more than bog-standard user-level privileges? Normal users under Linux are not permitted to change "security.*" attributes at all, but they may bind to sockets, etc. You can define a "capability" which lets you do all that, but then you're just blindly giving processes more privileges than they need to complete an operation. Why should you get the "rename all files" priv when all you need is "Make my log files get $LABEL when I put them in /var/log/mydaemon/"?
Quoted 3 lines
Quoted 1 line
Why should it? Admittedly, moving data from "TopSecret" to "Secret" requires a process labeled with a range including at least "S-TS" *and* with the MLS "read-to-clearance" attribute, but you can be as stingy with that attribute as you like.
Yup. And plenty of people like you think that is really spiffy.
Please explain why you think it isn't?
Quoted 3 lines
Quoted 1 line
That attribute is explicitly given its magic abilities in the mlsconstrain rules defined in the policy file itself, so it's also possible to do information flow analysis on it.
I much prefer strait-up process capabilities to magic attributes. Call me old fashioned if you want to.
You can call them "process capabilities" or "magic attributes", they're the same thing, just more fine-grained. Instead of (Note: r1 == subject role, r2 == target role, t2 == target type):
mlsconstrain process transition ( (r1 == r2) || (t1 ==i_am_a_role_changing_capability) )
you have (Note: t1 == subject type):
mlsconstrain process transition ( (r1 == r2) || (r1 == system_r &&
t1 == i_am_a_login_process && t2 == i_am_a_user_entrypoint) )
The latter is like the former, except instead of one single ultimate "change-any-role" capability, you have a capability which allows a system login process to change roles *ONLY* if it's also changing to a user entrypoint. Please tell me which you think is more secure.
Quoted 3 lines
Quoted 1 line
Under SELinux the labeling is implicit *AND* the transitions are entirely within the policy. This means that you can do information flow analysis (as I described above) and it *ALSO* means that the program cannot possibly "abuse" its privileges because it has none.
It means you have not only the program to worry about being written correctly, but the policy as well.
If your security policy sucks then you might as well not have MAC at all. At least under SELinux the absolute worst possible case is that you always fall back to DAC-based security.
Quoted 3 lines
Quoted 1 line
So the implicit labeling of files actually restricts every process *FURTHER*. They no longer have even an inkling of a choice about file labeling, and that's a GOOD thing.
That's true about Smack, you know. The process has no choice about the label that the files get.
So how do you selectively label files based on criteria such as "where did I get put"? How do you distinguish between a "log file" which is create-and-append-only, a "database file" which I can modify however I want to, and a "unix socket" which I can bind in /var/run and get connections from user processes?
Quoted 3 lines
Quoted 1 line
The only remaining extension we need to really thoroughly lock down our systems is to allow last-path-component matching in type-transitions and allow rules (EG: When "vipw" creates a file named "passwd" in an "
etc_t" directory, it is automatically labeled "etc_passwd_t")Hey, and AppArmor does that today!
No, AppArmor doesn't. It says: "/usr/sbin/httpd may not access /etc/shadow", for example, whereas SELinux with the proposed extension says: "Only the 'passwd' program or 'vipw' by a sysadmin may modify *ANY* password shadow file, and if I create a "shadow" file in *ANY* etc_t directory then it's automatically a shadow file. The difference is also in the treatment of hard-links. Under SELinux I can guarantee that the data in the shadow_t file is secure, no matter where somebody manages to get it linked to, and in addition I can guarantee that nobody can spoof me and make me create the shadow file elsewhere or with the wrong label.
Quoted 4 lines
Quoted 2 lines
From what I understand Stephen Smalley and others are thinking that over even now. I'll do it myself as soon as I get time at work beyond prepping systems for shipping to clients if they haven't finished it by them.
You might want to review the archives on how that experiment ended up before saying much more about it.
Hmm, I haven't seen anything pass LKML and digging in the [email protected] archives (as well as google) doesn't seem to be turning up anything even vaguely related. Do you happen to have the link handy?
Quoted 1 line
Thank you for your comments. I hope that I have made the behavior and value of Smack clearer in responding to them.
You're welcome. I endeavor to poke my nose into every little LSM-related corner in the kernel, this one included.
Cheers,
Kyle Moffett
Casey Schaufler
maintainerQuoted 2 lines · --- Kyle Moffett
Linus and AKPM pulled from CC, I'm sure they're bored to tears by now ;-).
Yeah.
Quoted 27 lines · Casey Schaufler
Quoted 16 lines
Quoted 9 lines · --- Kyle Moffett
Quoted 4 lines · Casey Schaufler
It would be instructive for those who are not well versed in the nuances of SELinux policy if you actually spelled out the whole thing, rather than using "## and more ##". Part of the point of Smack is the makeup of the full list that would be required here.
Well, yes, but how exactly do you define "read", "write", and "execute" for the full list of SELinux object classes found here:
http://www.tresys.com/selinux/obj_perms_help.htmlSmack is designed to treat objects as consistantly as is reasonable. The list of object classes defined by SELinux is great for a system designed to treat accesses with the highest possible granularity. This is not a design goal for Smack.
Quoted 7 lines
Quoted 4 lines
I was considering compiling the complete list, but such an exercise would take me at least an hour to do properly and which categories individual permissions should be placed in could be argued for weeks.
I will be happy to consider your arguement when you are willing to present the complete argument.
Here's my complete argument:
Quoted 9 lines
Regardless of how you categorize "read", "write", "execute", and "doesnt-need-protection" in your policy language, I can write an SELinux policy and a list of labels which expresses that policy. Moreover, without too much work I can probably write a Perl script to do it for you. On the other hand I can only do that if you tell me exactly how you want to categorize those things, though. In my personal opinion they cannot be reasonably categorized without breaking all sorts of tools or leaving gaping holes; precisely the reason that SELinux uses such a fine-grained list.
This identifies an important design philosophy issue, that being what granularity is appropriate. I have no interest in composing a description of Smack at the granularity that SELinux uses. The point you make, that you need to have that in order to create a policy description, is one of the reasons for Smack. Simplified.
I respect the design decisions that SELinux has made regarding granularity without agreeing with them myself.
Quoted 7 lines
Quoted 6 lines
Quoted 2 lines
Specifically, do you classify the
bind()syscall as a "read" or a "write" operation.Neither. Bind attaches a name (port number) to a socket (which is a data structure that is part of your process) from a global namespace. No objects are involved, hence no accesses.
Quoted 5 lines
So "
bind()" doesn't present a security hole at all and any program may bind to any port? Sounds fun! I'm sure lots of crackers would love to get ahold of an account on such a web-server; what havoc they could wreak! Even the <1024 restriction doesn't sufficiently limit things these days, as many critical services use ports >=1024.
Heaven forbid I should put all those firewall writers out of work. Seriously, the port namespace is completely arbitrary by "design".
Quoted 62 lines
Quoted 38 lines
Quoted 38 lines
Quoted 37 lines
Quoted 22 lines
And now to describe these rules:
Quoted 8 lines
Smack defines and uses these labels:
"*" - pronounced "star"
"_" - pronounced "floor"
"^" - pronounced "hat"
"?" - pronounced "huh"The access rules enforced by Smack are, in order:
Quoted 11 lines
1. Any access requested by a task labeled "*" is denied.
2. A read or execute access requested by a task labeled "^" is permitted.
3. A read or execute access requested on an object labeled "_" is permitted.
4. Any access requested on an object labeled "*" is permitted.
5. Any access requested by a task on an object with the same label is permitted.
6. Any access requested that is explicitly defined in the loaded rule set is permitted.
7. Any other access is denied.Quoted 13 lines
## These are calls to the above macros which plug in the necessary arguments
r(hat, {*})x(hat, {*})r(~{star}, floor)x(~{star}, floor)r(~{star}, star)w(~{star}, star)x(~{star}, star)r(~{star}, self)w(~{star}, self)x(~{star}, self)
## Include your "loaded rule set" here ##What would that look like?
Quoted 8 lines
Quoted 5 lines
The same kind of thing as the r, x, and w above, with occasional "type
my_type_t; role rr typesmy_type_t;" to declare a type before use. If you wanted to add support for attributes which apply to multiple types, you could put those after a comma after the "typemy_type_t" portion of the type declaration.Well, I'm interested in seeing the actual code, not "the same kind of thing" as arguement.
Ok, you want sample policy to match your "MLS" sample? For convenience here's one more macro:
define(rx',r($1',$2') x($1',$2')')type unclass;
type c;
type s;
type ts;rx(c, unclass)rx(s, c)rx(s, unclass)rx(ts, s)rx(ts, c)rx(ts, unclass)
Quoted 8 lines
In case you don't have the policy you typed into your email, it looks almost identical with a few exceptions for slightly modified syntax:
Quoted 6 lines
C Unclass rx S C rx S Unclass rx TS S rx TS C rx TS Unclass rx
Yup. Your macro invocations look very much like the Smack specification. Your macro definitions are of course unnecessary in Smack, and you really ought to be using the MLS labels SELinux supports, and you need a base policy underneath this.
Quoted 33 lines
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
Quoted 5 lines
Smack rule sets can be easily defined that describe Bell&LaPadula sensitivity, Biba integrity, and a variety of interesting configurations. Smack rule sets can be modified on the fly to accomodate changes in the operating environment or even the time of day.
SELinux can do this as well. It even includes support for conditional policy:
bool
foo_can_do_loggingtrue;if (foo_can_do_logging) { allow foo_t foo_log_t:file { create read getattr append }; }Quoted 5 lines
Quoted 3 lines
Quoted 1 line
You have to build the booleans into the policy in advance.
Well, yes, but a policy which completely ignores
This sentence no verb.
Whoops, I think I must have smashed the delete key or something while sending. Here's the paragraphs which got elided:
Well, yes, but a policy which completely ignores future expandability can't be expanded upon regardless. It would also be very hard to add new policy without a lot of duplication under your system. On the other hand, with SELinux you can very easily add attribute-based policy so adding new capabilities is as simple as sticking existing attributes on newly defined types. For example:
type
my_log_t,file_type,log_file;
typemy_log_daemon, daemon;
Quoted 7 lines
Right there I just gave permission for the logrotate to recycle files labelled
my_log_t, which the sysadmin and audit admin can also read (and the audit admin can delete). I also gave permission for my daemon to send SIGCHLD to init, and for init/initscripts to send it a SIGTERM/SIGQUIT. All without writing a SINGLE policy rule. Basically all of those existing behaviors are found in allow rules built on the "file_type", "log_file", and "daemon" attributes.
Ah, now you're refering to the reference policy, right?
Quoted 17 lines
Quoted 17 lines
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
The SELinux tools also have support for policy modules, so you can extend the policy without modifying the base system.
And that's a good thing, but you still have to compile and reload your policy, and maybe relabel you filesystem when you do so.
What exactly prevents you from having to "reload" and "relabel the filesystem" when using your system?
Good question. First, changing Smack rules is no big deal. They can be added or changed one by one as required while the system is running, and there are uses that exploit that. One example is to put the label "Game" on certain programs and:
at 8:00am "Worker Game no"
at 5:00pm "Worker Game x"
Quoted 6 lines
Quoted 1 line
Thus Worker processes can access Game files only during off hours.
This is fundamentally broken: First of all we have no fd revoke support yet, so all a user has to do is start the game at 5:05pm just before they leave, then leave it running in the background during the day for them to play at leisure.
That's why it's never a good idea to teach the Pointy Haired One about "ps".
Quoted 5 lines
Secondly, you can already do the
same thing with DAC and a PAM groups-from-time-of-day module, I don't see why such a thing is special enough to need MAC. Thirdly, I could do exactly the same thing with an SELinux boolean and a cronjob (once we get proper revoke support):
There is usually a way to address any particular problem using DAC, it's often sufficiently painful that MAC looks like a better approach.
Your boolean solution requires more forthought than the Smack rule solution, but I'll give it to you once you've fleshed out your "##" lines.
Quoted 17 lines
## Rule to allow cron to tweak the "
can_play_games" boolean value if (can_play_games) {
## Insert game-playing allow rules here
}Then in cron:
0 8 * * * root setseboolcan_play_gamesfalse
0 17 * * * root setseboolcan_play_gamestrueQuoted 6 lines
As far as relabeling the file system goes, the rules apply to processes and objects, not to programs. The label on a program describes who can access it, it will run with the label of the process that exec's it. A change in the rules does not require a change to the labels on the file system for things to work according to the rules of engagement.
Quoted 4 lines
By this logic, every program will always have the same label, unless you recode every program to explicitly change it when it starts; precisely the thing that the SELinux type transitions were designed to avoid.
Yes. This is the way it should be. A small set of very carefully analysed programs that change labels under carefully controlled circumstances is what I want. login, sshd, cron, special purpose launchers. Written with the assumption that they will be attacked.
Quoted 10 lines
Quoted 7 lines
Quoted 4 lines
When you change the meaning of new types, you clearly would need to first reload the policy then relaunch programs or relabel files to take advantage of the new types, otherwise they would be categorically ignored by the system.
I'm sorry, but again, I don't know what you mean by "changing the meaning of new types".
Oh, say something like "Oh, drat, I wanted this daemon to run as some other type".
Sorry, "type" is a meaningless attribute in Smack.
Quoted 4 lines
Unless you relabel the files and relaunch the daemon
the system will have no idea how the system will change. And if you let arbitrary root processes relabel things on the fly then you've lost all the security advantages to a MAC system.
MAC systems have been behaving this way for decades. SELinux is the exception, not the rule on this.
Quoted 6 lines
Quoted 3 lines
I think you may be making assumptions about the behavior of Smack based on what SELinux does that don't hold. I hesitate to call a Smack rule list a language.
Well, it's a syntactic construction to describe an idea, ergo it's a language.
Ok. I still don't understand the point.
Quoted 15 lines
Quoted 11 lines
Quoted 2 lines
I suspect you'd get shot down instantly if you tried to stuff the policy compiler in the kernel too.
Smack rule specifications are really really basic, just the subject label, the object label, and the access permitted. There are no wildcards, no expressions (regular or otherwise) and they apply to all objects. Only the labels are taken into account on an access check, not the userid, the current directory, the time of day, or the binary involved. Oh, there is a capability to override the check, but that's just basic Linux behavior and I wouldn't want to muck that up.
I think you may be making assumptions about the behaviour of SELinux based on what other OSes do which don't hold:
Quoted 8 lines
(a) SELinux does not care about user id, current directory, time of day, etc. It cares solely about 3 things:
the Subject, the Object, and the Action. For example, if an init script attempts to execute the apache binary then SELinux gets the following data for parameters:
subject="system_u:system_r:initrc_t:SystemLow-SystemHigh" object="system_u:object_r:httpd_exec_t:SystemLow" action="file-Quoted 1 line
execute".
Yes, and each of the components of the subject and object contexts is dependent on a more circumstances than I'd care to deal with. You've demonstrated that SELinux implements fine granularity.
Quoted 4 lines
(b) SELinux does NOT have a capability which overrides it. If you want to do something that the policy categorically does not allow, you have 2 choices: change the policy or disable SELinux. You can also use a policy which disables both of those options
Yup. I think that's bad.
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Ok, let's say you want to use your model to restrict Apache and MySQL running at the same classification level. You have to define combined labels, such as:
S_ApacheS_MySQLrx
[...]Now if you want to run an apache/mysql pair at TS, you have to copy all those rules and substitute "S_" with "
TS_".
Quoted 8 lines
Quoted 3 lines
There is only one rule to copy. I think most sysadmins can insert a "T" with sufficient confidence that this is not going to be a major issue.
Which means that for every new category/level-alteration you have to modify a significant portion of your policy. With SELinux I get to either add 2 lines to a local policy module or run a couple "semanage" commands.
Yup. And Bell & LaPadula using a combination of levels and categories is probably the Smack worst case. But guess what? The dig against that policy has always been that no one wanted to combine levels and categories.
Quoted 44 lines
Quoted 5 lines
Quoted 2 lines
With SELinux, you don't have to do anything other than define new labels for the secret-web-docs and the top-secret-web-docs folders,
Which if you actually write out the change is going to require more than inserting a "T".
Umm, how so? Any of these will work:
* The security administrator creates my /www_S and /www_TS
folders, labels them, and remembers not to run "restorecon" on those folders.* The security administrator loads a local policy module with just
an fc file containing:/www_S(/.*)? system_u:object_r:web_docs_t:Secret /www_TS(/.*)? system_u:object_r:web_docs_t:TopSecret* The security administrator runs these commands:
semanage fcontext -a -r Secret-Secret -ssystem_u-tweb_docs_t'/www_S(/.*)?'
semanage fcontext -a -r TopSecret-TopSecret -ssystem_u-tweb_docs_t'/www_TS(/.*)?'Quoted 22 lines
Quoted 21 lines
Quoted 8 lines
Quoted 8 lines
This is exactly what my company does, but the ability to restrict *exactly* what mechanisms are used is important. You restrict against file-system access implicitly, whereas SELinux does it explicitly:
allow foo_t foo_sock_t:socket { .... }; versus: allow foo_t foo_log_t:file { ... };Quoted 7 lines
Quoted 4 lines
With SELinux you can also allow your program to create files labelled as "log files" in one directory in one type and "transfer files" in another directory in a completely different type.
I would be very interested to see the policy that your guard box uses.
Unfortunately that's still considered company-proprietary information at the moment, although that's likely to change at some point in the future. We're not all that different from the httpd policies and similar stuff found in the SELinux "refpolicy" available from tresys' website.
Quoted 6 lines
Quoted 2 lines
I think there's a rule against using proprietary information that you can't share in a friendly debate on the LKML.
Well, you were the one who asked. It's mostly irrelevant to the discussion since the *same* kind of stuff is found in almost every module in the tresys-distributed refpolicy.
OK.
Quoted 15 lines
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 3 lines
I'm proud to say that the software of the company I work for does not need any extra privilege at all (aside from binding to ports <1024) to run under SELinux with strict MLS.
That is an aspect of SELinux that has its dark side. While you are not explicitly violating a policy (e.g. requiring a capability) you are doing things that some of us would argue ought to require a capability. SELinux integrates privilege into the policy mechanism.
Quoted 4 lines
Quoted 1 line
How does "moving data around a system" require root privileges?
Hmm. You snuck the adjective "root" into the discussion when it wasn't there before.
Quoted 8 lines
Ok, fine, how does "moving data around a system" require anything more than bog-standard user-level privileges? Normal users under Linux are not permitted to change "security.*" attributes at all, but they may bind to sockets, etc. You can define a "capability" which lets you do all that, but then you're just blindly giving processes more privileges than they need to complete an operation. Why should you get the "rename all files" priv when all you need is "Make my log files get $LABEL when I put them in
/var/log/mydaemon/"?
Privilege granularity is a seperate issue. Smack uses Linux privilege machanisms and is happy to do so.
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Why should it? Admittedly, moving data from "TopSecret" to "Secret" requires a process labeled with a range including at least "S-TS" *and* with the MLS "read-to-clearance" attribute, but you can be as stingy with that attribute as you like.
Yup. And plenty of people like you think that is really spiffy.
Please explain why you think it isn't?
I grew up believing that downgrading classified information should always be an explicit, concious act.
Quoted 13 lines
Quoted 6 lines
Quoted 3 lines
That attribute is explicitly given its magic abilities in the mlsconstrain rules defined in the policy file itself, so it's also possible to do information flow analysis on it.
I much prefer strait-up process capabilities to magic attributes. Call me old fashioned if you want to.
You can call them "process capabilities" or "magic attributes", they're the same thing, just more fine-grained. Instead of (Note: r1 == subject role, r2 == target role, t2 == target type):
mlsconstrain process transition ( (r1 == r2) || (t1 ==
i_am_a_role_changing_capability) )
Quoted 8 lines
you have (Note: t1 == subject type):
mlsconstrain process transition ( (r1 == r2) || (r1 == system_r &&t1 ==
i_am_a_login_process&& t2 ==i_am_a_user_entrypoint) )The latter is like the former, except instead of one single ultimate "change-any-role" capability, you have a capability which allows a system login process to change roles *ONLY* if it's also changing to a user entrypoint. Please tell me which you think is more secure.
Don't look at me. A well written program could do fine with either.
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
Under SELinux the labeling is implicit *AND* the transitions are entirely within the policy. This means that you can do information flow analysis (as I described above) and it *ALSO* means that the program cannot possibly "abuse" its privileges because it has none.
Quoted 6 lines
Quoted 2 lines
It means you have not only the program to worry about being written correctly, but the policy as well.
If your security policy sucks then you might as well not have MAC at all. At least under SELinux the absolute worst possible case is that you always fall back to DAC-based security.
Ok.
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
So the implicit labeling of files actually restricts every process *FURTHER*. They no longer have even an inkling of a choice about file labeling, and that's a GOOD thing.
Quoted 8 lines
Quoted 2 lines
That's true about Smack, you know. The process has no choice about the label that the files get.
So how do you selectively label files based on criteria such as "where did I get put"? How do you distinguish between a "log file" which is create-and-append-only, a "database file" which I can modify however I want to, and a "unix socket" which I can bind in
/var/runand get connections from user processes?
I don't. They're all objects.
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
The only remaining extension we need to really thoroughly lock down our systems is to allow last-path-component matching in type- transitions and allow rules (EG: When "vipw" creates a file named "passwd" in an "
etc_t" directory, it is automatically labeled "etc_passwd_t")Hey, and AppArmor does that today!
Quoted 10 lines
No, AppArmor doesn't. It says: "
/usr/sbin/httpdmay not access/etc/shadow", for example, whereas SELinux with the proposed extension
says: "Only the 'passwd' program or 'vipw' by a sysadmin may modify *ANY* password shadow file, and if I create a "shadow" file in *ANY*etc_tdirectory then it's automatically a shadow file. The difference is also in the treatment of hard-links. Under SELinux I can guarantee that the data in theshadow_tfile is secure, no matter where somebody manages to get it linked to, and in addition I can guarantee that nobody can spoof me and make me create the shadow file elsewhere or with the wrong label.
If you say so.
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
From what I understand Stephen Smalley and others are thinking that over even now. I'll do it myself as soon as I get time at work beyond prepping systems for shipping to clients if they haven't finished it by them.
Quoted 7 lines
Quoted 2 lines
You might want to review the archives on how that experiment ended up before saying much more about it.
Hmm, I haven't seen anything pass LKML and digging in the [email protected] archives (as well as google) doesn't seem to be turning up anything even vaguely related. Do you happen to have the link handy?
Nope.
Quoted 5 lines
Quoted 2 lines
Thank you for your comments. I hope that I have made the
behavior and value of Smack clearer in responding to them.You're welcome. I endeavor to poke my nose into every little LSM- related corner in the kernel, this one included.
Why?
Casey Schaufler
[email protected]
Quoted 3 lines · Casey Schaufler
I respect the design decisions that SELinux has made regarding granularity without agreeing with them myself.
It isn't even an exclusive decision: both design points can be "right", but aimed at different use cases. Which is why LSM exists, so users can decide on an appropriate mechanism.
Crispin
Signature · 3 lines
Crispin Cowan, Ph.D. http://crispincowan.com/~crispin/ Director of Software Engineering http://novell.com AppArmor Chat: irc.oftc.net/#apparmor
Quoted 5 lines · Casey Schaufler
Quoted 4 lines · --- Kyle Moffett
Quoted 3 lines · Casey Schaufler
Quoted 1 line · --- Kyle Moffett
I was considering compiling the complete list, but such an exercise would take me at least an hour to do properly and which categories individual permissions should be placed in could be argued for weeks.
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
I will be happy to consider your arguement when you are willing to present the complete argument.
Here's my complete argument:
Regardless of how you categorize "read", "write", "execute", and "doesnt-need-protection" in your policy language, I can write an SELinux policy and a list of labels which expresses that policy. Moreover, without too much work I can probably write a Perl script to do it for you. On the other hand I can only do that if you tell me exactly how you want to categorize those things, though. In my personal opinion they cannot be reasonably categorized without breaking all sorts of tools or leaving gaping holes; precisely the reason that SELinux uses such a fine-grained list.
This identifies an important design philosophy issue, that being what granularity is appropriate. I have no interest in composing a description of Smack at the granularity that SELinux uses.
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?
Quoted 1 line
The point you make, that you need to have that in order to create a policy description, is one of the reasons for Smack. Simplified.
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.
Quoted 15 lines
Quoted 15 lines
Ok, you want sample policy to match your "MLS" sample? For convenience here's one more macro:
define(rx',r($1',$2') x($1',$2')')type unclass;
type c;
type s;
type ts;rx(c, unclass)rx(s, c)rx(s, unclass)rx(ts, s)rx(ts, c)rx(ts, unclass)In case you don't have the policy you typed into your email, it looks almost identical with a few exceptions for slightly modified syntax:
Quoted 8 lines
Quoted 6 lines
Quoted 6 lines
C Unclass rx S C rx S Unclass rx TS S rx TS C rx TS Unclass rxYup. Your macro invocations look very much like the Smack specification. Your macro definitions are of course unnecessary in Smack, and you really ought to be using the MLS labels SELinux supports, and you need a base policy underneath this.
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.
Quoted 10 lines
Quoted 8 lines
Whoops, I think I must have smashed the delete key or something while sending. Here's the paragraphs which got elided:
Well, yes, but a policy which completely ignores future expandability can't be expanded upon regardless. It would also be very hard to add new policy without a lot of duplication under your system. On the other hand, with SELinux you can very easily add attribute-based policy so adding new capabilities is as simple as sticking existing attributes on newly defined types. For example:
type
my_log_t,file_type,log_file;
typemy_log_daemon, daemon;Right there I just gave permission for the logrotate to recycle files labelled
my_log_t, which the sysadmin and audit admin can also read (and the audit admin can delete). I also gave permission for my daemon to send SIGCHLD to init, and for init/initscripts to send it a SIGTERM/SIGQUIT. All without writing a SINGLE policy rule. Basically all of those existing behaviors are found in allow rules built on the "file_type", "log_file", and "daemon" attributes.Ah, now you're refering to the reference policy, right?
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.
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
They can be added or changed one by one as required while the system is running, and there are uses that exploit that. One example is to put the label "Game" on certain programs and:
at 8:00am "Worker Game no"
at 5:00pm "Worker Game x"
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
Thus Worker processes can access Game files only during off hours.
This is fundamentally broken:
[...]
Secondly, you can already do the same thing with DAC and a PAM groups-from-time-of-day module, I don't see why such a thing is special enough to need MAC. Thirdly, I could do exactly the same thing with an SELinux boolean and a cronjob (once we get proper revoke support):There is usually a way to address any particular problem using DAC, it's often sufficiently painful that MAC looks like a better approach.
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?
Quoted 1 line
Your boolean solution requires more forthought than the Smack rule solution, but I'll give it to you once you've fleshed out your "##" lines.
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.
Quoted 1 line
Quoted 1 line
## Rule to allow cron to tweak the "
can_play_games" boolean value
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);
Quoted 3 lines
Quoted 3 lines
if (
can_play_games) {
## Insert game-playing allow rules here
}
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 douses_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.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
As far as relabeling the file system goes, the rules apply to processes and objects, not to programs. The label on a program describes who can access it, it will run with the label of the process that exec's it. A change in the rules does not require a change to the labels on the file system for things to work according to the rules of engagement.
By this logic, every program will always have the same label, unless you recode every program to explicitly change it when it starts; precisely the thing that the SELinux type transitions were designed to avoid.
Yes. This is the way it should be. A small set of very carefully analysed programs that change labels under carefully controlled circumstances is what I want. login, sshd, cron, special purpose launchers. Written with the assumption that they will be attacked.
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.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
When you change the meaning of new types, you clearly would need to first reload the policy then relaunch programs or relabel files to take advantage of the new types, otherwise they would be categorically ignored by the system.
I'm sorry, but again, I don't know what you mean by "changing the meaning of new types".
Oh, say something like "Oh, drat, I wanted this daemon to run as some other type".
Sorry, "type" is a meaningless attribute in Smack.
Sorry for being unclear. Assume s/type/label/g; the question still stands.
Quoted 3 lines
Quoted 1 line
Unless you relabel the files and relaunch the daemon the system will have no idea how the system will change. And if you let arbitrary root processes relabel things on the fly then you've lost all the security advantages to a MAC system.
MAC systems have been behaving this way for decades. SELinux is the exception, not the rule on this.
"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.
Quoted 5 lines
Quoted 3 lines
I think you may be making assumptions about the behaviour of SELinux based on what other OSes do which don't hold:
(a) SELinux does not care about user id, current directory, time of day, etc. It cares solely about 3 things: the Subject, the Object, and the Action. For example, if an init script attempts to execute the apache binary then SELinux gets the following data for parameters: subject="system_u:system_r:initrc_t:SystemLow-SystemHigh" object="system_u:object_r:httpd_exec_t:SystemLow" action="file->execute".
Yes, and each of the components of the subject and object contexts is dependent on a more circumstances than I'd care to deal with. You've demonstrated that SELinux implements fine granularity.
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.
Quoted 3 lines
Quoted 1 line
(b) SELinux does NOT have a capability which overrides it. If you want to do something that the policy categorically does not allow, you have 2 choices: change the policy or disable SELinux. You can also use a policy which disables both of those options
Yup. I think that's bad.
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.
Quoted 1 line
And Bell & LaPadula using a combination of levels and categories is probably the Smack worst case. But guess what? The dig against that policy has always been that no one wanted to combine levels and categories.
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.
Quoted 3 lines
Quoted 1 line
Ok, fine, how does "moving data around a system" require anything more than bog-standard user-level privileges? Normal users under Linux are not permitted to change "security.*" attributes at all, but they may bind to sockets, etc. You can define a "capability" which lets you do all that, but then you're just blindly giving processes more privileges than they need to complete an operation. Why should you get the "rename all files" priv when all you need is "Make my log files get $LABEL when I put them in
/var/log/mydaemon/"?Privilege granularity is a seperate issue. Smack uses Linux privilege machanisms and is happy to do so.
"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.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Why should it? Admittedly, moving data from "TopSecret" to "Secret" requires a process labeled with a range including at least "S-TS" *and* with the MLS "read-to-clearance" attribute, but you can be as stingy with that attribute as you like.
Yup. And plenty of people like you think that is really spiffy.
Please explain why you think it isn't?
I grew up believing that downgrading classified information should always be an explicit, concious act.
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.
Quoted 11 lines
Quoted 9 lines
You can call them "process capabilities" or "magic attributes", they're the same thing, just more fine-grained. Instead of (Note: r1 == subject role, r2 == target role, t2 == target type):
mlsconstrain process transition ( (r1 == r2) || (t1 ==
i_am_a_role_changing_capability) )you have (Note: t1 == subject type):
mlsconstrain process transition ( (r1 == r2) || (r1 == system_r&& t1 ==
i_am_a_login_process&& t2 ==i_am_a_user_entrypoint) )The latter is like the former, except instead of one single ultimate "change-any-role" capability, you have a capability which allows a system login process to change roles *ONLY* if it's also changing to a user entrypoint. Please tell me which you think is more secure.
Don't look at me. A well written program could do fine with either.
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.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
So the implicit labeling of files actually restricts every process *FURTHER*. They no longer have even an inkling of a choice about file labeling, and that's a GOOD thing.
That's true about Smack, you know. The process has no choice about the label that the files get.
So how do you selectively label files based on criteria such as "where did I get put"? How do you distinguish between a "log file" which is create-and-append-only, a "database file" which I can modify however I want to, and a "unix socket" which I can bind in
/var/runand get connections from user processes?I don't. They're all objects.
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.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Thank you for your comments. I hope that I have made the behavior and value of Smack clearer in responding to them.
You're welcome. I endeavor to poke my nose into every little LSM-related corner in the kernel, this one included.
Why?
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
Quoted 6 lines · Kyle Moffett
Quoted 1 line · Casey Schaufler
Your boolean solution requires more forthought than the Smack rule solution, but I'll give it to you once you've fleshed out your "##" lines.
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.
nit: without the selinux policy server (which is not production ready by any means) we have to grant the same to cron in this case (or at least to the domain that cron runs the cronjobs in). SELinux and Smack alike need special permissions to modify the running policy, no surprises there.
Quoted 7 lines · Joshua Brindle
Quoted 4 lines · Kyle Moffett
Quoted 1 line · Casey Schaufler
Your boolean solution requires more forthought than the Smack rule solution, but I'll give it to you once you've fleshed out your "##" lines.
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.
nit: without the selinux policy server (which is not production ready by any means) we have to grant the same to cron in this case (or at least to the domain that cron runs the cronjobs in). SELinux and Smack alike need special permissions to modify the running policy, no surprises there.
Yeah, I figured this out a couple minutes ago. Turns out you can get a similar effect with a little properly labeled shell script though (text included in my last email), but it does decrease overall system security.
Cheers,
Kyle Moffett
Casey Schaufler
maintainerQuoted 5 lines · --- Kyle Moffett
<really big snip>
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?
Those that refer to object accesses and those that do not. The former are generally interesting, the latter are generally not. That's a rule of thumb, mind you. Anyway, have a look at the hook table, it's in smack_lsm.c
Quoted 5 lines
Quoted 2 lines
The point you make, that you need to have that in order to create a policy description, is one of the reasons for Smack. Simplified.
Well yes, but a simplified policy is useless if it uses no LSM hooks.
As above, that's smack_lsm.c, a little over 2000 lines of good old fashioned C code.
Quoted 8 lines
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.
It's all spelled out in the module. Go wild.
Quoted 7 lines
<another major snip>
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.
Ok.
Quoted 24 lines
Quoted 22 lines
Quoted 13 lines
Whoops, I think I must have smashed the delete key or something while sending. Here's the paragraphs which got elided:
Well, yes, but a policy which completely ignores future expandability can't be expanded upon regardless. It would also be very hard to add new policy without a lot of duplication under your system. On the other hand, with SELinux you can very easily add attribute-based policy so adding new capabilities is as simple as sticking existing attributes on newly defined types. For example:
type
my_log_t,file_type,log_file;
typemy_log_daemon, daemon;Quoted 8 lines
Right there I just gave permission for the logrotate to recycle files labelled
my_log_t, which the sysadmin and audit admin can also read (and the audit admin can delete). I also gave permission for my daemon to send SIGCHLD to init, and forinit/initscripts to send it a SIGTERM/SIGQUIT. All without writing a SINGLE policy rule. Basically all of those existing behaviors are found in allow rules built on the "file_type", "log_file", and "daemon" attributes.Quoted 1 line
Ah, now you're refering to the reference policy, right?
Quoted 9 lines
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.
After you have the 400,000 lines of reference policy behind it.
Quoted 20 lines
Quoted 17 lines
Quoted 9 lines
Quoted 8 lines
They can be added or changed one by one as required while the system is running, and there are uses that exploit that. One example is to put the label "Game" on certain programs and:
at 8:00am "Worker Game no"
at 5:00pm "Worker Game x"Thus Worker processes can access Game files only during off hours.
Quoted 7 lines
This is fundamentally broken:
[...]
Secondly, you can already do the same thing with DAC and a PAM groups-from-time-of-day module, I don't see why such a thing is special enough to need MAC. Thirdly, I could do exactly the same thing with an SELinux boolean and a cronjob (once we get proper revoke support):Quoted 2 lines
There is usually a way to address any particular problem using DAC, it's often sufficiently painful that MAC looks like a better approach.
Quoted 7 lines
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?
HeeHee. Don't think heart monitor, think in-car trip recorder. The games can only be used when the car's at rest. It's a strange world we live in today.
Quoted 7 lines
<Another big snip>
Quoted 4 lines
Yes. This is the way it should be. A small set of very carefully analysed programs that change labels under carefully controlled circumstances is what I want. login, sshd, cron, special purpose launchers. Written with the assumption that they will be attacked.
Quoted 12 lines
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.
I don't think we're debating the same issues any more. I can see that you are well versed in the nuances of SELinux behavior. I understand what SELinux does, and the arguements in it's favor. I don't see that the complexity it requires is necessary in many cases.
Quoted 8 lines
Quoted 7 lines
Quoted 4 lines
Unless you relabel the files and relaunch the daemon the system will have no idea how the system will change. And if you let arbitrary root processes relabel things on the fly then you've lost all the security advantages to a MAC system.
MAC systems have been behaving this way for decades. SELinux is the exception, not the rule on this.
Quoted 6 lines
"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.
That sword cuts both ways, you know. And if a complex system is intractable for an environment it cannot make you feel more secure.
I think that below here it's all philosophical differences based on significantly different experiance and goals. Can you run SELinux successfully on an 2 megahertz ARM processor with 8 meg of ram, and no labeled file systems? I don't know that Smack will ever be as appropriate for an enterprise server as SELinux is today, but time will tell.
Casey Schaufler
[email protected]
Hi!
Quoted 10 lines
Quoted 8 lines
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.
It's all spelled out in the module. Go wild.
Kyle claims he can emulate SMACK with SELinux + perl script, but I don't think it is fair to force him to write that perl. You want the code merged, so it should be up to you to do the work... or acknowledge that selinux ineed is smack supperset and argue that SMACK is better, anyway, because of its simplicity / speed / something.
Or maybe that perl script is impossible to write for some reason? Tell us if so...
Pavel
(who is no security expert)
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Casey Schaufler
maintainerQuoted 11 lines · --- Pavel Machek
Hi!
Quoted 9 lines
Quoted 8 lines
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.
Quoted 4 lines
Quoted 1 line
It's all spelled out in the module. Go wild.
Kyle claims he can emulate SMACK with SELinux + perl script, but I don't think it is fair to force him to write that perl.
It would not surprise me particularly much if Kyle or someone like him could produce a perl script that could generate an SELinux policy that, when added to the reference policy on a system described by the reference policy, could do a fair imitation of the Smack scheme.
One point that I would like to make clear however is that the requirement for a 400,000 line reference policy for a jumping off point is one of the reasons for Smack. Another point that I think is important, and the rationale behind my being a butt on this (sorry, Kyle, I knew some one would come after me like this, I wasn't aiming at you) is that I have seen several cases where the flexability and capability of SELinux policy has been asserted but the followthrough was missing. I am interested in seeing what an SELinux policy to do what Smack does would look like. I personally though it would be easier to write an LSM than to write that policy.
Quoted 3 lines
You want the
code merged, so it should be up to you to do the work... or acknowledge that selinux ineed is smack supperset
I acknowledge that I do not know how to prove that there is no way, using any and all of the facilities of SELinux, to duplicate any particular facility of Smack.
I do not acknowledge it as a superset. I am not convinced that all of the proposed SELinux eqivalence claims would actually result in working systems.
Quoted 2 lines
and argue that SMACK
is better, anyway, because of its simplicity / speed / something.
My understanding of the current SELinux philosophy is that policy should only be written by professionals, and that this was "always" the intention. I respect that, and for policy that requires the level of sophistication that SELinux does I would have a hard time arguing otherwise.
One of the things that limited the widespread adoption of MLS systems was that the policy, even one as simple as Bell & LaPadula, was considered to complex for most uses. I do not see that SELinux, or AppArmor for that matter, addresses this fundimental impediment to the use of mandatory access control. Yes, you can do just about anything with the right combination of classes, booleans, and other interesting facilities, but you can't do simple things directly.
I was actually quite pleased to see the beginings of an SELinux policy "equivalent" for Smack. I am disappointed that there is insufficient wind in the sails to follow through with it. I would like to compare, contrast, and benchmark against it. I just don't want to write it.
Quoted 2 lines
Or maybe that perl script is impossible to write for some reason? Tell us if so...
Goodness Pavel, it's perl! A good sysadmin can do anything in perl! Seriously, maybe he could do it. For the reasons above, I'd be happy to see the attempt. I would love to debate the Smack vs. SELinux question with real data. I am not much concerned with comparisons based on assertion and speculation. I have gotten some very good, meaty comparison data for guardbox applications (Thanks Joshua) and I look forward to more.
Quoted 2 lines
Pavel
(who is no security expert)
You just don't want the rock star lifestyle.
... And thank you for suggestions.
Casey Schaufler
[email protected]
Btw, at:
diff -uprN -X linux-2.6.22-base/Documentation/dontdiff linux-2.6.22-base/security/smack/Kconfig linux-2.6.22/security/smack/Kconfig
--- linux-2.6.22-base/security/smack/Kconfig 1969-12-31
16:00:00.000000000 -0800
+++ linux-2.6.22/security/smack/Kconfig 2007-07-10 01:08:05.000000000 -0700 @@ -0,0 +1,10 @@
+config SECURITY_SMACK
+ bool "Simplified Mandatory Access Control Kernel Support" + depends on NETLABEL && SECURITY_NETWORK + default n + help
+ This selects the Simplified Mandatory Access Control Kernel.
+ SMACK is useful for sensitivity, integrity, and a variety
+ of other madatory security schemes.
+ If you are unsure how to answer this question, answer N.
+
change:
+ of other madatory security schemes.
to:
+ of other mandatory security schemes.
Signature · 2 lines
Miguel Ojeda http://maxextreme.googlepages.com/index.htm
Finally moved back in and with internet. Yay!
Quoted 1 line · Casey Schaufler
It would not surprise me particularly much if Kyle or someone like him could produce a perl script that could generate an SELinux policy that, when added to the reference policy on a system described by the reference policy, could do a fair imitation of the Smack scheme.
Umm, when did I ever say "emulate smack on top of the reference policy"? I state categorically that I can write an estimated 500 line perl script which will generate a standalone SELinux policy based directly on a smack ruleset. It would require no additional policy beyond what the script outputs, and the script would be only roughly 500 lines so it can't contain all that much direct source-to-output text.
I've started tinkering with that perl script, though I probably won't get it finished till tomorrow or sunday.
Quoted 1 line
One point that I would like to make clear however is that the requirement for a 400,000 line reference policy for a jumping off point is one of the reasons for Smack.
There is no "requirement" for a 400,000-line reference policy to reproduce exactly the behavior of SMACK. The SMACK architecture is trivial and therefore the SELinux policy is also simple.
Quoted 3 lines
Quoted 1 line
and argue that SMACK is better, anyway, because of its simplicity / speed / something.
My understanding of the current SELinux philosophy is that policy should only be written by professionals, and that this was "always" the intention. I respect that, and for policy that requires the level of sophistication that SELinux does I would have a hard time arguing otherwise.
I can also state categorically that given the set of all admins, users, and software developers, hardly a fraction of them are qualified to write security policy at all. Hell, most admins and software developers can't get SUID binaries right, and that's a thousand times simpler than a MAC security policy. Ergo the only people who should be writing security policy for deployment are those people who have studied and trained in the stuff. Those people are also known as "security professionals".
Quoted 1 line
One of the things that limited the widespread adoption of MLS systems was that the policy, even one as simple as Bell & LaPadula, was considered to complex for most uses. I do not see that SELinux, or AppArmor for that matter, addresses this fundimental impediment to the use of mandatory access control. Yes, you can do just about anything with the right combination of classes, booleans, and other interesting facilities, but you can't do simple things directly.
Neither security nor your average distro nowadays is "simple" by any stretch of the imagination. Hell, my desktop system hits at least 2 million unique lines of code during boot, let alone logging in to XFCE. If you can show me a security system other than SELinux which is sufficiently flexible to secure those 2 million lines of code along with the other 50 million lines of code found in various pieces of software on my Debian box then I'll go put on my dunce hat and sit in the corner.
Cheers,
Kyle Moffett
Quoted 5 lines · Kyle Moffett
XFCE. If you can show me a security system other than SELinux which is sufficiently flexible to secure those 2 million lines of code along with the other 50 million lines of code found in various pieces of software on my Debian box then I'll go put on my dunce hat and sit in the corner.
/me hands Kyle a dunce cap. :)
Unfortunately, I have to agree that both AppArmor and Smack have at least the potential of qualifying as "securing the 2M lines of code".
The part that Kyle forgot was what most evals these days call the "protection profile" - What's the threat model, who are you defending against, and just how good a job does it have to do? I'll posit that for a computer that is (a) not networked, (b) doesn't process sensitive information, and (c) has reasonable physical security, a security policy of "return(permitted);" for everything may be quite sufficient.
(Of course, I also have boxes where "the SELinux reference policy with all the MCS extensions plus all the LSPP work" is someplace I'm trying to get to).
Quoted 8 lines · On Aug 19, 2007, at 17:12:41, [email protected] wrote:
Quoted 1 line · Kyle Moffett
If you can show me a security system other than SELinux which is sufficiently flexible to secure those 2 million lines of code along with the other 50 million lines of code found in various pieces of software on my Debian box then I'll go put on my dunce hat and sit in the corner.
/me hands Kyle a dunce cap. :)
Unfortunately, I have to agree that both AppArmor and Smack have at least the potential of qualifying as "securing the 2M lines of code".
The part that Kyle forgot was what most evals these days call the "protection profile" - What's the threat model, who are you defending against, and just how good a job does it have to do? I'll posit that for a computer that is (a) not networked, (b) doesn't process sensitive information, and (c) has reasonable physical security, a security policy of "return(permitted);" for everything may be quite sufficient.
Well, in this case the "box" I want to secure will eventually be running multi-user X on a multi-level-with-IPsec network. For that kind of protection profile, there is presently no substitute for SELinux with some X11 patches. AppArmor certainly doesn't meet the confidentiality requirements (no data labelling), and SMACK has no way of doing the very tight per-syscall security requirements we have to meet. I didn't make this clear initially but that is the kind of system I'm talking about wanting to secure some 50 million lines of code on.
Quoted 1 line
(Of course, I also have boxes where "the SELinux reference policy with all the MCS extensions plus all the LSPP work" is someplace I'm trying to get to).
Well, for some of the systems we distribute, "all the MCS extensions plus all the LSPP work" is nowhere near enough security; we need full-fledged multi-level-security, role-based-access-control, and specific per-daemon MAC restrictions.
Cheers,
Kyle Moffett
Casey Schaufler
maintainerQuoted 21 lines · --- Kyle Moffett
Quoted 12 lines · On Aug 19, 2007, at 17:12:41, [email protected] wrote:
Quoted 5 lines · Kyle Moffett
If you can show me a security system other than SELinux which is sufficiently flexible to secure those 2 million lines of code along with the other 50 million lines of code found in various pieces of software on my Debian box then I'll go put on my dunce hat and sit in the corner.
/me hands Kyle a dunce cap. :)
Unfortunately, I have to agree that both AppArmor and Smack have at least the potential of qualifying as "securing the 2M lines of code".
Quoted 7 lines
The part that Kyle forgot was what most evals these days call the "protection profile" - What's the threat model, who are you defending against, and just how good a job does it have to do? I'll posit that for a computer that is (a) not networked, (b) doesn't process sensitive information, and (c) has reasonable physical security, a security policy of "return(permitted);" for everything may be quite sufficient.
Quoted 7 lines
Well, in this case the "box" I want to secure will eventually be running multi-user X on a multi-level-with-IPsec network. For that kind of protection profile, there is presently no substitute for SELinux with some X11 patches. AppArmor certainly doesn't meet the confidentiality requirements (no data labelling), and SMACK has no way of doing the very tight per-syscall security requirements we have to meet.
And what requirements would those be? Seriously, I've done Common Criteria and TCSEC evaluations on systems with less flexibility and granularity than Smack that included X, NFSv3, NIS, clusters, and all sorts of spiffy stuff. I mean, if the requirement is anything short of "runs SELinux" I have good reason to believe that a Smack based system is up to it.
Quoted 3 lines
I didn't make this clear initially but that is the kind of system I'm talking about wanting to secure some 50 million lines of code on.
Cool. SELinux provides one approach to dealing with that, and the huge multiuser general purpose machine chuck full of legacy software hits the SELinux sweet spot.
Quoted 8 lines
Quoted 3 lines
(Of course, I also have boxes where "the SELinux reference policy with all the MCS extensions plus all the LSPP work" is someplace I'm trying to get to).
Well, for some of the systems we distribute, "all the MCS extensions plus all the LSPP work" is nowhere near enough security; we need full- fledged multi-level-security, role-based-access-control, and specific per-daemon MAC restrictions.
Sounds like more of what SELinux is good for.
Casey Schaufler
[email protected]
Quoted 4 lines · Casey Schaufler
Quoted 1 line · --- Kyle Moffett
Well, in this case the "box" I want to secure will eventually be running multi-user X on a multi-level-with-IPsec network. For that kind of protection profile, there is presently no substitute for SELinux with some X11 patches. AppArmor certainly doesn't meet the confidentiality requirements (no data labelling), and SMACK has no way of doing the very tight per-syscall security requirements we have to meet.
And what requirements would those be? Seriously, I've done Common Criteria and TCSEC evaluations on systems with less flexibility and granularity than Smack that included X, NFSv3, NIS, clusters, and all sorts of spiffy stuff.
These are requirements more of the "give the client warm fuzzies". On the other hand, when designing a box that could theoretically be run on a semi-public unclassified network and yet still be safe enough to run classified data over IPsec links, you want to give the client all the warm fuzzies they ask for and more.
Quoted 1 line
I mean, if the requirement is anything short of "runs SELinux" I have good reason to believe that a Smack based system is up to it.
"up to it", yes, but I think you'll find that beyond the simplest policies, an SELinux policy that properly uses the SELinux infrastructure will be much shorter than the equivalent SMACK policy, not even including all the things that SELinux does and SMACK doesn't.
Quoted 3 lines
Quoted 1 line
I didn't make this clear initially but that is the kind of system I'm talking about wanting to secure some 50 million lines of code on.
Cool. SELinux provides one approach to dealing with that, and the huge multiuser general purpose machine chuck full of legacy software hits the SELinux sweet spot.
Well, given that 99.9% of the systems people are really concerned about security on are multi-user general-purpose machines chuck full of legacy software, that seems to work just fine. If it's a single-user box then you don't even need MAC, just a firewall, a good locked rack/case/keyboard/etc, and decent physical security. If it's entirely custom-controlled software then you can just implement the "MAC" entirely in your own software. "General-purpose" vs "special-purpose" is debatable, so I'll just leave that one lie.
Replying to another email:
Quoted 3 lines
Quoted 1 line
but you written it in wrong language. You written it in C, while you should have written it in SELinux policy language (and your favourite scripting language as frontend).
I have often marvelled at the notion of a simplification layer. I believe that you build complex things on top of simple things, not the other way around.
There is no "one answer" to this question in software development. Generally you prioritize things based on maximizing maintainability and speed and minimizing code, bugs, and complexity. Those are often both conflicting and in agreement. Here are a few common examples of simple-thing-on-complex-thing:
* pthreads on top of clone() * open(some_string) on top of all the complex VFS machinery * "netcat" on top of the vast Linux network stack including
support for arbitrary packet filtering and transformation.
In addition, "simple" is undesirable if it makes the implementation less generic for no good reason. Would you want to use the "simple" MS Windows disk-drive model under Linux? Every disk is its own letter and has its files under it. Oh, you wanted to mount a filesystem over C:\tmp? Sorry, we don't support that, too bad. Under Linux we have a very flexible and powerful VFS which lets you do very crazy things, and then for the user's convenience we have various "simple" interfaces (like Gnome/KDE/XFCE).
Software development is very much about finding the Right Model(TM) to underlie the system, and then building any simplifications-to-the-user on top of the very simple model.
Look at the SELinux model again; it has the following things:
(A) Labels on almost-all user-visible kernel objects
(B) Individual access rules for almost every operation on those
objects
(C) "Transition" rules to set the label on newly created objects.
(D) Fundamental "constraints" which enforce hard limits on what
may be permitted with "allow" rules
From a fundamental standpoint it's harder to get much simpler than that. On top of that model, we also have a bit of additional *flexibility* for MLS/RBAC, although that flexibility may be ignored completely.
(1) You can define "users" which may only assume some "roles"
(2) You can define "roles" may only run in some "types"
(3) There's a simple way of declaring multiple "levels" and
"dominance".
So you see, SELinux is a pretty fundamental description of the degrees of flexibility needed to secure everything. That kind of FUNDAMENTAL description is what belongs in the kernel. Anything else can and should be built on top with better libraries and/or user interfaces.
As for the script, I'm partway through debugging it but my time is all chewed up with other stuff now, so it may take me an extra couple days.
Cheers,
Kyle Moffett
Casey Schaufler
maintainerQuoted 10 lines · --- Kyle Moffett
Quoted 9 lines · Casey Schaufler
Quoted 7 lines · --- Kyle Moffett
Well, in this case the "box" I want to secure will eventually be running multi-user X on a multi-level-with-IPsec network. For that kind of protection profile, there is presently no substitute for SELinux with some X11 patches. AppArmor certainly doesn't meet the confidentiality requirements (no data labelling), and SMACK has no way of doing the very tight per-syscall security requirements we have to meet.
Quoted 6 lines
Quoted 4 lines
And what requirements would those be? Seriously, I've done Common Criteria and TCSEC evaluations on systems with less flexibility and granularity than Smack that included X, NFSv3, NIS, clusters, and all sorts of spiffy stuff.
These are requirements more of the "give the client warm fuzzies".
OK, that's perfectly reasonable. If the client has been sold on the concept of SELinux the client will get warm fuzzies only from SELinux. Security is how you feel about it, after all.
Quoted 4 lines
On the other hand, when designing a box that could theoretically be run on a semi-public unclassified network and yet still be safe enough to run classified data over IPsec links, you want to give the client all the warm fuzzies they ask for and more.
Yes. Of course, a little hard technology behind it doesn't hurt, either.
Quoted 6 lines
Quoted 2 lines
I mean, if the requirement is anything short of "runs SELinux" I have good reason to believe that a Smack based system is up to it.
"up to it", yes, but I think you'll find that beyond the simplest policies, an SELinux policy that properly uses the SELinux infrastructure will be much shorter than the equivalent SMACK policy,
Well, I find that hard to believe. Maybe I'm only thinking of what you would consider the simplest policies.
Quoted 1 line
not even including all the things that SELinux does and SMACK doesn't.
Of course.
Quoted 10 lines
Quoted 6 lines
Quoted 2 lines
I didn't make this clear initially but that is the kind of system I'm talking about wanting to secure some 50 million lines of code on.
Cool. SELinux provides one approach to dealing with that, and the huge multiuser general purpose machine chuck full of legacy software hits the SELinux sweet spot.
Well, given that 99.9% of the systems people are really concerned about security on are multi-user general-purpose machines chuck full of legacy software, that seems to work just fine.
Err, no. By unit count such systems are extremely rare. There is tremendous concern for security in your cell phone, your DVR, your PDA, and even your toaster.
Quoted 3 lines
If it's a single-
user box then you don't even need MAC, just a firewall, a good locked rack/case/keyboard/etc, and decent physical security.
You cell phone has really lousy physical security.
Quoted 4 lines
If it's
entirely custom-controlled software then you can just implement the "MAC" entirely in your own software. "General-purpose" vs "special- purpose" is debatable, so I'll just leave that one lie.
Indeed. Total control over the software on your phone is not a competetive option for a provider.
Quoted 10 lines
Replying to another email:
Quoted 7 lines
Quoted 3 lines
but you written it in wrong language. You written it in C, while you should have written it in SELinux policy language (and your favourite scripting language as frontend).
I have often marvelled at the notion of a simplification layer. I believe that you build complex things on top of simple things, not the other way around.
There is no "one answer" to this question in software development.
You're correct. Can I quote you on that?
Quoted 14 lines
Generally you prioritize things based on maximizing maintainability and speed and minimizing code, bugs, and complexity. Those are often both conflicting and in agreement. Here are a few common examples of simple-thing-on-complex-thing:
...Look at the SELinux model again; it has the following things:
(A) Labels on almost-all user-visible kernel objects
(B) Individual access rules for almost every operation on those
objects
(C) "Transition" rules to set the label on newly created objects.
(D) Fundamental "constraints" which enforce hard limits on what
may be permitted with "allow" rules
Quoted 2 lines
From a fundamental standpoint it's harder to get much simpler than
that.
It's easy to get simpler than that:
(A) Labels on all objects and subjects
(B) Access rules for subjects and objects
No transformations. Operations in terms of rwx. lots simpler.
Quoted 8 lines
On top of that model, we also have a bit of additional
*flexibility* for MLS/RBAC, although that flexibility may be ignored completely.
(1) You can define "users" which may only assume some "roles"
(2) You can define "roles" may only run in some "types"
(3) There's a simple way of declaring multiple "levels" and
"dominance".
Quoted 5 lines
So you see, SELinux is a pretty fundamental description of the degrees of flexibility needed to secure everything. That kind of FUNDAMENTAL description is what belongs in the kernel. Anything else can and should be built on top with better libraries and/or user interfaces.
I don't believe that. I understand that some people do.
Quoted 3 lines
As for the script, I'm partway through debugging it but my time is all chewed up with other stuff now, so it may take me an extra couple days.
Curse that day job!
Thank you.
Casey Schaufler
[email protected]
Casey Schaufler
maintainerQuoted 5 lines · --- Kyle Moffett
...
As for the script, I'm partway through debugging it but my time is all chewed up with other stuff now, so it may take me an extra couple days.
Any progress on this?
Casey Schaufler
[email protected]
Casey Schaufler
maintainerQuoted 9 lines · --- Kyle Moffett
Finally moved back in and with internet. Yay!
Quoted 5 lines · Casey Schaufler
It would not surprise me particularly much if Kyle or someone like him could produce a perl script that could generate an SELinux policy that, when added to the reference policy on a system described by the reference policy, could do a fair imitation of the Smack scheme.
Quoted 4 lines
Umm, when did I ever say "emulate smack on top of the reference policy"? I state categorically that I can write an estimated 500 line perl script which will generate a standalone SELinux policy based directly on a smack ruleset.
Even better.
Quoted 4 lines
It would require no additional
policy beyond what the script outputs, and the script would be only roughly 500 lines so it can't contain all that much direct source-to- output text.
Better still.
Quoted 2 lines
I've started tinkering with that perl script, though I probably won't get it finished till tomorrow or sunday.
Ok. I've been a developement manager, so I'll expect it Thursday. (That's a Pointy Haired Manager joke, BTW)
Quoted 7 lines
Quoted 3 lines
One point that I would like to make clear however is that the requirement for a 400,000 line reference policy for a jumping off point is one of the reasons for Smack.
There is no "requirement" for a 400,000-line reference policy to reproduce exactly the behavior of SMACK. The SMACK architecture is trivial
I prefer "simple" over "trivial", but yes, you have the nut of it.
Quoted 1 line
and therefore the SELinux policy is also simple.
Well, that's what the exercise is out to demonstrate. I admit to being curious to see the proposed policy.
Quoted 9 lines
Quoted 8 lines
Quoted 2 lines
and argue that SMACK is better, anyway, because of its simplicity / speed / something.
My understanding of the current SELinux philosophy is that policy should only be written by professionals, and that this was "always" the intention. I respect that, and for policy that requires the level of sophistication that SELinux does I would have a hard time arguing otherwise.
Quoted 3 lines
I can also state categorically that given the set of all admins, users, and software developers, hardly a fraction of them are qualified to write security policy at all.
I can understand your postion on the SELinux policy.
Quoted 2 lines
Hell, most admins and
software developers can't get SUID binaries right,
Sadly true.
Quoted 2 lines
and that's a
thousand times simpler than a MAC security policy.
Now you see, I don't agree with that. It's simpler than an SELinux policy. It's not simpler than a Bell & LaPadula (once we were able to get past the initial resistance to MAC and get someone a three day training class they were able to do some cool things) and it's certainly not simpler than Smack.
Quoted 4 lines
Ergo the only
people who should be writing security policy for deployment are those people who have studied and trained in the stuff. Those people are also known as "security professionals".
If only security professionals can use the system you have failed to provide a general purpose facility. It may have value in limited circumstances but it is not for everybody.
Quoted 8 lines
Quoted 7 lines
One of the things that limited the widespread adoption of MLS systems was that the policy, even one as simple as Bell & LaPadula, was considered to complex for most uses. I do not see that SELinux, or AppArmor for that matter, addresses this fundimental impediment to the use of mandatory access control. Yes, you can do just about anything with the right combination of classes, booleans, and other interesting facilities, but you can't do simple things directly.
Quoted 8 lines
Neither security nor your average distro nowadays is "simple" by any stretch of the imagination. Hell, my desktop system hits at least 2 million unique lines of code during boot, let alone logging in to XFCE. If you can show me a security system other than SELinux which is sufficiently flexible to secure those 2 million lines of code along with the other 50 million lines of code found in various pieces of software on my Debian box then I'll go put on my dunce hat and sit in the corner.
It is my position that the SELinux reference policy fails the "small enough to analyze" clause of the TCB principle. As a result SELinux does not help me feel secure. Restating the complexity of the applications in the policy is arguably an improvement, but I can't help but think the effort would be better put into fixing the applications.
So long as your definition of "secure" allows for something other than "runs SELinux", and so long as you are willing to accept the conclusions of "security professionals", I can point to several examples of systems that have been evaluated using other mechanisms. There aren't other mechanisms upstream in Linux yet.
Casey Schaufler
[email protected]
Hi!
Quoted 8 lines
Quoted 4 lines
Ergo the only
people who should be writing security policy for deployment are those people who have studied and trained in the stuff. Those people are also known as "security professionals".If only security professionals can use the system you have failed to provide a general purpose facility. It may have value in limited circumstances but it is not for everybody.
But that's okay. Maybe SElinux is not simple enough to use for everyone, but that does not mean you can't auto-generate policy from something else, "easy to understand".
IOW smack may be great idea, but you written it in wrong language. You written it in C, while you should have written it in SELinux policy language (and your favourite scripting language as frontend).
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Casey Schaufler
maintainerQuoted 7 lines · --- Pavel Machek
Hi!
Quoted 5 lines
Quoted 4 lines
Ergo the only
people who should be writing security policy for deployment are those people who have studied and trained in the stuff. Those people are also known as "security professionals".
Quoted 7 lines
Quoted 3 lines
If only security professionals can use the system you have failed to provide a general purpose facility. It may have value in limited circumstances but it is not for everybody.
But that's okay. Maybe SElinux is not simple enough to use for everyone, but that does not mean you can't auto-generate policy from something else, "easy to understand". IOW smack may be great idea,
Thank you.
Quoted 3 lines
but you written it in wrong language. You
written it in C, while you should have written it in SELinux policy language (and your favourite scripting language as frontend).
I have often marvelled at the notion of a simplification layer. I believe that you build complex things on top of simple things, not the other way around.
Casey Schaufler
[email protected]
Quoted 8 lines
Quoted 4 lines
but you written it in wrong language. You
written it in C, while you should have written it in SELinux policy language (and your favourite scripting language as frontend).I have often marvelled at the notion of a simplification layer. I believe that you build complex things on top of simple things, not the other way around.
As we have to maintain selinux, anyway, I don't see why simplification layer is a problem.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Casey Schaufler
maintainerQuoted 11 lines · --- Pavel Machek
Quoted 8 lines
Quoted 4 lines
but you written it in wrong language. You
written it in C, while you should have written it in SELinux policy language (and your favourite scripting language as frontend).I have often marvelled at the notion of a simplification layer. I believe that you build complex things on top of simple things, not the other way around.
As we have to maintain selinux, anyway, I don't see why simplification layer is a problem.
It's an issue if you want to do simple things, have the resources to do simple things, but go over budget because the simple things are built on top of complex things that you don't need. I see this crop up frequently with IT infrastructures, where simple problems get solved using completely unnecessary components just because those components are available. If you want to maintain an SELinux policy that looks like it does smackish things in addition to the reference policy that's OK by me.
Casey Schaufler
[email protected]
Quoted 9 lines · Casey Schaufler
Quoted 2 lines
As we have to maintain selinux, anyway, I don't see why simplification layer is a problem.
It's an issue if you want to do simple things, have the resources to do simple things, but go over budget because the simple things are built on top of complex things that you don't need. I see this crop up frequently with IT infrastructures, where simple problems get solved using completely unnecessary components just because those components are available.
class LinkedList {} for example. Just look how simple the linux kernel does it ;-)
Jan
Quoted 2 lines · Casey Schaufler
"*" - pronounced "star"
wall
Quoted 1 line
"_" - pronounced "floor"
floor
Quoted 1 line
"^" - pronounced "hat"
roof
Quoted 1 line
"?" - pronounced "huh"
it's dark in here :)
security/smack/Kconfig line 3
Quoted 3 lines
security/smack/Kconfig +3
-0+config SECURITY_SMACK + bool "Simplified Mandatory Access Control Kernel Support" + depends on NETLABEL && SECURITY_NETWORK
Is this a hard dependency, or can this work without network sec labels?
security/smack/Kconfig line 9
Quoted 6 lines
security/smack/Kconfig +6
-0+ default n + help + This selects the Simplified Mandatory Access Control Kernel. + SMACK is useful for sensitivity, integrity, and a variety + of other madatory security schemes. + If you are unsure how to answer this question, answer N.
I smell broken tabs.
security/smack/Makefile line 7
Quoted 9 lines
+++ linux-2.6.22/security/smack/Makefile 2007-07-10 01:08:05.000000000 -0700
security/smack/Makefile +7
-0@@ -0,0 +1,8 @@ +# +# Makefile for the SMACK LSM +# + +obj-$(CONFIG_SECURITY_SMACK) := smack.o + +smack-y := smack_lsm.o smack_access.o smackfs.o
smack-objs :=
security/smack/smack_access.c line 5
Quoted 7 lines
security/smack/smack_access.c +6
-0+++ linux-2.6.22/security/smack/smack_access.c 2007-07-24 15:36:18.000000000 -0700@@ -0,0 +1,113 @@ +extern struct smk_list_entry *smack_list; + +static int smk_get_access (smack_t sub,smack_t obj) +{ +struct smk_list_entry *sp = smack_list;
proposes const struct. should be used elsewhere too.
security/smack/smack_access.c line 43
Quoted 1 line
security/smack/smack_access.c +1
-0+if (sub ==SMK_STAR )
I just remember MechWarrior2 (game from Activison), where SMK stood for their movie format... it's also a nice abbreviation for Seamonkey (browser suite).
security/smack/smack_access.c line 64
Quoted 5 lines
security/smack/smack_access.c +5
-0+if (sub ==SMK_HAT && ((request &MAY_ANYREAD ) == request)) +return 0 ; + +if (obj ==SMK_FLOOR && ((request &MAY_ANYREAD ) == request)) +return 0 ;
Redundant parentheses, be gone.
Never was it easier to say what ^ is called in your language :)
if (sub == '^' && ...) return 0; if (obj == '_' && ...)
security/smack/smack_access.c line 100
Quoted 7 lines
security/smack/smack_access.c +7
-0+/* +* The value that this adds is that everything after any +* character that's not allowed in a smack will be null +*/ +smack_t smk_from_string (char *str) +{ +smack_t smack =0LL ;
"smack_t smack = 0;" is enough here.
security/smack/smack_access.c line 104
Quoted 4 lines
security/smack/smack_access.c +4
-0+char *cp; +int i; + +for (cp = (char *)&smack, i =0 ; i <sizeof (smack_t); str++,cp++,i++) {
Whatever it tries to do, this is not endian-safe. Except if @str actually points to another smack_t. Yuck.
security/smack/smackfs.c
Quoted 12 lines
security/smack/smack_access.c +9
-0+if (*str <=' ' || *str >'~' ) +return smack; + *cp = *str; + } +/* +* Too long. +*/ +return SMK_INVALID ; +}diff -uprN -X linux-2.6.22-base/Documentation/dontdiff
linux-2.6.22-base/security/smack/smackfs.clinux-2.6.22/security/smack/smackfs.csecurity/smack/smackfs.c +0
-0
Can't securityfs and/or sysfs be used?
security/smack/smackfs.c line 42
Quoted 11 lines
security/smack/smackfs.c +11
-0+enum smk_inos { +SMK_ROOT_INO =2 , +SMK_LOAD =3 ,/* load policy */ +SMK_LINKS =4 ,/* symlinks */ +SMK_CIPSO =5 ,/* load label -> CIPSO mapping */ +SMK_DOI =6 ,/* CIPSO DOI */ +SMK_DIRECT =7 ,/* CIPSO level indicating direct label */ +SMK_AMBIENT =8 ,/* internet ambient label */ +SMK_NLTYPE =9 ,/* label scheme to use by default */ +SMK_TMP =100 ,/* MUST BE LAST! /smack/tmp */ +};
Generally, =s are aligned too.
security/smack/smackfs.c line 70
Quoted 6 lines
security/smack/smackfs.c +6
-0+static struct smk_cipso_entry smack_cipso_floor = { + .smk_next =NULL , + .smk_smack =SMK_FLOOR , + .smk_level =0 , + .smk_catset =0LL , +};
const me.
Quoted 3 lines
+/*
+ * 'ssssssss oooooooo mmmm\n\0'
+ */
I wonder why it's limited to 8 characters? Ah right.. sizeof(smack_t). uhm.. are you trying to tell me that smack_t [typedef'ed to u64] are actually meant as a char[8]? (/me scrathces head)
security/smack/smackfs.c line 104
Quoted 4 lines
security/smack/smackfs.c +4
-0+for (cp = result; slp !=NULL ; slp = slp->smk_next) { + srp = &slp->smk_rule; +sprintf (cp,"%-8s %-8s" , + (char *)&srp->smk_subject, (char *)&srp->smk_object);
I like (const char *).
security/smack/smackfs.c
Quoted 2 lines
security/smack/smackfs.c +2
-0+printk ("%s:%d bad scan\n" , + __FUNCTION__, __LINE__);
__FUNCTION__ is a GNU extension, C99 uses __func__. Not sure what they've got for __LINE__.
security/smack/smackfs.c line 224
Quoted 8 lines
security/smack/smackfs.c +8
-0+if (strchr (modestr,'r' ) ||strchr (modestr,'R' )) + rule.smk_access |=MAY_READ ; +if (strchr (modestr,'w' ) ||strchr (modestr,'W' )) + rule.smk_access |=MAY_WRITE ; +if (strchr (modestr,'x' ) ||strchr (modestr,'X' )) + rule.smk_access |=MAY_EXEC ; +if (strchr (modestr,'a' ) ||strchr (modestr,'A' )) + rule.smk_access |=MAY_APPEND ;
There's strpbrk() available for you.
security/smack/smackfs.c line 249
Quoted 8 lines
security/smack/smackfs.c +8
-0+static char *smk_digit (char *cp) +{ +for (; *cp !='\0' ; cp++) +if (*cp >='0' && *cp <='9' ) +return cp; + +return NULL ; +}
strpbrk again.
security/smack/smackfs.c line 252
Quoted 2 lines
security/smack/smackfs.c +2
-0+static int smk_cipso_doied; +static int smk_cipso_written;
Votes for unsigned int if it {can never be, is not intended to be} negative.
security/smack/smackfs.c line 329
Quoted 3 lines
security/smack/smackfs.c +3
-0+for (slp = smack_cipso; slp !=NULL ; slp = slp->smk_next) { +sprintf (cp,"%-8s %3d" , (char *)&slp->smk_smack,slp->smk_level); + cp +=strlen (cp);
sprintf returns the number of bytes it has written, so
cp += sprintf(cp, ...)
might be used. [Can sprintf even return -1 here?]
security/smack/smackfs.c
Quoted 1 line
security/smack/smackfs.c +1
-0+ *(data + count) ='\0' ;
data[count] = '\0';
security/smack/smackfs.c line 490
Quoted 8 lines
security/smack/smackfs.c +8
-0+char temp[80 ]; +ssize_t rc; + +if (*ppos !=0 ) +return 0 ; + +sprintf (temp,"%d" , smk_cipso_doi_value); + rc =simple_read_from_buffer (buf, count, ppos, temp,strlen (temp));
80 is plenty for a 11 char string.
Look, they've got funny ideas! :) net/ipv4/netfilter/nf_nat_irc.c:char buffer[sizeof("4294967296 65635")];
security/smack/smackfs.c line 631
Quoted 13 lines
security/smack/smackfs.c +13
-0+static struct option_names netlbl_choices[] = { + {NETLBL_NLTYPE_RIPSO , +NETLBL_NLTYPE_RIPSO_NAME ,"ripso" }, + {NETLBL_NLTYPE_CIPSOV4 , +NETLBL_NLTYPE_CIPSOV4_NAME ,"cipsov4" }, + {NETLBL_NLTYPE_CIPSOV4 , +NETLBL_NLTYPE_CIPSOV4_NAME ,"cipso" }, + {NETLBL_NLTYPE_CIPSOV6 , +NETLBL_NLTYPE_CIPSOV6_NAME ,"cipsov6" }, + {NETLBL_NLTYPE_UNLABELED , +NETLBL_NLTYPE_UNLABELED_NAME ,"unlabeled" }, +}; +#define NCHOICES (sizeof(netlbl_choices) / sizeof(struct option_names))
ARRAY_SIZE()..
security/smack/smackfs.c line 650
Quoted 3 lines
security/smack/smackfs.c +3
-0+for (i =0 ; i <NCHOICES ; i++) +if (smack_net_nltype == netlbl_choices[i].o_number) { +sprintf (bound,"%s" , netlbl_choices[i].o_name);
looks dangerous; to overflow.
security/smack/smackfs.c line 685
Quoted 3 lines
security/smack/smackfs.c +3
-0+for (i =0 ; i <NCHOICES ; i++) +if ((strcmp (bound, netlbl_choices[i].o_name) ==0 ) || + (strcmp (bound, netlbl_choices[i].o_alias) ==0 )) {
redundant ()
security/smack/smackfs.c line 704
Quoted 2 lines
security/smack/smackfs.c +2
-0+#define SMK_TMPPATH_SIZE 32 +#define SMK_TMPPATH_ROOT "/moldy/"
What is going to be mold?
security/smack/smackfs.c
Quoted 2 lines
security/smack/smackfs.c +2
-0+if (slp ==NULL ) { +printk ("%s:%d failed\n" , __FUNCTION__, __LINE__);
KERN_<level> is missing. (Check other places too)
security/smack/smackfs.c
Quoted 10 lines
security/smack/smackfs.c +9
-0+#define SMK_MAXLEN (sizeof(smack_t) - 1)/* NULL terminated */ + +/* +* I hope these are the hokeyist lines of code in the module. Casey. +*/ +#define DEVPTS_SUPER_MAGIC 0x1cd1 +#define SOCKFS_MAGIC 0x534F434B +#define PIPEFS_MAGIC 0x50495045 +#define TMPFS_MAGIC 0x01021994
Try moving them to linux/magic.h.
security/smack/smackfs.c
Quoted 3 lines
security/smack/smackfs.c +3
-0+extern int smack_net_nltype; +extern int smack_cipso_direct; +extern struct smk_cipso_entry *smack_cipso;
for consistency reasons, add extern to the other vars too...
Quoted 4 lines
security/smack/smackfs.c +4
-0+struct inode_smack *new_inode_smack (smack_t smack) +{ +struct inode_smack *isp; +
security/smack/smackfs.c
Quoted 10 lines
security/smack/smackfs.c +10
-0+ isp =kzalloc (sizeof (struct inode_smack ),GFP_KERNEL ); +if (isp ==NULL ) +return NULL ; + + isp->smk_inode = smack; + isp->smk_flags =0 ; +mutex_init (&isp->smk_lock); + +return isp; +}
Tabs or so.
security/smack/smackfs.c
Quoted 7 lines
security/smack/smackfs.c +7
-0+static int smack_task_movememory (struct task_struct *p) +{ +int rc; + + rc =smk_curacc (smk_of_task (p),MAY_WRITE ); +return rc; +}
Uh...
{
return smk_curacc(smk_of_task(p), MAY_WRITE);
}(also others)
Quoted 31 lines
security/smack/smackfs.c +30
-0+ +static int smack_task_kill (struct task_struct *p,struct siginfo *info, +int sig,u32 secid) +{ +smack_t *tsp =smk_of_task (p); +int rc; + +/* +* Sending a signal requires that the sender +* can write the receiver. +*/ + rc =smk_curacc (tsp,MAY_WRITE ); + +return rc; +} + +static int smack_sb_statfs (struct dentry *dentry) +{ +struct superblock_smack *sbp; + +if (dentry ==NULL || dentry->d_sb ==NULL || + dentry->d_sb->s_security ==NULL ) +return 0 ; + + sbp = dentry->d_sb->s_security; + +return smk_curacc (&sbp->smk_floor,MAY_READ ); +} +/* +* Inode hooks
security/smack/smackfs.c
Quoted 10 lines
security/smack/smackfs.c +10
-0+*/ +static int smack_inode_alloc_security (struct inode *inode) +{ +smack_t *csp =smk_of_task (current); + + inode->i_security =new_inode_smack (*csp); +if (inode->i_security ==NULL ) +return -ENOMEM ; +return 0 ; +}
Tabz.
security/smack/smackfs.c
Quoted 10 lines
security/smack/smackfs.c +10
-0+static int smack_inode_init_security (struct inode *inode,struct inode *dir, +char **name,void **value,size_t *len) +{ +smack_t *isp =smk_of_inode (inode); + +if (name && (*name =kstrdup (XATTR_SMACK_SUFFIX ,GFP_KERNEL )) ==NULL ) +return -ENOMEM ; + +if (value && (*value =kstrdup ((char *)isp,GFP_KERNEL )) ==NULL ) +return -ENOMEM ;
Try not to do big assignments in if.
security/smack/smackfs.c
Quoted 4 lines
security/smack/smackfs.c +4
-0+static const char *smack_inode_xattr_getsuffix (void ) +{ +return XATTR_SMACK_SUFFIX ; +}
inline it, or opencode.
security/smack/smackfs.c
Quoted 9 lines
security/smack/smackfs.c +9
-0+static int smack_inode_setsecurity (struct inode *inode,const char *name, +const void *value,size_t size,int flags) +{ +smack_t smack; +smack_t *isp =smk_of_inode (inode); +struct socket_smack *ssp; +struct socket *sock; +struct super_block *sbp; +struct inode *ip = (struct inode *)inode;
This cast is really pointless.
security/smack/smackfs.c
Quoted 2 lines
security/smack/smackfs.c +2
-0+static int smack_inode_listsecurity (struct inode *inode,char *buffer, +size_t buffer_size)
Whitespace broken.
[attention span ran out]
Nice.
Jan
Casey Schaufler
maintainerQuoted 11 lines · --- Jan Engelhardt
Quoted 2 lines · Casey Schaufler
"*" - pronounced "star"wall
Quoted 1 line
"_" - pronounced "floor"
floor
Quoted 1 line
"^" - pronounced "hat"roof
Quoted 1 line
"?" - pronounced "huh"it's dark in here :)
It's almost worth considering the change for the joke. Almost.
Quoted 5 lines
security/smack/Kconfig line 3
Quoted 3 lines
security/smack/Kconfig +3
-0+config SECURITY_SMACK + bool "Simplified Mandatory Access Control Kernel Support" + depends on NETLABEL && SECURITY_NETWORKIs this a hard dependency, or can this work without network sec labels?
Smack uses netlabel to communicate label information even locally. Without this only processes running with the ambient label would be able to use sockets.
Quoted 8 lines
security/smack/Kconfig line 9
Quoted 6 lines
security/smack/Kconfig +6
-0+ default n + help + This selects the Simplified Mandatory Access Control Kernel. + SMACK is useful for sensitivity, integrity, and a variety + of other madatory security schemes. + If you are unsure how to answer this question, answer N.I smell broken tabs.
Yup. Fixed.
Quoted 11 lines
security/smack/Makefile line 7
Quoted 9 lines
+++ linux-2.6.22/security/smack/Makefile 2007-07-10 01:08:05.000000000 -0700
security/smack/Makefile +7
-0@@ -0,0 +1,8 @@ +# +# Makefile for the SMACK LSM +# + +obj-$(CONFIG_SECURITY_SMACK) := smack.o + +smack-y := smack_lsm.o smack_access.o smackfs.osmack-objs :=
Added.
Quoted 10 lines
Review line 8
Quoted 1 line
(quoted diff) +1
-0+++ linux-2.6.22/security/smack/smack_access.c 2007-07-24 15:36:18.000000000-0700
security/smack/smack_access.c line 5
Quoted 6 lines
security/smack/smack_access.c +5
-0@@ -0,0 +1,113 @@ +extern struct smk_list_entry *smack_list; + +static int smk_get_access (smack_t sub,smack_t obj) +{ +struct smk_list_entry *sp = smack_list;proposes const struct. should be used elsewhere too.
I've hit a few places.
Quoted 4 lines
security/smack/smack_access.c line 43
Quoted 1 line
security/smack/smack_access.c +1
-0+if (sub ==SMK_STAR )I just remember MechWarrior2 (game from Activison), where SMK stood for their movie format... it's also a nice abbreviation for Seamonkey (browser suite).
Err, yeah. Okay.
Quoted 7 lines
security/smack/smack_access.c line 64
Quoted 5 lines
security/smack/smack_access.c +5
-0+if (sub ==SMK_HAT && ((request &MAY_ANYREAD ) == request)) +return 0 ; + +if (obj ==SMK_FLOOR && ((request &MAY_ANYREAD ) == request)) +return 0 ;Redundant parentheses, be gone.
Done.
Quoted 6 lines
Never was it easier to say what ^ is called in your language :)
if (sub == '^' && ...) return 0; if (obj == '_' && ...)
Quoted 9 lines
security/smack/smack_access.c line 100
Quoted 7 lines
security/smack/smack_access.c +7
-0+/* +* The value that this adds is that everything after any +* character that's not allowed in a smack will be null +*/ +smack_t smk_from_string (char *str) +{ +smack_t smack =0LL ;"
smack_tsmack = 0;" is enough here.
Ok.
Quoted 7 lines
security/smack/smack_access.c line 104
Quoted 4 lines
security/smack/smack_access.c +4
-0+char *cp; +int i; + +for (cp = (char *)&smack, i =0 ; i <sizeof (smack_t); str++,cp++,i++) {Whatever it tries to do, this is not endian-safe. Except if @str actually points to another
smack_t. Yuck.
Small string stuck in a large integer. The only operation is comparison. Big or little endian the string will come out right, and that's what's important.
Quoted 12 lines
Quoted 10 lines
security/smack/smack_access.c +9
-0+if (*str <=' ' || *str >'~' ) +return smack; + *cp = *str; + } +/* +* Too long. +*/ +return SMK_INVALID ; +}diff -uprN -X linux-2.6.22-base/Documentation/dontdiff
linux-2.6.22-base/security/smack/smackfs.clinux-2.6.22/security/smack/smackfs.c
Quoted 6 lines
Quoted 1 line
---
linux-2.6.22-base/security/smack/smackfs.c1969-12-31 16:00:00.000000000-0800
Quoted 1 line
+++
linux-2.6.22/security/smack/smackfs.c2007-07-24 21:51:30.000000000-0700
Can't securityfs and/or sysfs be used?
I have to look into that for the configuration values. I don't think I can do it for the symlinks.
Quoted 5 lines
Quoted 5 lines
security/smack/smackfs.c +5
-0+enum smk_inos { +SMK_ROOT_INO =2 , +SMK_LOAD =3 ,/* load policy */ +SMK_LINKS =4 ,/* symlinks */ +SMK_CIPSO =5 ,/* load label -> CIPSO mapping */
Quoted 8 lines
security/smack/smackfs.c line 42
Quoted 6 lines
security/smack/smackfs.c +6
-0+SMK_DOI =6 ,/* CIPSO DOI */ +SMK_DIRECT =7 ,/* CIPSO level indicating direct label */ +SMK_AMBIENT =8 ,/* internet ambient label */ +SMK_NLTYPE =9 ,/* label scheme to use by default */ + SMK_TMP = 100, /* MUST BE LAST! /smack/tmp */ +};Generally, =s are aligned too.
It's pretty inconsistant, but that's what I prefer, too. I'll do it.
Quoted 8 lines
security/smack/smackfs.c line 70
Quoted 6 lines
security/smack/smackfs.c +6
-0+static struct smk_cipso_entry smack_cipso_floor = { + .smk_next =NULL , + .smk_smack =SMK_FLOOR , + .smk_level =0 , + .smk_catset =0LL , +};const me.
This is the correct tinitial value, but could be changed.
Quoted 7 lines
Quoted 3 lines
+/*
+ * 'ssssssss oooooooo mmmm\n\0'
+ */I wonder why it's limited to 8 characters? Ah right..
sizeof(smack_t). uhm.. are you trying to tell me thatsmack_t[typedef'ed to u64] are actually meant as a char[8]? (/me scrathces head)
Yes. "s == o" vs "strcmp(s,o) == 0".
Quoted 11 lines
security/smack/smackfs.c line 104
Quoted 4 lines
security/smack/smackfs.c +4
-0+for (cp = result; slp !=NULL ; slp = slp->smk_next) { + srp = &slp->smk_rule; +sprintf (cp,"%-8s %-8s" , + (char *)&srp->smk_subject, (char *)&srp->smk_object);I like (const char *).
Review
Quoted 2 lines
(quoted diff) +2
-0+ printk("%s:%d bad scan\n", + __FUNCTION__, __LINE__);
__FUNCTION__is a GNU extension, C99 uses__func__.
Changed, although it's used extensively elsewhere.
Quoted 1 line
Not sure what they've got for
__LINE__.
No clue. Leaving it as is.
Quoted 10 lines
security/smack/smackfs.c line 224
Quoted 8 lines
security/smack/smackfs.c +8
-0+if (strchr (modestr,'r' ) ||strchr (modestr,'R' )) + rule.smk_access |=MAY_READ ; +if (strchr (modestr,'w' ) ||strchr (modestr,'W' )) + rule.smk_access |=MAY_WRITE ; +if (strchr (modestr,'x' ) ||strchr (modestr,'X' )) + rule.smk_access |=MAY_EXEC ; +if (strchr (modestr,'a' ) ||strchr (modestr,'A' )) + rule.smk_access |=MAY_APPEND ;There's
strpbrk()available for you.
Makes it a little cleaner. Thank you.
Quoted 10 lines
security/smack/smackfs.c line 249
Quoted 8 lines
security/smack/smackfs.c +8
-0+static char *smk_digit (char *cp) +{ +for (; *cp !='\0' ; cp++) +if (*cp >='0' && *cp <='9' ) +return cp; + +return NULL ; +}strpbrk again.
Thank you again.
Quoted 4 lines
security/smack/smackfs.c line 252
Quoted 2 lines
security/smack/smackfs.c +2
-0+static int smk_cipso_doied; +static int smk_cipso_written;Votes for unsigned int if it {can never be, is not intended to be} negative.
No problem. Changed.
Quoted 7 lines
security/smack/smackfs.c line 329
Quoted 3 lines
security/smack/smackfs.c +3
-0+for (slp = smack_cipso; slp !=NULL ; slp = slp->smk_next) { +sprintf (cp,"%-8s %3d" , (char *)&slp->smk_smack,slp->smk_level); + cp +=strlen (cp);sprintf returns the number of bytes it has written, so
cp += sprintf(cp, ...)might be used. [Can sprintf even return -1 here?]
Better.
Quoted 3 lines
Review
Quoted 1 line
(quoted diff) +1
-0+ *(data + count) = '\0';data[count] = '\0';
Yeah, it's clearer.
Quoted 14 lines
security/smack/smackfs.c line 490
Quoted 8 lines
security/smack/smackfs.c +8
-0+char temp[80 ]; +ssize_t rc; + +if (*ppos !=0 ) +return 0 ; + +sprintf (temp,"%d" , smk_cipso_doi_value); + rc =simple_read_from_buffer (buf, count, ppos, temp,strlen (temp));80 is plenty for a 11 char string.
Look, they've got funny ideas! :) net/ipv4/netfilter/nf_nat_irc.c:char buffer[sizeof("4294967296 65635")];
Quoted 15 lines
security/smack/smackfs.c line 631
Quoted 13 lines
security/smack/smackfs.c +13
-0+static struct option_names netlbl_choices[] = { + {NETLBL_NLTYPE_RIPSO , +NETLBL_NLTYPE_RIPSO_NAME ,"ripso" }, + {NETLBL_NLTYPE_CIPSOV4 , +NETLBL_NLTYPE_CIPSOV4_NAME ,"cipsov4" }, + {NETLBL_NLTYPE_CIPSOV4 , +NETLBL_NLTYPE_CIPSOV4_NAME ,"cipso" }, + {NETLBL_NLTYPE_CIPSOV6 , +NETLBL_NLTYPE_CIPSOV6_NAME ,"cipsov6" }, + {NETLBL_NLTYPE_UNLABELED , +NETLBL_NLTYPE_UNLABELED_NAME ,"unlabeled" }, +}; +#define NCHOICES (sizeof(netlbl_choices) / sizeof(struct option_names))
ARRAY_SIZE()..
Spiffy. Used.
Quoted 5 lines
security/smack/smackfs.c line 650
Quoted 3 lines
security/smack/smackfs.c +3
-0+for (i =0 ; i <NCHOICES ; i++) +if (smack_net_nltype == netlbl_choices[i].o_number) { +sprintf (bound,"%s" , netlbl_choices[i].o_name);looks dangerous; to overflow.
Constant strings all fit.
Quoted 5 lines
security/smack/smackfs.c line 685
Quoted 3 lines
security/smack/smackfs.c +3
-0+for (i =0 ; i <NCHOICES ; i++) +if ((strcmp (bound, netlbl_choices[i].o_name) ==0 ) || + (strcmp (bound, netlbl_choices[i].o_alias) ==0 )) {redundant ()
Removed.
Quoted 4 lines
security/smack/smackfs.c line 704
Quoted 2 lines
security/smack/smackfs.c +2
-0+#define SMK_TMPPATH_SIZE 32 +#define SMK_TMPPATH_ROOT "/moldy/"What is going to be mold?
/tmp -> /smack/tmp -> /moldy/<yoursmacklabelhere>
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (slp == NULL) { + printk("%s:%d failed\n", __FUNCTION__, __LINE__);KERN_<level> is missing. (Check other places too)
printks in excess. Cleanup and correction in order.
Quoted 13 lines
security/smack/smack_lsm.c line 37
Quoted 11 lines
security/smack/smack_lsm.c +9
-0+#define SMK_MAXLEN (sizeof(smack_t) - 1)/* NULL terminated */ + +/* +* I hope these are the hokeyist lines of code in the module. Casey. +*/ +#define DEVPTS_SUPER_MAGIC 0x1cd1 +#define SOCKFS_MAGIC 0x534F434B +#define PIPEFS_MAGIC 0x50495045 +#define TMPFS_MAGIC 0x01021994Try moving them to
linux/magic.h.
Worth looking into.
Quoted 5 lines
security/smack/smack_lsm.c line 45
Quoted 3 lines
security/smack/smack_lsm.c +3
-0+extern int smack_net_nltype; +extern int smack_cipso_direct; +extern struct smk_cipso_entry *smack_cipso;for consistency reasons, add extern to the other vars too...
the others?
Quoted 8 lines
Quoted 8 lines
security/smack/smack_lsm.c +8
-0+struct inode_smack *new_inode_smack (smack_t smack) +{ +struct inode_smack *isp; + + isp =kzalloc (sizeof (struct inode_smack ),GFP_KERNEL ); +if (isp ==NULL ) +return NULL ; +
Quoted 8 lines
security/smack/smack_lsm.c line 85
Quoted 6 lines
security/smack/smack_lsm.c +6
-0+ isp->smk_inode = smack; + isp->smk_flags =0 ; +mutex_init (&isp->smk_lock); + +return isp; +}Tabs or so.
Yup. Fixed.
Quoted 10 lines
security/smack/smack_lsm.c line 197
Quoted 7 lines
security/smack/smack_lsm.c +7
-0+static int smack_task_movememory (struct task_struct *p) +{ +int rc; + + rc =smk_curacc (smk_of_task (p),MAY_WRITE ); +return rc; +}Uh...
Quoted 5 lines
{ return smk_curacc(smk_of_task(p), MAY_WRITE); }(also others)
That was a little excessive, wasn't it?
Quoted 29 lines
Quoted 28 lines
security/smack/smack_lsm.c +28
-0+ +static int smack_task_kill (struct task_struct *p,struct siginfo *info, +int sig,u32 secid) +{ +smack_t *tsp =smk_of_task (p); +int rc; + +/* +* Sending a signal requires that the sender +* can write the receiver. +*/ + rc =smk_curacc (tsp,MAY_WRITE ); + +return rc; +} + +static int smack_sb_statfs (struct dentry *dentry) +{ +struct superblock_smack *sbp; + +if (dentry ==NULL || dentry->d_sb ==NULL || + dentry->d_sb->s_security ==NULL ) +return 0 ; + + sbp = dentry->d_sb->s_security; + +return smk_curacc (&sbp->smk_floor,MAY_READ ); +}
Quoted 14 lines
security/smack/smack_lsm.c line 394
Quoted 12 lines
security/smack/smack_lsm.c +12
-0+/* +* Inode hooks +*/ +static int smack_inode_alloc_security (struct inode *inode) +{ +smack_t *csp =smk_of_task (current); + + inode->i_security =new_inode_smack (*csp); +if (inode->i_security ==NULL ) +return -ENOMEM ; +return 0 ; +}Tabz.
Fixxxed.
Quoted 13 lines
Quoted 1 line
+static int smack_inode_init_security(struct inode *inode, struct inode
*dir,
security/smack/smack_lsm.c line 411
Quoted 9 lines
security/smack/smack_lsm.c +9
-0+ char **name, void **value, size_t *len) +{ + smack_t *isp = smk_of_inode(inode); + +if (name && (*name =kstrdup (XATTR_SMACK_SUFFIX ,GFP_KERNEL )) ==NULL ) +return -ENOMEM ; + +if (value && (*value =kstrdup ((char *)isp,GFP_KERNEL )) ==NULL ) +return -ENOMEM ;Try not to do big assignments in if.
Fixed.
Quoted 6 lines
security/smack/smack_lsm.c line 585
Quoted 4 lines
security/smack/smack_lsm.c +4
-0+static const char *smack_inode_xattr_getsuffix (void ) +{ +return XATTR_SMACK_SUFFIX ; +}inline it, or opencode.
Better yet, no one is using the hook. nuked.
Quoted 11 lines
security/smack/smack_lsm.c line 639
Quoted 9 lines
security/smack/smack_lsm.c +9
-0+static int smack_inode_setsecurity (struct inode *inode,const char *name, +const void *value,size_t size,int flags) +{ +smack_t smack; +smack_t *isp =smk_of_inode (inode); +struct socket_smack *ssp; +struct socket *sock; +struct super_block *sbp; +struct inode *ip = (struct inode *)inode;This cast is really pointless.
The variable is really pointless. Repaired.
Quoted 4 lines
security/smack/smack_lsm.c line 677
Quoted 2 lines
security/smack/smack_lsm.c +2
-0+static int smack_inode_listsecurity (struct inode *inode,char *buffer, +size_t buffer_size)Whitespace broken.
Fixed
Quoted 2 lines
[attention span ran out]
It's a summer Saturday. Thank you for your helpful comments.
Quoted 1 line
Nice.
Thank you.
Casey Schaufler
[email protected]
Quoted 11 lines · Casey Schaufler
Quoted 10 lines
security/smack/Makefile line 7
Quoted 8 lines
security/smack/Makefile +7
-0@@ -0,0 +1,8 @@ +# +# Makefile for the SMACK LSM +# + +obj-$(CONFIG_SECURITY_SMACK) := smack.o + +smack-y := smack_lsm.o smack_access.o smackfs.osmack-objs :=
Quoted 1 line
Added.
I should have added "replace it".
Quoted 9 lines
Quoted 7 lines
security/smack/smackfs.c line 80
Quoted 3 lines
security/smack/smackfs.c +3
-0+/* +* 'ssssssss oooooooo mmmm\n\0' +*/ I wonder why it's limited to 8 characters? Ah right..
sizeof(smack_t). uhm.. are you trying to tell me thatsmack_t[typedef'ed to u64] are actually meant as a char[8]? (/me scrathces head)Yes. "s == o" vs "
strcmp(s,o)== 0".
Evil optimization ;-)
[ s == o is memcmp(s, o, sizeof(that)) == 0]
Quoted 11 lines
Quoted 11 lines
security/smack/smackfs.c line 490
Quoted 8 lines
security/smack/smackfs.c +8
-0+char temp[80 ]; +ssize_t rc; + +if (*ppos !=0 ) +return 0 ; + +sprintf (temp,"%d" , smk_cipso_doi_value); + rc =simple_read_from_buffer (buf, count, ppos, temp,strlen (temp));80 is plenty for a 11 char string.
Quoted 2 lines
Quoted 2 lines
Look, they've got funny ideas! :) net/ipv4/netfilter/nf_nat_irc.c:char buffer[sizeof("4294967296 65635")];
Proposal would have been: char temp[sizeof("4294967296")];
Quoted 7 lines
Quoted 5 lines
security/smack/smack_lsm.c line 45
Quoted 3 lines
security/smack/smack_lsm.c +3
-0+extern int smack_net_nltype; +extern int smack_cipso_direct; +extern struct smk_cipso_entry *smack_cipso;for consistency reasons, add extern to the other vars too...
the others?
There were some [or some function prototypes] above this point.
Quoted 10 lines
Quoted 10 lines
security/smack/smack_lsm.c line 197
Quoted 7 lines
security/smack/smack_lsm.c +7
-0+static int smack_task_movememory (struct task_struct *p) +{ +int rc; + + rc =smk_curacc (smk_of_task (p),MAY_WRITE ); +return rc; +}Uh...
Quoted 7 lines
Quoted 5 lines
{ return smk_curacc(smk_of_task(p), MAY_WRITE); }(also others)
That was a little excessive, wasn't it?
How do you mean? I was just suggesting to collapse the three [four] lines into one, getting rid of the tempotemporaries in a lot of these functions, for example,
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
security/smack/smack_lsm.c +6
-0+static int smack_task_kill (struct task_struct *p,struct siginfo *info, +int sig,u32 secid) +{ +smack_t *tsp =smk_of_task (p); +int rc; +
Quoted 8 lines
Quoted 8 lines
security/smack/smack_lsm.c line 212
Quoted 8 lines
security/smack/smack_lsm.c +8
-0+/* +* Sending a signal requires that the sender +* can write the receiver. +*/ + rc =smk_curacc (tsp,MAY_WRITE ); + +return rc; +}
static int smack_task_kill(struct stask_struct *p, struct siginfo *info,
int sig, u32 secid)
{
/* Comment */
return smk_curacc(smk_of_task(p), MAY_WRITE);
}Jan
Casey Schaufler
maintainerQuoted 14 lines · --- Jan Engelhardt
Quoted 14 lines
Quoted 14 lines
security/smack/smack_lsm.c line 197
Quoted 7 lines
security/smack/smack_lsm.c +7
-0+static int smack_task_movememory (struct task_struct *p) +{ +int rc; + + rc =smk_curacc (smk_of_task (p),MAY_WRITE ); +return rc; +}Uh...
{ return smk_curacc(smk_of_task(p), MAY_WRITE); }
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
(also others)
That was a little excessive, wasn't it?
How do you mean? I was just suggesting to collapse the three [four] lines into
one, getting rid of the tempotemporaries in a lot of these functions, for example,
Sorry, I meant that my code was excessive, not your comment. Your comment was fine and most welcome. I'm sorry that I was unclear and sounded defensive.
Casey Schaufler
[email protected]
Quoted 1 line · Casey Schaufler
Smack is the Simplified Mandatory Access Control Kernel.
I like the simplified part.
security/smack/smack_access.c line 27
Quoted 8 lines
security/smack/smack_access.c +8
-0+static int smk_get_access (smack_t sub,smack_t obj) +{ +struct smk_list_entry *sp = smack_list; + +for (; sp !=NULL ; sp = sp->smk_next) +if (sp->smk_rule.smk_subject == sub && + sp->smk_rule.smk_object == obj) +return sp->smk_rule.smk_access;
Do I miss something, or is there really no locking for the reader side of the list? That looks dangerous. Of course a global lock for readers would be likely a scaling disaster. You could use RCU.
Or if you assume rules are changed only very infrequently it might be more cache friendly to compile all the rules into a linear buffer and then just replace the whole buffer atomically with a RCU grace period on cahnges.
It doesn't look like it would scale to larger numbers of rules though. Is that intended? Would caching of decisions fit into the design?
Also in general code style would need some improvements; e.g. no externs in .c; no ../.. include hacks etc.
You also seem weak on the Documentation front.
Other than that it looks reasonably clean (haven't read all of it)
-Andi
Casey Schaufler
maintainerQuoted 6 lines · --- Andi Kleen
Quoted 1 line · Casey Schaufler
Smack is the Simplified Mandatory Access Control Kernel.
I like the simplified part.
Quoted 12 lines
security/smack/smack_access.c line 27
Quoted 8 lines
security/smack/smack_access.c +8
-0+static int smk_get_access (smack_t sub,smack_t obj) +{ +struct smk_list_entry *sp = smack_list; + +for (; sp !=NULL ; sp = sp->smk_next) +if (sp->smk_rule.smk_subject == sub && + sp->smk_rule.smk_object == obj) +return sp->smk_rule.smk_access;Do I miss something, or is there really no locking for the reader side of the list? That looks dangerous. Of course a global lock for readers would be likely a scaling disaster. You could use RCU.
Entries are never deleted, although they can be modified.
Quoted 4 lines
Or if you assume rules are changed only very infrequently it might be more cache friendly to compile all the rules into a linear buffer and then just replace the whole buffer atomically with a RCU grace period on cahnges.
Individual entries can be modified without changing the whole thing, but they shouldn't change often.
Quoted 2 lines
It doesn't look like it would scale to larger numbers of rules though. Is that intended? Would caching of decisions fit into the design?
I put some thought into clever schemes for supporting large rule sets well but decided to go ahead with the simplest possible mechanism because I expect that in real deployments the number of rules will be small. In fact, experiance says that virtually all access choices will be covered either by the subject==object case or the subject can read floor case. Cacheing, hashing, and 2D structures are all possibilties that I would be happy to entertain as enhancements.
Quoted 3 lines
Also in general code style would need some improvements; e.g. no externs in .c; no ../.. include hacks etc. You also seem weak on the Documentation front.
Yes, it is pretty sparse.
Quoted 1 line
Other than that it looks reasonably clean (haven't read all of it)
Thank you for your comments. I think the next version will be improved.
Casey Schaufler
[email protected]
Quoted 1 line
Entries are never deleted, although they can be modified.
The modification case still seems racy then.
-Andi
Casey Schaufler
maintainerQuoted 3 lines · --- Andi Kleen
Quoted 1 line
Entries are never deleted, although they can be modified.
The modification case still seems racy then.
Fair enough. I'll look into real list management.
Casey Schaufler
[email protected]
Quoted 8 lines · Casey Schaufler
Quoted 3 lines · --- Andi Kleen
Quoted 1 line
Entries are never deleted, although they can be modified.
The modification case still seems racy then.
Fair enough. I'll look into real list management.
You don't necessarily need more list management if you don't plan to remove entries, but just replace them.
e.g. what could work to atomically replace is:
- Make the buffer a pointer to an allocated buffer that also contains a struct rcu_head.
- Reader: Does rcu_read_lock() around list walk (that just disables preemption on preemptible kernels and is otherwise a nop). Also uses rcu_reference for reading the pointer.
- Writer: Continues using the mutex to protect against other writers. When changing an entry allocate a new buffer + rcu_head. Initialize buffer. Replace pointer. Free old buffer using call_rcu()
The RCU would just make sure the buffer is not freed while other CPUs are still accessing it. It also means they can use stale rules for a time, but it is a strictly bounded time (bounded to max time walking the list plus max time any interrupt handlers inbetween run [admittedly that can be very long in theory, but it's all logically only a single rule check])
-Andi
Casey Schaufler
maintainerQuoted 24 lines · --- Andi Kleen
Quoted 8 lines · Casey Schaufler
Quoted 3 lines · --- Andi Kleen
Quoted 1 line
Entries are never deleted, although they can be modified.
The modification case still seems racy then.
Fair enough. I'll look into real list management.
You don't necessarily need more list management if you don't plan to remove entries, but just replace them.
e.g. what could work to atomically replace is:
- Make the buffer a pointer to an allocated buffer that also contains a struct
rcu_head.
- Reader: Doesrcu_read_lock()around list walk (that just disables preemption on preemptible kernels and is otherwise a nop). Also usesrcu_referencefor reading the pointer.
- Writer: Continues using the mutex to protect against other writers. When changing an entry allocate a new buffer +rcu_head. Initialize buffer. Replace pointer. Free old buffer usingcall_rcu()
Quoted 6 lines
The RCU would just make sure the buffer is not freed while other CPUs are still accessing it. It also means they can use stale rules for a time, but it is a strictly bounded time (bounded to max time walking the list plus max time any interrupt handlers inbetween run [admittedly that can be very long in theory, but it's all logically only a single rule check])
Thank you. You have no idea how helpful that little suggestion was.
Casey Schaufler
[email protected]
Quoted 13 lines · Casey Schaufler (on Sat, 11 Aug 2007 10:57:31 -0700) wrote:
Smack is the Simplified Mandatory Access Control Kernel.
[snip]
Smack defines and uses these labels:
"*" - pronounced "star" "_" - pronounced "floor" "^" - pronounced "hat" "?" - pronounced "huh"The access rules enforced by Smack are, in order:
Quoted 11 lines
1. Any access requested by a task labeled "*" is denied.
2. A read or execute access requested by a task labeled "^" is permitted.
3. A read or execute access requested on an object labeled "_" is permitted.
4. Any access requested on an object labeled "*" is permitted.
5. Any access requested by a task on an object with the same label is permitted.
6. Any access requested that is explicitly defined in the loaded rule set is permitted.
7. Any other access is denied.
Some security systems that have the concept of "no default access" (task labeled "*") also allow access by those tasks but only if there is an explicit rule giving access to the task. IOW, rule 6 is applied before rule 1. In my experience this simplifies special cases where a task should only have access to a very small set of resources. I'm curious why smack goes the other way?
Casey Schaufler
maintainerQuoted 26 lines · --- Keith Owens
Quoted 13 lines · Casey Schaufler (on Sat, 11 Aug 2007 10:57:31 -0700) wrote:
Smack is the Simplified Mandatory Access Control Kernel.
[snip]
Smack defines and uses these labels:
"*" - pronounced "star" "_" - pronounced "floor" "^" - pronounced "hat" "?" - pronounced "huh"The access rules enforced by Smack are, in order:
Quoted 11 lines
1. Any access requested by a task labeled "*" is denied.
2. A read or execute access requested by a task labeled "^" is permitted.
3. A read or execute access requested on an object labeled "_" is permitted.
4. Any access requested on an object labeled "*" is permitted.
5. Any access requested by a task on an object with the same label is permitted.
6. Any access requested that is explicitly defined in the loaded rule set is permitted.
7. Any other access is denied.
Quoted 6 lines
Some security systems that have the concept of "no default access" (task labeled "*") also allow access by those tasks but only if there is an explicit rule giving access to the task. IOW, rule 6 is applied before rule 1. In my experience this simplifies special cases where a task should only have access to a very small set of resources. I'm curious why smack goes the other way?
A task labeled star would create files labeled star, which would be readable and writable by everyone (rule 4). This would be bad.
Over the past three decade I've seen a lot of secure installations but I have never seen one where they really wanted to deny any real application access to "/". That's a major reason for chrooted environments.
Remember also that a process labeled Coffee would have read access to floor files, all access to star files (e.g. /dev/null), read and write access to Coffee objects, and no others unless specified. If you are serious about reducing the programs a Coffee process can run you can do so by moving them off the floor, that is, giving them a different label, say "Tea". There is a cost to doing this, which is that you now have to give other labels explicit access to Tea objects. This is how you would implement a Biba integrity policy.
So, can you give me an example where you don't want access to any file system objects (no read or execute access on floor) and are still doing something useful? Remember that you can't exec a program if you can't access it.
I think that access to the file system namespace is universally required. I'm open to education.
Casey Schaufler
[email protected]