diff options
| author | Casey Schaufler <casey@schaufler-ca.com> | 2008-02-05 01:29:50 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-05 12:44:20 -0500 |
| commit | e114e473771c848c3cfec05f0123e70f1cdbdc99 (patch) | |
| tree | 933b840f3ccac6860da56291c742094f9b5a20cb /security | |
| parent | eda61d32e8ad1d9102872f9a0abf3344bf9c5e67 (diff) | |
Smack: Simplified Mandatory Access Control Kernel
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 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.
The patch, patches for ls and sshd, a README, a startup script,
and x86 binaries for ls and sshd are also available on
http://www.schaufler-ca.com
Development has been done using Fedora Core 7 in a virtual machine
environment and on an old Sony laptop.
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-23 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. Smack labels are composed of printable characters and may not
include "/".
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
accommodate 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.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Cc: Joshua Brindle <method@manicmethod.com>
Cc: Paul Moore <paul.moore@hp.com>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: James Morris <jmorris@namei.org>
Cc: "Ahmed S. Darwish" <darwish.07@gmail.com>
Cc: Andrew G. Morgan <morgan@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'security')
| -rw-r--r-- | security/Kconfig | 1 | ||||
| -rw-r--r-- | security/Makefile | 2 | ||||
| -rw-r--r-- | security/smack/Kconfig | 10 | ||||
| -rw-r--r-- | security/smack/Makefile | 7 | ||||
| -rw-r--r-- | security/smack/smack.h | 220 | ||||
| -rw-r--r-- | security/smack/smack_access.c | 356 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 2518 | ||||
| -rw-r--r-- | security/smack/smackfs.c | 981 |
8 files changed, 4095 insertions, 0 deletions
diff --git a/security/Kconfig b/security/Kconfig index 389e151e3b6..25ffe1b9dc9 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
| @@ -105,6 +105,7 @@ config SECURITY_ROOTPLUG | |||
| 105 | If you are unsure how to answer this question, answer N. | 105 | If you are unsure how to answer this question, answer N. |
| 106 | 106 | ||
| 107 | source security/selinux/Kconfig | 107 | source security/selinux/Kconfig |
| 108 | source security/smack/Kconfig | ||
| 108 | 109 | ||
| 109 | endmenu | 110 | endmenu |
| 110 | 111 | ||
diff --git a/security/Makefile b/security/Makefile index ef87df2f50a..9e8b0252501 100644 --- a/security/Makefile +++ b/security/Makefile | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_KEYS) += keys/ | 5 | obj-$(CONFIG_KEYS) += keys/ |
| 6 | subdir-$(CONFIG_SECURITY_SELINUX) += selinux | 6 | subdir-$(CONFIG_SECURITY_SELINUX) += selinux |
| 7 | subdir-$(CONFIG_SECURITY_SMACK) += smack | ||
| 7 | 8 | ||
| 8 | # if we don't select a security model, use the default capabilities | 9 | # if we don't select a security model, use the default capabilities |
| 9 | ifneq ($(CONFIG_SECURITY),y) | 10 | ifneq ($(CONFIG_SECURITY),y) |
| @@ -14,5 +15,6 @@ endif | |||
| 14 | obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o | 15 | obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o |
| 15 | # Must precede capability.o in order to stack properly. | 16 | # Must precede capability.o in order to stack properly. |
| 16 | obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o | 17 | obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o |
| 18 | obj-$(CONFIG_SECURITY_SMACK) += commoncap.o smack/built-in.o | ||
| 17 | obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o | 19 | obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o |
| 18 | obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o | 20 | obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o |
diff --git a/security/smack/Kconfig b/security/smack/Kconfig new file mode 100644 index 00000000000..603b0878434 --- /dev/null +++ b/security/smack/Kconfig | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | config SECURITY_SMACK | ||
| 2 | bool "Simplified Mandatory Access Control Kernel Support" | ||
| 3 | depends on NETLABEL && SECURITY_NETWORK | ||
| 4 | default n | ||
| 5 | help | ||
| 6 | This selects the Simplified Mandatory Access Control Kernel. | ||
| 7 | Smack is useful for sensitivity, integrity, and a variety | ||
| 8 | of other mandatory security schemes. | ||
| 9 | If you are unsure how to answer this question, answer N. | ||
| 10 | |||
diff --git a/security/smack/Makefile b/security/smack/Makefile new file mode 100644 index 00000000000..67a63aaec82 --- /dev/null +++ b/security/smack/Makefile | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | # | ||
| 2 | # Makefile for the SMACK LSM | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_SECURITY_SMACK) := smack.o | ||
| 6 | |||
| 7 | smack-y := smack_lsm.o smack_access.o smackfs.o | ||
diff --git a/security/smack/smack.h b/security/smack/smack.h new file mode 100644 index 00000000000..a21a0e907ab --- /dev/null +++ b/security/smack/smack.h | |||
| @@ -0,0 +1,220 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation, version 2. | ||
| 7 | * | ||
| 8 | * Author: | ||
| 9 | * Casey Schaufler <casey@schaufler-ca.com> | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef _SECURITY_SMACK_H | ||
| 14 | #define _SECURITY_SMACK_H | ||
| 15 | |||
| 16 | #include <linux/capability.h> | ||
| 17 | #include <linux/spinlock.h> | ||
| 18 | #include <net/netlabel.h> | ||
| 19 | |||
| 20 | /* | ||
| 21 | * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is | ||
| 22 | * bigger than can be used, and 24 is the next lower multiple | ||
| 23 | * of 8, and there are too many issues if there isn't space set | ||
| 24 | * aside for the terminating null byte. | ||
| 25 | */ | ||
| 26 | #define SMK_MAXLEN 23 | ||
| 27 | #define SMK_LABELLEN (SMK_MAXLEN+1) | ||
| 28 | |||
| 29 | /* | ||
| 30 | * How many kinds of access are there? | ||
| 31 | * Here's your answer. | ||
| 32 | */ | ||
| 33 | #define SMK_ACCESSDASH '-' | ||
| 34 | #define SMK_ACCESSLOW "rwxa" | ||
| 35 | #define SMK_ACCESSKINDS (sizeof(SMK_ACCESSLOW) - 1) | ||
| 36 | |||
| 37 | struct superblock_smack { | ||
| 38 | char *smk_root; | ||
| 39 | char *smk_floor; | ||
| 40 | char *smk_hat; | ||
| 41 | char *smk_default; | ||
| 42 | int smk_initialized; | ||
| 43 | spinlock_t smk_sblock; /* for initialization */ | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct socket_smack { | ||
| 47 | char *smk_out; /* outbound label */ | ||
| 48 | char *smk_in; /* inbound label */ | ||
| 49 | char smk_packet[SMK_LABELLEN]; /* TCP peer label */ | ||
| 50 | }; | ||
| 51 | |||
| 52 | /* | ||
| 53 | * Inode smack data | ||
| 54 | */ | ||
| 55 | struct inode_smack { | ||
| 56 | char *smk_inode; /* label of the fso */ | ||
| 57 | struct mutex smk_lock; /* initialization lock */ | ||
| 58 | int smk_flags; /* smack inode flags */ | ||
| 59 | }; | ||
| 60 | |||
| 61 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ | ||
| 62 | |||
| 63 | /* | ||
| 64 | * A label access rule. | ||
| 65 | */ | ||
| 66 | struct smack_rule { | ||
| 67 | char *smk_subject; | ||
| 68 | char *smk_object; | ||
| 69 | int smk_access; | ||
| 70 | }; | ||
| 71 | |||
| 72 | /* | ||
| 73 | * An entry in the table of permitted label accesses. | ||
| 74 | */ | ||
| 75 | struct smk_list_entry { | ||
| 76 | struct smk_list_entry *smk_next; | ||
| 77 | struct smack_rule smk_rule; | ||
| 78 | }; | ||
| 79 | |||
| 80 | /* | ||
| 81 | * An entry in the table mapping smack values to | ||
| 82 | * CIPSO level/category-set values. | ||
| 83 | */ | ||
| 84 | struct smack_cipso { | ||
| 85 | int smk_level; | ||
| 86 | char smk_catset[SMK_LABELLEN]; | ||
| 87 | }; | ||
| 88 | |||
| 89 | /* | ||
| 90 | * This is the repository for labels seen so that it is | ||
| 91 | * not necessary to keep allocating tiny chuncks of memory | ||
| 92 | * and so that they can be shared. | ||
| 93 | * | ||
| 94 | * Labels are never modified in place. Anytime a label | ||
| 95 | * is imported (e.g. xattrset on a file) the list is checked | ||
| 96 | * for it and it is added if it doesn't exist. The address | ||
| 97 | * is passed out in either case. Entries are added, but | ||
| 98 | * never deleted. | ||
| 99 | * | ||
| 100 | * Since labels are hanging around anyway it doesn't | ||
| 101 | * hurt to maintain a secid for those awkward situations | ||
| 102 | * where kernel components that ought to use LSM independent | ||
| 103 | * interfaces don't. The secid should go away when all of | ||
| 104 | * these components have been repaired. | ||
| 105 | * | ||
| 106 | * If there is a cipso value associated with the label it | ||
| 107 | * gets stored here, too. This will most likely be rare as | ||
| 108 | * the cipso direct mapping in used internally. | ||
| 109 | */ | ||
| 110 | struct smack_known { | ||
| 111 | struct smack_known *smk_next; | ||
| 112 | char smk_known[SMK_LABELLEN]; | ||
| 113 | u32 smk_secid; | ||
| 114 | struct smack_cipso *smk_cipso; | ||
| 115 | spinlock_t smk_cipsolock; /* for changing cipso map */ | ||
| 116 | }; | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Mount options | ||
| 120 | */ | ||
| 121 | #define SMK_FSDEFAULT "smackfsdef=" | ||
| 122 | #define SMK_FSFLOOR "smackfsfloor=" | ||
| 123 | #define SMK_FSHAT "smackfshat=" | ||
| 124 | #define SMK_FSROOT "smackfsroot=" | ||
| 125 | |||
| 126 | /* | ||
| 127 | * xattr names | ||
| 128 | */ | ||
| 129 | #define XATTR_SMACK_SUFFIX "SMACK64" | ||
| 130 | #define XATTR_SMACK_IPIN "SMACK64IPIN" | ||
