Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934508Ab3EGCe7 (ORCPT ); Mon, 6 May 2013 22:34:59 -0400 Received: from cn.fujitsu.com ([222.73.24.84]:43453 "EHLO song.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1759947Ab3EGCTX (ORCPT ); Mon, 6 May 2013 22:19:23 -0400 X-IronPort-AV: E=Sophos;i="4.87,625,1363104000"; d="scan'208";a="7201747" From: Gao feng To: viro@zeniv.linux.org.uk, eparis@redhat.com, ebiederm@xmission.com, sgrubb@redhat.com, akpm@linux-foundation.org, serge.hallyn@ubuntu.com, davem@davemloft.net Cc: netdev@vger.kernel.org, containers@lists.linux-foundation.org, linux-kernel@vger.kernel.org, linux-audit@redhat.com, Gao feng Subject: [PATCH RFC 01/48] Audit: make audit kernel side netlink sock per userns Date: Tue, 7 May 2013 10:20:22 +0800 Message-Id: <1367893269-9308-2-git-send-email-gaofeng@cn.fujitsu.com> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1367893269-9308-1-git-send-email-gaofeng@cn.fujitsu.com> References: <1367893269-9308-1-git-send-email-gaofeng@cn.fujitsu.com> X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/05/07 10:18:25, Serialize by Router on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/05/07 10:18:26, Serialize complete at 2013/05/07 10:18:26 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6779 Lines: 234 This patch try to make the audit_sock per user namespace, not global. Since sock is assigned to net namespace, when creating a netns, we will allocate a audit_sock for the userns which create this netns, and this netns will keep alive until the creator userns being destroyed. If userns create many netns, the audit_sock is only allocated once. Signed-off-by: Gao feng --- include/linux/audit.h | 5 +++ include/linux/user_namespace.h | 9 ++++++ kernel/audit.c | 73 ++++++++++++++++++++++++++++++++++-------- kernel/user_namespace.c | 2 ++ 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 5a6d718..690d7d8 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -429,6 +429,8 @@ static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) { } #endif +extern void audit_free_user_ns(struct user_namespace *ns); + extern int audit_update_lsm_rules(void); /* Private API (for audit.c only) */ @@ -476,6 +478,9 @@ static inline void audit_log_link_denied(const char *string, { } static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) { } + +static inline void audit_free_user_ns(struct user_namespace *ns) +{ } #define audit_enabled 0 #endif /* CONFIG_AUDIT */ static inline void audit_log_string(struct audit_buffer *ab, const char *buf) diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index b6b215f..8797421 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -17,6 +17,12 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */ } extent[UID_GID_MAP_MAX_EXTENTS]; }; +#ifdef CONFIG_AUDIT +struct audit_ctrl { + struct sock *sock; +}; +#endif + struct user_namespace { struct uid_gid_map uid_map; struct uid_gid_map gid_map; @@ -26,6 +32,9 @@ struct user_namespace { kuid_t owner; kgid_t group; unsigned int proc_inum; +#ifdef CONFIG_AUDIT + struct audit_ctrl audit; +#endif bool may_mount_sysfs; bool may_mount_proc; }; diff --git a/kernel/audit.c b/kernel/audit.c index 0b084fa..766dcbf 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -62,6 +62,7 @@ #include #include #include +#include #include "audit.h" @@ -118,9 +119,6 @@ u32 audit_sig_sid = 0; */ static atomic_t audit_lost = ATOMIC_INIT(0); -/* The netlink socket. */ -static struct sock *audit_sock; - /* Hash for inode-based rules */ struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; @@ -404,7 +402,8 @@ static void kauditd_send_skb(struct sk_buff *skb) int err; /* take a reference in case we can't send it and we want to hold it */ skb_get(skb); - err = netlink_unicast(audit_sock, skb, audit_nlk_portid, 0); + err = netlink_unicast(init_user_ns.audit.sock, skb, + audit_nlk_portid, 0); if (err < 0) { BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */ printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid); @@ -481,7 +480,7 @@ int audit_send_list(void *_dest) mutex_unlock(&audit_cmd_mutex); while ((skb = __skb_dequeue(&dest->q)) != NULL) - netlink_unicast(audit_sock, skb, pid, 0); + netlink_unicast(init_user_ns.audit.sock, skb, pid, 0); kfree(dest); @@ -522,7 +521,8 @@ static int audit_send_reply_thread(void *arg) /* Ignore failure. It'll only happen if the sender goes away, because our timeout is set to infinite. */ - netlink_unicast(audit_sock, reply->skb, reply->pid, 0); + netlink_unicast(init_user_ns.audit.sock, reply->skb, + reply->pid, 0); kfree(reply); return 0; } @@ -937,24 +937,56 @@ static void audit_receive(struct sk_buff *skb) mutex_unlock(&audit_cmd_mutex); } +static int __net_init audit_net_init(struct net *net) +{ + struct user_namespace *ns = net->user_ns; + + if (!ns->audit.sock) { + struct sock *sk = NULL; + /* + * create kernel side netlink socket for audit, + * make audit sock per user namespace. + */ + struct netlink_kernel_cfg cfg = { + .input = audit_receive, + }; + + sk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg); + if (!sk) { + if (net_eq(net, &init_net)) + audit_panic("cannot initialize netlink socket"); + return -1; + } + sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; + ns->audit.sock = sk; + /* + * Get reference of net->passive, this force this netns + * to be alive, it will be destroyed when we destroy the + * userns. + */ + atomic_inc(&net->passive); + } + + return 0; +} + +static struct pernet_operations audit_net_ops = { + .init = audit_net_init, +}; + /* Initialize audit support at boot time. */ static int __init audit_init(void) { int i; - struct netlink_kernel_cfg cfg = { - .input = audit_receive, - }; if (audit_initialized == AUDIT_DISABLED) return 0; printk(KERN_INFO "audit: initializing netlink socket (%s)\n", audit_default ? "enabled" : "disabled"); - audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, &cfg); - if (!audit_sock) - audit_panic("cannot initialize netlink socket"); - else - audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; + + if (register_pernet_subsys(&audit_net_ops) < 0) + return -1; skb_queue_head_init(&audit_skb_queue); skb_queue_head_init(&audit_skb_hold_queue); @@ -1549,7 +1581,20 @@ void audit_log_secctx(struct audit_buffer *ab, u32 secid) EXPORT_SYMBOL(audit_log_secctx); #endif +void audit_free_user_ns(struct user_namespace *ns) +{ + if (audit_initialized == AUDIT_DISABLED) + return; + + if (ns->audit.sock) { + struct net *net = sock_net(ns->audit.sock); + netlink_kernel_release(ns->audit.sock); + net_drop_ns(net); + } +} + EXPORT_SYMBOL(audit_log_start); EXPORT_SYMBOL(audit_log_end); EXPORT_SYMBOL(audit_log_format); EXPORT_SYMBOL(audit_log); +EXPORT_SYMBOL(audit_free_user_ns); diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index d8c30db..99de920 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -22,6 +22,7 @@ #include #include #include +#include static struct kmem_cache *user_ns_cachep __read_mostly; @@ -124,6 +125,7 @@ void free_user_ns(struct user_namespace *ns) do { parent = ns->parent; proc_free_inum(ns->proc_inum); + audit_free_user_ns(ns); kmem_cache_free(user_ns_cachep, ns); ns = parent; } while (atomic_dec_and_test(&parent->count)); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/