Smack Updates

Submitted by Jeremy
on October 4, 2007 - 8:33pm

Casey Schaufler posted an updated Smack patchset based on feedback from the previous posting, "I have broken the Smack patch into the netlabel changes from Paul Moore (1/2) and the Smack LSM (2/2), at Paul's kind suggestion." He added:

"The smackfs symlinks have proven too contentious. I have removed the facility. Al and Alan are correct that the rich set of mount options currently available can handle any of the use cases I was looking at without excessive difficulty."

Smack is the Simplified Mandatory Access Control Kernel, utilizing the LSM framework to implement label-based mandatory access control and slated for inclusion in the upcoming 2.6.24 mainline kernel during the 2.6.24-rc1 merge window.


From: Casey Schaufler <casey@...>
Subject: [PATCH 0/2] Version 5 (2.6.23-rc8-mm2) Smack: Simplified Mandatory Access Control Kernel
Date: Oct 4, 2:23 pm 2007

I have broken the Smack patch into the netlabel changes from Paul Moore
(1/2) and the Smack LSM (2/2), at Paul's kind suggestion.

The smackfs symlinks have proven too contentious. I have removed the
facility. Al and Alan are correct that the rich set of mount options
currently available can handle any of the use cases I was looking at
without excessive difficulty.

I think that is the last of the major issues. I'm sure that if there
are more y'all will let me know.

Thank you.

-

From: Casey Schaufler <casey@...>
Subject: [PATCH 1/2] [NetLabel] Introduce a new kernel configuration API for NetLabel - Version 5 (2.6.23-rc8-mm2) Smack: Simplified Mandatory Access Control Kernel
Date: Oct 4, 2:23 pm 2007

From: Paul Moore

Add a new set of configuration functions to the NetLabel/LSM API so that
LSMs can perform their own configuration of the NetLabel subsystem without
relying on assistance from userspace.

Signed-off-by: Paul Moore
Signed-off-by: Casey Schaufler
---

include/net/netlabel.h | 47 ++++++++--
net/ipv4/cipso_ipv4.c | 4 -
net/netlabel/netlabel_cipso_v4.c | 2
net/netlabel/netlabel_cipso_v4.h | 3 +
net/netlabel/netlabel_domainhash.h | 1
net/netlabel/netlabel_kapi.c | 174 ++++++++++++++++++++++++++++++++++++
6 files changed, 222 insertions(+), 9 deletions(-)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 2e5b2f6..facaf68 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -36,6 +36,8 @@
#include
#include

+struct cipso_v4_doi;
+
/*
* NetLabel - A management interface for maintaining network packet label
* mapping tables for explicit packet labling protocols.
@@ -99,12 +101,6 @@ struct netlbl_audit {
uid_t loginuid;
};

-/* Domain mapping definition struct */
-struct netlbl_dom_map;
-
-/* Domain mapping operations */
-int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info);
-
/* LSM security attributes */
struct netlbl_lsm_cache {
atomic_t refcount;
@@ -285,6 +281,19 @@ static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr)

