This patch is a first attempt at adding auditing support to NetLabel, based on a conversation with Steve Grubb on irc last Friday (9/22). I wanted to send this out to the audit mailing list first to get some feedback on such things as message types and message formats. Once I have collected your feedback I plan on posting the next version of the patch to both the netdev and audit mailing lists for inclusion in 2.6.19.
So please, if you have comments/concerns/etc. please share them now so this does not get help up later - thank you. --- include/linux/audit.h | 6 ++ net/netlabel/netlabel_cipso_v4.c | 37 +++++++++--- net/netlabel/netlabel_domainhash.c | 36 +++++++++++- net/netlabel/netlabel_unlabeled.c | 28 +++++++-- net/netlabel/netlabel_user.c | 110 +++++++++++++++++++++++++++++++++++++ net/netlabel/netlabel_user.h | 6 ++ 6 files changed, 208 insertions(+), 15 deletions(-) Index: net-2.6/include/linux/audit.h =================================================================== --- net-2.6.orig/include/linux/audit.h +++ net-2.6/include/linux/audit.h @@ -95,6 +95,12 @@ #define AUDIT_MAC_POLICY_LOAD 1403 /* Policy file load */ #define AUDIT_MAC_STATUS 1404 /* Changed enforcing,permissive,off */ #define AUDIT_MAC_CONFIG_CHANGE 1405 /* Changes to booleans */ +#define AUDIT_MAC_UNLBL_ACCEPT 1406 /* NetLabel: allow unlabeled traffic */ +#define AUDIT_MAC_UNLBL_DENY 1407 /* NetLabel: deny unlabeled traffic */ +#define AUDIT_MAC_CIPSOV4_ADD 1408 /* NetLabel: add CIPSOv4 DOI entry */ +#define AUDIT_MAC_CIPSOV4_DEL 1409 /* NetLabel: del CIPSOv4 DOI entry */ +#define AUDIT_MAC_MAP_ADD 1410 /* NetLabel: add LSM domain mapping */ +#define AUDIT_MAC_MAP_DEL 1411 /* NetLabel: del LSM domain mapping */ #define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_LAST_KERN_ANOM_MSG 1799 Index: net-2.6/net/netlabel/netlabel_cipso_v4.c =================================================================== --- net-2.6.orig/net/netlabel/netlabel_cipso_v4.c +++ net-2.6/net/netlabel/netlabel_cipso_v4.c @@ -32,6 +32,7 @@ #include <linux/socket.h> #include <linux/string.h> #include <linux/skbuff.h> +#include <linux/audit.h> #include <net/sock.h> #include <net/netlink.h> #include <net/genetlink.h> @@ -162,8 +163,7 @@ static int netlbl_cipsov4_add_std(struct int nla_a_rem; int nla_b_rem; - if (!info->attrs[NLBL_CIPSOV4_A_DOI] || - !info->attrs[NLBL_CIPSOV4_A_TAGLST] || + if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] || !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]) return -EINVAL; @@ -344,8 +344,7 @@ static int netlbl_cipsov4_add_pass(struc int ret_val; struct cipso_v4_doi *doi_def = NULL; - if (!info->attrs[NLBL_CIPSOV4_A_DOI] || - !info->attrs[NLBL_CIPSOV4_A_TAGLST]) + if (!info->attrs[NLBL_CIPSOV4_A_TAGLST]) return -EINVAL; doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); @@ -381,21 +380,34 @@ static int netlbl_cipsov4_add(struct sk_ { int ret_val = -EINVAL; - u32 map_type; + u32 type; + u32 doi; + const char *type_str = "(unknown)"; + struct audit_buffer *audit_buf; - if (!info->attrs[NLBL_CIPSOV4_A_MTYPE]) + if (!info->attrs[NLBL_CIPSOV4_A_DOI] || + !info->attrs[NLBL_CIPSOV4_A_MTYPE]) return -EINVAL; - map_type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]); - switch (map_type) { + type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]); + switch (type) { case CIPSO_V4_MAP_STD: + type_str = "std"; ret_val = netlbl_cipsov4_add_std(info); break; case CIPSO_V4_MAP_PASS: + type_str = "pass"; ret_val = netlbl_cipsov4_add_pass(info); break; } + if (ret_val == 0) { + doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); + audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD); + audit_log_format(audit_buf, " doi=%u type=%s", doi, type_str); + audit_log_end(audit_buf); + } + return ret_val; } @@ -653,13 +665,20 @@ static int netlbl_cipsov4_listall(struct static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) { int ret_val = -EINVAL; - u32 doi; + u32 doi = 0; + struct audit_buffer *audit_buf; if (info->attrs[NLBL_CIPSOV4_A_DOI]) { doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free); } + if (ret_val == 0) { + audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL); + audit_log_format(audit_buf, " doi=%u", doi); + audit_log_end(audit_buf); + } + return ret_val; } Index: net-2.6/net/netlabel/netlabel_domainhash.c =================================================================== --- net-2.6.orig/net/netlabel/netlabel_domainhash.c +++ net-2.6/net/netlabel/netlabel_domainhash.c @@ -35,12 +35,14 @@ #include <linux/skbuff.h> #include <linux/spinlock.h> #include <linux/string.h> +#include <linux/audit.h> #include <net/netlabel.h> #include <net/cipso_ipv4.h> #include <asm/bug.h> #include "netlabel_mgmt.h" #include "netlabel_domainhash.h" +#include "netlabel_user.h" struct netlbl_domhsh_tbl { struct list_head *tbl; @@ -197,6 +199,8 @@ int netlbl_domhsh_add(struct netlbl_dom_ { int ret_val; u32 bkt; + struct audit_buffer *audit_buf; + char *audit_domain; switch (entry->type) { case NETLBL_NLTYPE_UNLABELED: @@ -236,6 +240,25 @@ int netlbl_domhsh_add(struct netlbl_dom_ spin_unlock(&netlbl_domhsh_def_lock); } else ret_val = -EINVAL; + if (ret_val == 0) { + if (entry->domain != NULL) + audit_domain = entry->domain; + else + audit_domain = "(default)"; + audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD); + audit_log_format(audit_buf, " domain=%s", audit_domain); + switch (entry->type) { + case NETLBL_NLTYPE_UNLABELED: + audit_log_format(audit_buf, " protocol=unlbl"); + break; + case NETLBL_NLTYPE_CIPSOV4: + audit_log_format(audit_buf, + " protocol=cipsov4 doi=%u", + entry->type_def.cipsov4->doi); + break; + } + audit_log_end(audit_buf); + } rcu_read_unlock(); if (ret_val != 0) { @@ -280,6 +303,8 @@ int netlbl_domhsh_remove(const char *dom { int ret_val = -ENOENT; struct netlbl_dom_map *entry; + struct audit_buffer *audit_buf; + char *audit_domain; rcu_read_lock(); if (domain != NULL) @@ -316,8 +341,17 @@ int netlbl_domhsh_remove(const char *dom ret_val = -ENOENT; spin_unlock(&netlbl_domhsh_def_lock); } - if (ret_val == 0) + if (ret_val == 0) { + if (entry->domain != NULL) + audit_domain = entry->domain; + else + audit_domain = "(default)"; + audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL); + audit_log_format(audit_buf, " domain=%s", audit_domain); + audit_log_end(audit_buf); + call_rcu(&entry->rcu, netlbl_domhsh_free_entry); + } remove_return: rcu_read_unlock(); Index: net-2.6/net/netlabel/netlabel_unlabeled.c =================================================================== --- net-2.6.orig/net/netlabel/netlabel_unlabeled.c +++ net-2.6/net/netlabel/netlabel_unlabeled.c @@ -64,6 +64,25 @@ static struct nla_policy netlbl_unlabel_ }; /* + * Helper Functions + */ + +/** + * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag + * @value: desired value + * + * Description: + * Set the value of the unlabeled accept flag to @value. + * + */ +static void netlbl_unlabel_acceptflg_set(u8 value) +{ + atomic_set(&netlabel_unlabel_accept_flg, value); + netlbl_audit_nomsg((value ? + AUDIT_MAC_UNLBL_ACCEPT : AUDIT_MAC_UNLBL_DENY)); +} + +/* * NetLabel Command Handlers */ @@ -79,18 +98,17 @@ static struct nla_policy netlbl_unlabel_ */ static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) { - int ret_val = -EINVAL; u8 value; if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) { value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]); if (value == 1 || value == 0) { - atomic_set(&netlabel_unlabel_accept_flg, value); - ret_val = 0; + netlbl_unlabel_acceptflg_set(value); + return 0; } } - return ret_val; + return -EINVAL; } /** @@ -238,7 +256,7 @@ int netlbl_unlabel_defconf(void) if (ret_val != 0) return ret_val; - atomic_set(&netlabel_unlabel_accept_flg, 1); + netlbl_unlabel_acceptflg_set(1); return 0; } Index: net-2.6/net/netlabel/netlabel_user.c =================================================================== --- net-2.6.orig/net/netlabel/netlabel_user.c +++ net-2.6/net/netlabel/netlabel_user.c @@ -32,6 +32,8 @@ #include <linux/types.h> #include <linux/list.h> #include <linux/socket.h> +#include <linux/audit.h> +#include <linux/tty.h> #include <net/sock.h> #include <net/netlink.h> #include <net/genetlink.h> @@ -74,3 +76,111 @@ int netlbl_netlink_init(void) return 0; } + +/* + * NetLabel Audit Functions + */ + +/** + * netlbl_audit_start_common - Start an audit message + * @type: audit message type + * + * Description: + * Start an audit message using the type specified in @type and fill the audit + * message with some fields common to all NetLabel audit messages. Returns + * a pointer to the audit buffer on success, NULL on failure. + * + */ +struct audit_buffer *netlbl_audit_start_common(int type) +{ + struct audit_context *audit_ctx = current->audit_context; + struct audit_buffer *audit_buf; + uid_t audit_loginuid; + const char *audit_tty; + char audit_comm[sizeof(current->comm)]; + struct vm_area_struct *vma; + + audit_buf = audit_log_start(audit_ctx, GFP_ATOMIC, type); + if (audit_buf == NULL) + return NULL; + + switch (type) { + case AUDIT_MAC_UNLBL_ACCEPT: + audit_log_format(audit_buf, + "netlabel: module=unlbl action=accept"); + break; + case AUDIT_MAC_UNLBL_DENY: + audit_log_format(audit_buf, + "netlabel: module=unlbl action=deny"); + break; + case AUDIT_MAC_CIPSOV4_ADD: + audit_log_format(audit_buf, + "netlabel: module=cipsov4 action=add"); + break; + case AUDIT_MAC_CIPSOV4_DEL: + audit_log_format(audit_buf, + "netlabel: module=cipsov4 action=del"); + break; + case AUDIT_MAC_MAP_ADD: + audit_log_format(audit_buf, + "netlabel: module=map action=add"); + break; + case AUDIT_MAC_MAP_DEL: + audit_log_format(audit_buf, + "netlabel: module=map action=del"); + break; + } + + audit_loginuid = audit_get_loginuid(audit_ctx); + if (current->signal && + current->signal->tty && + current->signal->tty->name) + audit_tty = current->signal->tty->name; + else + audit_tty = "(none)"; + get_task_comm(audit_comm, current); + + audit_log_format(audit_buf, + " auid=%u uid=%u euid=%u tty=%s pid=%d", + audit_loginuid, + current->uid, + current->euid, + audit_tty, + current->pid); + audit_log_format(audit_buf, " comm="); + audit_log_untrustedstring(audit_buf, audit_comm); + if (current->mm) { + down_read(¤t->mm->mmap_sem); + vma = current->mm->mmap; + while (vma) { + if ((vma->vm_flags & VM_EXECUTABLE) && + vma->vm_file) { + audit_log_d_path(audit_buf, + " exe=", + vma->vm_file->f_dentry, + vma->vm_file->f_vfsmnt); + break; + } + vma = vma->vm_next; + } + up_read(¤t->mm->mmap_sem); + } + + return audit_buf; +} + +/** + * netlbl_audit_nomsg - Send an audit message without additional text + * @type: audit message type + * + * Description: + * Send an audit message with only the common NetLabel audit fields. + * + */ +void netlbl_audit_nomsg(int type) +{ + struct audit_buffer *audit_buf; + + audit_buf = netlbl_audit_start_common(type); + audit_log_end(audit_buf); +} Index: net-2.6/net/netlabel/netlabel_user.h =================================================================== --- net-2.6.orig/net/netlabel/netlabel_user.h +++ net-2.6/net/netlabel/netlabel_user.h @@ -34,6 +34,7 @@ #include <linux/types.h> #include <linux/skbuff.h> #include <linux/capability.h> +#include <linux/audit.h> #include <net/netlink.h> #include <net/genetlink.h> #include <net/netlabel.h> @@ -75,4 +76,9 @@ static inline void *netlbl_netlink_hdr_p int netlbl_netlink_init(void); +/* NetLabel Audit Functions */ + +struct audit_buffer *netlbl_audit_start_common(int type); +void netlbl_audit_nomsg(int type); + #endif -- paul moore linux security @ hp -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit