Skip to contentSkip to conversation

Smack: Simplified Mandatory Access Control Kernel

PATCH In review Casey Schaufler 11 participants 43 messages Aug 11, 2007 – Sep 7, 2007

Subsystems (2)
lore
Share & tools
lore

Casey Schaufler

author maintainer
#0 lore raw

PATCH 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  r

On 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
diff -uprN -X linux-2.6.22-base/Documentation/dontdiff linux-2.6.22-base/security/Kconfig linux-2.6.22/security/Kconfig
@@ -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
diff -uprN -X linux-2.6.22-base/Documentation/dontdiff linux-2.6.22-base/security/Makefile linux-2.6.22/security/Makefile
@@ -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
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
@@ -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
diff -uprN -X linux-2.6.22-base/Documentation/dontdiff linux-2.6.22-base/security/smack/Makefile linux-2.6.22/security/smack/Makefile
@@ -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.

#1 lore raw
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?

author maintainer
#2 lore raw
Quoted 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]

#3 lore raw
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.

#4 lore raw
In reply to Casey Schaufler
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 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 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

author maintainer
#5 lore raw
Quoted 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 recvfrom recv_msg }; allow $1 $2:ipc { getattr read associate unix_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 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... ## ')

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_logging true;

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 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.

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_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.

Ok.

Quoted 18 lines
Quoted 5 lines

Another case that I especially like:

SatData Guard w
Guard Publish w

Quoted 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]

#6 lore raw
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 recvfrom recv_msg }; allow $1 $2:ipc { getattr read associate unix_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_logging true;

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

author maintainer
#7 lore raw
Quoted 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 recvfrom recv_msg }; allow $1 $2:ipc { getattr read associate unix_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 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.

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_logging true;

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 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.

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_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_".

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 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

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]

#8 lore raw

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 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.

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 rx
Quoted 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_logging true;

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_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_".

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 -t
web_docs_t '/www_S(/.*)?'
semanage fcontext -a -r TopSecret-TopSecret -s system_u -t
web_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

author maintainer
#9 lore raw
Quoted 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.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 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 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.

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_logging true;

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;

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 setsebool can_play_games false
0 17 * * * root setsebool can_play_games true

Quoted 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_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_".

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 -s system_u -t
web_docs_t '/www_S(/.*)?'
semanage fcontext -a -r TopSecret-TopSecret -s system_u -t
web_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/run and 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/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.

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]

#10 lore raw
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
#11 lore raw
In reply to Casey Schaufler
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 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.

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;
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.

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 do
uses_shlib(ping_t)
can_network(ping_t)
can_ypbind(ping_t)

## Allow additional permissions that ping needs to operate
allow ping_t etc_t:file { getattr read };
allow ping_t self:unix_stream_socket create_socket_perms;
allow ping_t self:rawip_socket { create ioctl read write bind getopt setopt }; allow ping_t netif_type:netif { rawip_send rawip_recv };
allow ping_t node_type:node { rawip_send rawip_recv };
allow ping_t self:capability { net_raw setuid };

## Allow ping to poke at the terminal
allow ping_t admin_tty_type:chr_file rw_file_perms; allow ping_t { userdomain privfd kernel_t }:fd use;

## Ping wants to get FS attributes and look in /var but doesn't need to dontaudit ping_t fs_t:filesystem getattr;
dontaudit ping_t var_t:dir search;

It should be pretty clear what every part of the policy is there for; basically that's the minimum necessary set of permissions for ping to run, with an optional boolean to control user pings. There's also a macro to give your arbitrary process the ability to run ping, such as for the "heartbeat" daemon for example.

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/run and 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

#12 lore raw
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.

#13 lore raw
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

author maintainer
#14 lore raw
In reply to Kyle Moffett
Quoted 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;
type my_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 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 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]

#15 lore raw

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
author maintainer
#16 lore raw
Quoted 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]

#17 lore raw

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
#18 lore raw
In reply to Casey Schaufler

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

#19 lore raw
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).

#20 lore raw
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

author maintainer
#21 lore raw
Quoted 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]

#22 lore raw
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

author maintainer
#23 lore raw
Quoted 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]

author maintainer
#25 lore raw
In reply to Kyle Moffett
Quoted 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]

#26 lore raw

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
author maintainer
#27 lore raw
Quoted 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]

#28 lore raw
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
author maintainer
#29 lore raw
Quoted 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]

#30 lore raw
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

#31 lore raw
In reply to Casey Schaufler
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.c linux-2.6.22/security/smack/smackfs.c

security/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

author maintainer
#32 lore raw
Quoted 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_NETWORK

Is 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.o

smack-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_t smack = 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.c
linux-2.6.22/security/smack/smackfs.c

Quoted 6 lines
Quoted 1 line

--- linux-2.6.22-base/security/smack/smackfs.c 1969-12-31 16:00:00.000000000

-0800

Quoted 1 line

+++ linux-2.6.22/security/smack/smackfs.c 2007-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 that smack_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		0x01021994

Try 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]

#33 lore raw
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.o

smack-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 that smack_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

author maintainer
#34 lore raw
Quoted 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]

#35 lore raw
In reply to Casey Schaufler
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

author maintainer
#36 lore raw
Quoted 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]

#37 lore raw
Quoted 1 line

Entries are never deleted, although they can be modified.

The modification case still seems racy then.

-Andi

author maintainer
#38 lore raw
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.

Casey Schaufler
[email protected]

#39 lore raw
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

author maintainer
#40 lore raw
Quoted 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: 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()

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]

#41 lore raw
In reply to Casey Schaufler
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?

author maintainer
#42 lore raw
Quoted 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]