#ifdef CONFIG_NETLABEL
/*
+ * LSM configuration operations
+ */
+int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info);
+int netlbl_cfg_unlbl_add_map(const char *domain,
+ struct netlbl_audit *audit_info);
+int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
+ struct netlbl_audit *audit_info);
+int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
+ const char *domain,
+ struct netlbl_audit *audit_info);
+int netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info);
+
+/*
* LSM security attribute operations
*/
int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
@@ -318,6 +327,32 @@ void netlbl_cache_invalidate(void);
int netlbl_cache_add(const struct sk_buff *skb,
const struct netlbl_lsm_secattr *secattr);
#else
+static inline int netlbl_cfg_map_del(const char *domain,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_cfg_unlbl_add_map(const char *domain,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
+ const char *domain,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
+static inline int netlbl_cfg_cipsov4_del(u32 doi,
+ struct netlbl_audit *audit_info)
+{
+ return -ENOSYS;
+}
static inline int netlbl_secattr_catmap_walk(
struct netlbl_lsm_secattr_catmap *catmap,
u32 offset)
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index ab56a05..714461c 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -557,8 +557,8 @@ int cipso_v4_doi_remove(u32 doi,
spin_unlock(&cipso_v4_doi_list_lock);
list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
if (dom_iter->valid)
- netlbl_domhsh_remove(dom_iter->domain,
- audit_info);
+ netlbl_cfg_map_del(dom_iter->domain,
+ audit_info);
cipso_v4_cache_invalidate();
rcu_read_unlock();

diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index c060e3f..07f7fd4 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -89,7 +89,7 @@ static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1
* safely.
*
*/
-static void netlbl_cipsov4_doi_free(struct rcu_head *entry)
+void netlbl_cipsov4_doi_free(struct rcu_head *entry)
{
struct cipso_v4_doi *ptr;

diff --git a/net/netlabel/netlabel_cipso_v4.h b/net/netlabel/netlabel_cipso_v4.h
index f03cf9b..220cb9d 100644
--- a/net/netlabel/netlabel_cipso_v4.h
+++ b/net/netlabel/netlabel_cipso_v4.h
@@ -163,4 +163,7 @@ enum {
/* NetLabel protocol functions */
int netlbl_cipsov4_genl_init(void);

+/* Free the memory associated with a CIPSOv4 DOI definition */
+void netlbl_cipsov4_doi_free(struct rcu_head *entry);
+
#endif
diff --git a/net/netlabel/netlabel_domainhash.h b/net/netlabel/netlabel_domainhash.h
index 3689956..8220990 100644
--- a/net/netlabel/netlabel_domainhash.h
+++ b/net/netlabel/netlabel_domainhash.h
@@ -61,6 +61,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
struct netlbl_audit *audit_info);
int netlbl_domhsh_add_default(struct netlbl_dom_map *entry,
struct netlbl_audit *audit_info);
+int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info);
int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info);
struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
int netlbl_domhsh_walk(u32 *skip_bkt,
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 4f50949..ec7b5a5 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -30,6 +30,7 @@

#include
#include
+#include
#include
#include
#include
@@ -37,10 +38,183 @@

#include "netlabel_domainhash.h"
#include "netlabel_unlabeled.h"
+#include "netlabel_cipso_v4.h"
#include "netlabel_user.h"
#include "netlabel_mgmt.h"

/*
+ * Configuration Functions
+ */
+
+/**
+ * netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
+ * @domain: the domain mapping to remove
+ * @audit_info: NetLabel audit information
+ *
+ * Description:
+ * Removes a NetLabel/LSM domain mapping. A @domain value of NULL causes the
+ * default domain mapping to be removed. Returns zero on success, negative
+ * values on failure.
+ *
+ */
+int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info)
+{
+ return netlbl_domhsh_remove(domain, audit_info);
+}
+
+/**
+ * netlbl_cfg_unlbl_add_map - Add an unlabeled NetLabel/LSM domain mapping
+ * @domain: the domain mapping to add
+ * @audit_info: NetLabel audit information
+ *
+ * Description:
+ * Adds a new unlabeled NetLabel/LSM domain mapping. A @domain value of NULL
+ * causes a new default domain mapping to be added. Returns zero on success,
+ * negative values on failure.
+ *
+ */
+int netlbl_cfg_unlbl_add_map(const char *domain,
+ struct netlbl_audit *audit_info)
+{
+ int ret_val = -ENOMEM;
+ struct netlbl_dom_map *entry;
+
+ entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+ if (entry == NULL)
+ goto cfg_unlbl_add_map_failure;
+ if (domain != NULL) {
+ entry->domain = kstrdup(domain, GFP_ATOMIC);
+ if (entry->domain == NULL)
+ goto cfg_unlbl_add_map_failure;
+ }
+ entry->type = NETLBL_NLTYPE_UNLABELED;
+
+ ret_val = netlbl_domhsh_add(entry, audit_info);
+ if (ret_val != 0)
+ goto cfg_unlbl_add_map_failure;
+
+ return 0;
+
+cfg_unlbl_add_map_failure:
+ if (entry != NULL)
+ kfree(entry->domain);
+ kfree(entry);
+ return ret_val;
+}
+
+/**
+ * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
+ * @doi_def: the DOI definition
+ * @audit_info: NetLabel audit information
+ *
+ * Description:
+ * Add a new CIPSOv4 DOI definition to the NetLabel subsystem. Returns zero on
+ * success, negative values on failure.
+ *
+ */
+int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
+ struct netlbl_audit *audit_info)
+{
+ int ret_val;
+ const char *type_str;
+ struct audit_buffer *audit_buf;
+
+ ret_val = cipso_v4_doi_add(doi_def);
+
+ audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
+ audit_info);
+ if (audit_buf != NULL) {
+ switch (doi_def->type) {
+ case CIPSO_V4_MAP_STD:
+ type_str = "std";
+ break;
+ case CIPSO_V4_MAP_PASS:
+ type_str = "pass";
+ break;
+ default:
+ type_str = "(unknown)";
+ }
+ audit_log_format(audit_buf,
+ " cipso_doi=%u cipso_type=%s res=%u",
+ doi_def->doi,
+ type_str,
+ ret_val == 0 ? 1 : 0);
+ audit_log_end(audit_buf);
+ }
+
+ return ret_val;
+}
+
+/**
+ * netlbl_cfg_cipsov4_add_map - Add a new CIPSOv4 DOI definition and mapping
+ * @doi_def: the DOI definition
+ * @domain: the domain mapping to add
+ * @audit_info: NetLabel audit information
+ *
+ * Description:
+ * Add a new CIPSOv4 DOI definition and NetLabel/LSM domain mapping for this
+ * new DOI definition to the NetLabel subsystem. A @domain value of NULL adds
+ * a new default domain mapping. Returns zero on success, negative values on
+ * failure.
+ *
+ */
+int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
+ const char *domain,
+ struct netlbl_audit *audit_info)
+{
+ int ret_val = -ENOMEM;
+ struct netlbl_dom_map *entry;
+
+ entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+ if (entry == NULL)
+ goto cfg_cipsov4_add_map_failure;
+ if (domain != NULL) {
+ entry->domain = kstrdup(domain, GFP_ATOMIC);
+ if (entry->domain == NULL)
+ goto cfg_cipsov4_add_map_failure;
+ }
+ entry->type = NETLBL_NLTYPE_CIPSOV4;
+ entry->type_def.cipsov4 = doi_def;
+
+ /* Grab a RCU read lock here so nothing happens to the doi_def variable
+ * between adding it to the CIPSOv4 protocol engine and adding a
+ * domain mapping for it. */
+
+ rcu_read_lock();
+ ret_val = netlbl_cfg_cipsov4_add(doi_def, audit_info);
+ if (ret_val != 0)
+ goto cfg_cipsov4_add_map_failure_unlock;
+ ret_val = netlbl_domhsh_add(entry, audit_info);
+ if (ret_val != 0)
+ goto cfg_cipsov4_add_map_failure_remove_doi;
+ rcu_read_unlock();
+
+ return 0;
+
+cfg_cipsov4_add_map_failure_remove_doi:
+ cipso_v4_doi_remove(doi_def->doi, audit_info, netlbl_cipsov4_doi_free);
+cfg_cipsov4_add_map_failure_unlock:
+ rcu_read_unlock();
+cfg_cipsov4_add_map_failure:
+ return ret_val;
+}
+
+/**
+ * netlbl_cfg_cipsov4_del - Removean existing CIPSOv4 DOI definition
+ * @doi: the CIPSO DOI value
+ * @audit_info: NetLabel audit information
+ *
+ * Description:
+ * Removes an existing CIPSOv4 DOI definition from the NetLabel subsystem.
+ * Returns zero on success, negative values on failure.
+ *
+ */
+int netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
+{
+ return cipso_v4_doi_remove(doi, audit_info, netlbl_cipsov4_doi_free);
+}
+
+/*
* Security Attribute Functions
*/

-


From: Casey Schaufler <casey@...> Subject: [PATCH 2/2] Version 5 (2.6.23-rc8-mm2) Smack: Simplified Mandatory Access Control Kernel Date: Oct 4, 2:23 pm 2007


How is this different...

Fred Flinta (not verified)
on
October 5, 2007 - 6:22am

How is this different from SELinux and TOMOYO Linux, and how does it compare?

Re: How is this different...

on
October 5, 2007 - 11:20pm

Most important difference (I think) is:

SELinux and SMACK : label based MAC
TOMOYO Linux (and AppArmor) : pathname based MAC

It is safe to say that labe based is more reliable. One of the good things with pathname based is readability of policy.

ntpd profile of AppArmor

/usr/sbin/ntpd {
 #include 
 #include 
 #include 
 capability ipc_lock,
 capability net_bind_service,
 capability sys_time,
 capability sys_chroot,
 capability setuid,
 /etc/ntp.conf             r,
 /etc/ntp/drift*           rwl,
 /etc/ntp/keys             r,
 /etc/ntp/step-tickers     r,
 /tmp/ntp*                 rwl,
 /usr/sbin/ntpd            rix,
 /var/log/ntp              w,
 /var/log/ntp.log          w,
 /var/run/ntpd.pid         w,
 /var/lib/ntp/drift        rwl,
 /var/lib/ntp/drift.TEMP   rwl,
 /var/lib/ntp/var/run/ntp/ntpd.pid w,
 /var/lib/ntp/drift/ntp.drift      r,
 /drift/ntp.drift.TEMP     rwl,
 /drift/ntp.drift          rwl,
}

TOMOYO Linux policy for "/etc/rc.d/rc.sysinit"
(quoted from http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/centos4.4/domain_policy....

 /sbin/init /etc/rc.d/rc.sysinit

6 /dev/tty
4 /etc/mtab
4 /etc/nsswitch.conf
4 /etc/passwd
4 /etc/rc.d/rc.sysinit
1 /sbin/initlog
allow_capability SYS_IOCTL

Smack is the *Simplified* Mandatory Access Control Kernel. I'm not sure but somebody on the LKML wrote SELinux and perl script can do the same level simplification (so SMACK is not neccesary).

TOMOYO Linux has a unique feature of automatic policy definition. SELinux and SMACK need policy definition to work, but TOMOYO Linux can generate policy definition if the learning mode is specified. (The above portion is an example)

apparmor has a learning mode too

Anonymous (not verified)
on
October 6, 2007 - 9:21am

and i think selinux allows it too

Re: apparmor has a learning mode too

on
October 10, 2007 - 3:38am

> and i think selinux allows it too

Good point.

In "ApArmor Technical Documentation (April 11, 2007)", there's a section "4.6 Genrating Profiles By Hand". If you take a look at that document, you will find the basic idea is converting logs into profiles (profile means policy in AppArmor). This is like audit2allow of SELinux.

TOMOYO Linux policy learning covers from system boot to shutdown.

<kernel> /usr/sbin/sshd /bin/tcsh /sbin/halt /sbin/shutdown
 
2 /dev/pts/\$
4 /etc/nsswitch.conf
4 /etc/passwd
1 /sbin/init
2 /var/run/shutdown.pid
6 /var/run/utmp
allow_capability SYS_IOCTL
allow_capability SYS_UNLINK
allow_create /var/run/shutdown.pid
allow_unlink /var/run/shutdown.pid

" /usr/sbin/sshd /bin/tcsh /sbin/halt /sbin/shutdown" is a name of the domain, meaning is "a domain of /sbin/shutdown that was execed by /sbin/halt that was execed by /bin/tcsh that was execed /usr/sbin/sshd".

Here's another difference between AppArmor and TOMOYO Linux. AppArmor's policy (profile) is per application while TOMOYO Linux's policy is per "application invocation history". TOMOYO Linux distinguishes firefox by its invocation history (or call chain).

What SELinux does not have is a "learning" mode. SELinux has a same sort of utility that converts logs into policy. And to use SELinux, you have to feed it policy first.

There's a Ubuntu 7.04 Desktop based TOMOYO Linux ISO image. All you need is just set CD and boot. Nothing else is required to see the system behavior. You can save and edit the result. Even changing a mode for " /xxx /xxx /xxx /xxx /yyy/firefox" is possible.

http://tomoyo.sourceforge.jp/incoming/

Not all people needs policy learning feature of TOMOYO Linux, but browsing the generated policy is just so much fun. You can use TOMOYO Linux just to analyze the behavior of *your* system.

My recommendation:

  • If security is your first concern, use SELinux. There's no doubt it's the best choice for Linux and you can trust.
  • If you are teacher and want to make students Linux more secure, AppArmor should be good. Customize profiles carefully and distribute them.
  • If you are interested in what are going on in your Linux box, TOMOYO Linux is for you.

Re: How is this different

on
October 10, 2007 - 3:38am

> How is this different from SELinux and TOMOYO Linux, and how does it compare?

I'm trying to make a comparison chart. Hope this helps.

http://tomoyo.sourceforge.jp/wiki-e/?WhatIs#comparison

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.