This patchset try to add namespace support for audit.
I choose to assign audit to the user namespace.
Right now,there are six kinds of namespaces, such as
net, mount, ipc, pid, uts and user. the first five
namespaces have special usage. the audit isn't suitable to
belong to these five namespaces, so the user namespace
may be the best choice.
Through I decide to make audit related resources per user
namespace, but audit uses netlink to communicate between kernel
space and user space, and the netlink is a private resource
of per net namespace. So we need the capability to allow the
netlink sockets to communicate with each other in the same user
namespace even they are in different net namespace. [PATCH 2/48]
does this job, it adds a new function "compare" for per netlink
table to compare two sockets. it means the netlink protocols can
has its own compare fuction, For other protocols, two netlink
sockets are different if they belong to the different net namespace.
For audit protocol, two sockets can be the same even they in different
net namespace,we use user namespace not net namespace to make the
decision.
There is one point that some people may dislike,in [PATCH 1/48],
the kernel side audit netlink socket is created only when we create
the first netns for the userns, and this userns will hold the netns
until we destroy this userns.
The other patches just make the audit related resources per
user namespace.
This patchset is sent as an RFC,any comments are welcome.
Gao feng (48):
Audit: make audit kernel side netlink sock per userns
netlink: Add compare function for netlink_table
Audit: implement audit self-defined compare function
Audit: make audit_skb_queue per user namespace
Audit: make audit_skb_hold_queue per user namespace
Audit: make kauditd_task per user namespace
Audit: make audit_pid per user namespace
Audit: make audit_nlk_portid per user namesapce
Audit: make audit_enabled per user namespace
Audit: change type of audit_ever_enabled to bool
Audit: make audit_ever_enabled per user namespace
Audit: make audit_initialized per user namespace
Audit: only allow init user namespace to change audit_rate_limit
Audit: only allow init user namespace to change audit_failure
Audit: allow to send netlink message to auditd in uninit user
namespace
Audit: user proper user namespace in audit_log_config_change
Audit: make kauditd_wait per user namespace
Audit: make audit_backlog_wait per user namespace
Audit: remove duplicate comments
Audit: introduce new audit logging interface for user namespace
Audit: pass proper user namespace to audit_log_common_recv_msg
Audit: Log audit config change in uninit user namespace
Audit: netfilter: Log xt table replace behavior in proper user
namespace
Audit: xt_AUDIT: Log audit message in proper user namespace
Audit: send reply message to the auditd in proper user namespace
Audit: make audit_inode_hash per user namespace
Audit: make tree_list per user namespace
Audit: make audit filter list per user namespace
Audit: make audit_krule belongs to user namespace
Audit: reply audit filter list request to proper user namespace
Audit: pass proper user namespace to audit_filter_syscall
Audit: pass proper user namespace to audit_filter_inode_name
Audit: Log filter related audit message to proper user namespace
Log audit tree related message in proper user namespace
Audit: Log task related audit message to proper user namespace
Audit: Log watch related audit message to proper user namespace
Audit: translate audit_log_start to audit_log_start_ns
Audit: tty: translate audit_log_start to audit_log_start_ns
Audit: netlabel: translate audit_log_start to audit_log_start_ns
Audit: ima: translate audit_log_start to audit_log_start_ns
Audit: lsm: translate audit_log_start to audit_log_start_ns
Audit: selinux: translate audit_log_start to audit_log_start_ns
Audit: xfrm: translate audit_log_start to audit_log_start_ns
Audit: rename audit_log_start_ns to audit_log_start
Audit: user audit_enabled_ns to replace audit_enabled
Audit: rename audit_enabled_ns to audit_enabled
Audit: make audit_log user namespace awared
Audit: allow root user of un-init user namespace to set audit
drivers/tty/tty_audit.c | 9 +-
include/linux/audit.h | 44 ++--
include/linux/netlink.h | 1 +
include/linux/user_namespace.h | 25 +++
include/net/xfrm.h | 7 +-
kernel/audit.c | 393 +++++++++++++++++++++---------------
kernel/audit.h | 24 +--
kernel/audit_tree.c | 49 ++---
kernel/audit_watch.c | 23 ++-
kernel/auditfilter.c | 76 +++----
kernel/auditsc.c | 156 ++++++++------
kernel/user.c | 19 ++
kernel/user_namespace.c | 3 +
net/core/dev.c | 12 +-
net/ipv4/cipso_ipv4.c | 4 +-
net/netfilter/x_tables.c | 9 +-
net/netfilter/xt_AUDIT.c | 8 +-
net/netlabel/netlabel_domainhash.c | 4 +-
net/netlabel/netlabel_unlabeled.c | 8 +-
net/netlabel/netlabel_user.c | 8 +-
net/netlink/af_netlink.c | 26 ++-
net/netlink/af_netlink.h | 1 +
net/xfrm/xfrm_policy.c | 4 +-
net/xfrm/xfrm_state.c | 14 +-
security/apparmor/lib.c | 2 +-
security/integrity/ima/ima_api.c | 5 +-
security/integrity/ima/ima_audit.c | 11 +-
security/integrity/ima/ima_policy.c | 5 +-
security/lsm_audit.c | 8 +-
security/selinux/avc.c | 3 +-
security/selinux/hooks.c | 17 +-
security/selinux/selinuxfs.c | 9 +-
security/selinux/ss/services.c | 30 ++-
security/smack/smack_lsm.c | 3 +-
34 files changed, 630 insertions(+), 390 deletions(-)
--
1.8.1.4
Now we can log audit message in the user namespace which current
task belongs to.
Signed-off-by: Gao feng <[email protected]>
---
security/selinux/hooks.c | 14 ++++++++++----
security/selinux/ss/services.c | 8 +++++---
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5c6f2cd..93b6c72 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2785,6 +2785,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
struct audit_buffer *ab;
size_t audit_size;
const char *str;
+ struct user_namespace *ns = current_user_ns();
/* We strip a nul only if it is at the end, otherwise the
* context contains a nul and we should audit that */
@@ -2798,10 +2799,11 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
str = "";
audit_size = 0;
}
- ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
+ ab = audit_log_start_ns(ns, current->audit_context,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR);
audit_log_format(ab, "op=setxattr invalid_context=");
audit_log_n_untrustedstring(ab, value, audit_size);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
return rc;
}
@@ -5328,6 +5330,7 @@ static int selinux_setprocattr(struct task_struct *p,
if (!capable(CAP_MAC_ADMIN)) {
struct audit_buffer *ab;
size_t audit_size;
+ struct user_namespace *ns = current_user_ns();
/* We strip a nul only if it is at the end, otherwise the
* context contains a nul and we should audit that */
@@ -5335,10 +5338,13 @@ static int selinux_setprocattr(struct task_struct *p,
audit_size = size - 1;
else
audit_size = size;
- ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
+ ab = audit_log_start_ns(ns,
+ current->audit_context,
+ GFP_ATOMIC,
+ AUDIT_SELINUX_ERR);
audit_log_format(ab, "op=fscreate invalid_context=");
audit_log_n_untrustedstring(ab, value, audit_size);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
return error;
}
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b4feecc..140a383 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -473,6 +473,7 @@ static void security_dump_masked_av(struct context *scontext,
int index;
u32 length;
bool need_comma = false;
+ struct user_namespace *ns;
if (!permissions)
return;
@@ -501,8 +502,9 @@ static void security_dump_masked_av(struct context *scontext,
goto out;
/* audit a message */
- ab = audit_log_start(current->audit_context,
- GFP_ATOMIC, AUDIT_SELINUX_ERR);
+ ns = current_user_ns();
+ ab = audit_log_start_ns(ns, current->audit_context,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR);
if (!ab)
goto out;
@@ -522,7 +524,7 @@ static void security_dump_masked_av(struct context *scontext,
? permission_names[index] : "????");
need_comma = true;
}
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
out:
/* release scontext/tcontext */
kfree(tcontext_name);
--
1.8.1.4
Now we can log audit message in the user namespace which current
task belongs to.
Signed-off-by: Gao feng <[email protected]>
---
security/lsm_audit.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 8d8d97d..90fcd08 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -392,11 +392,15 @@ void common_lsm_audit(struct common_audit_data *a,
void (*post_audit)(struct audit_buffer *, void *))
{
struct audit_buffer *ab;
+ struct user_namespace *ns;
if (a == NULL)
return;
+
+ ns = current_user_ns();
/* we use GFP_ATOMIC so we won't sleep */
- ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC);
+ ab = audit_log_start_ns(ns, current->audit_context,
+ GFP_ATOMIC, AUDIT_AVC);
if (ab == NULL)
return;
@@ -409,5 +413,5 @@ void common_lsm_audit(struct common_audit_data *a,
if (post_audit)
post_audit(ab, a);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
--
1.8.1.4
tree_list is used to list the directory releated audit rules,
it should be per user namespace.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/user_namespace.h | 1 +
kernel/audit.c | 2 ++
kernel/audit.h | 4 ++--
kernel/audit_tree.c | 22 ++++++++++++----------
kernel/auditfilter.c | 2 +-
5 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index c56e276..c870e28 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -32,6 +32,7 @@ struct audit_ctrl {
wait_queue_head_t backlog_wait;
#define AUDIT_INODE_BUCKETS 32
struct list_head inode_hash[AUDIT_INODE_BUCKETS];
+ struct list_head tree_list;
bool ever_enabled;
};
#endif
diff --git a/kernel/audit.c b/kernel/audit.c
index d254827..a0544b1 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1609,6 +1609,8 @@ void audit_set_user_ns(struct user_namespace *ns)
for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
INIT_LIST_HEAD(&ns->audit.inode_hash[i]);
+ INIT_LIST_HEAD(&ns->audit.tree_list);
+
ns->audit.initialized = AUDIT_INITIALIZED;
}
diff --git a/kernel/audit.h b/kernel/audit.h
index a01c892..a509796 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -122,7 +122,7 @@ extern struct audit_chunk *audit_tree_lookup(const struct inode *);
extern void audit_put_chunk(struct audit_chunk *);
extern int audit_tree_match(struct audit_chunk *, struct audit_tree *);
extern int audit_make_tree(struct audit_krule *, char *, u32);
-extern int audit_add_tree_rule(struct audit_krule *);
+extern int audit_add_tree_rule(struct user_namespace *ns, struct audit_krule *);
extern int audit_remove_tree_rule(struct audit_krule *);
extern void audit_trim_trees(void);
extern int audit_tag_tree(char *old, char *new);
@@ -131,7 +131,7 @@ extern void audit_put_tree(struct audit_tree *);
extern void audit_kill_trees(struct list_head *);
#else
#define audit_remove_tree_rule(rule) BUG()
-#define audit_add_tree_rule(rule) -EINVAL
+#define audit_add_tree_rule(ns, rule) -EINVAL
#define audit_make_tree(rule, str, op) -EINVAL
#define audit_trim_trees() (void)0
#define audit_put_tree(tree) (void)0
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index a291aa2..4531d73 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -35,7 +35,6 @@ struct audit_chunk {
} owners[];
};
-static LIST_HEAD(tree_list);
static LIST_HEAD(prune_list);
/*
@@ -581,10 +580,11 @@ static int compare_root(struct vfsmount *mnt, void *arg)
void audit_trim_trees(void)
{
struct list_head cursor;
+ struct list_head *tree_list = ¤t_user_ns()->audit.tree_list;
mutex_lock(&audit_filter_mutex);
- list_add(&cursor, &tree_list);
- while (cursor.next != &tree_list) {
+ list_add(&cursor, tree_list);
+ while (cursor.next != tree_list) {
struct audit_tree *tree;
struct path path;
struct vfsmount *root_mnt;
@@ -651,14 +651,14 @@ static int tag_mount(struct vfsmount *mnt, void *arg)
}
/* called with audit_filter_mutex */
-int audit_add_tree_rule(struct audit_krule *rule)
+int audit_add_tree_rule(struct user_namespace *ns, struct audit_krule *rule)
{
struct audit_tree *seed = rule->tree, *tree;
struct path path;
struct vfsmount *mnt;
int err;
- list_for_each_entry(tree, &tree_list, list) {
+ list_for_each_entry(tree, &ns->audit.tree_list, list) {
if (!strcmp(seed->pathname, tree->pathname)) {
put_tree(seed);
rule->tree = tree;
@@ -667,7 +667,7 @@ int audit_add_tree_rule(struct audit_krule *rule)
}
}
tree = seed;
- list_add(&tree->list, &tree_list);
+ list_add(&tree->list, &ns->audit.tree_list);
list_add(&rule->rlist, &tree->rules);
/* do not set rule->tree yet */
mutex_unlock(&audit_filter_mutex);
@@ -720,6 +720,8 @@ int audit_tag_tree(char *old, char *new)
int failed = 0;
struct path path1, path2;
struct vfsmount *tagged;
+ struct user_namespace *ns = current_user_ns();
+ struct list_head *tree_list = &ns->audit.tree_list;
int err;
err = kern_path(new, 0, &path2);
@@ -737,10 +739,10 @@ int audit_tag_tree(char *old, char *new)
}
mutex_lock(&audit_filter_mutex);
- list_add(&barrier, &tree_list);
+ list_add(&barrier, tree_list);
list_add(&cursor, &barrier);
- while (cursor.next != &tree_list) {
+ while (cursor.next != tree_list) {
struct audit_tree *tree;
int good_one = 0;
@@ -773,13 +775,13 @@ int audit_tag_tree(char *old, char *new)
spin_lock(&hash_lock);
if (!tree->goner) {
list_del(&tree->list);
- list_add(&tree->list, &tree_list);
+ list_add(&tree->list, tree_list);
}
spin_unlock(&hash_lock);
put_tree(tree);
}
- while (barrier.prev != &tree_list) {
+ while (barrier.prev != tree_list) {
struct audit_tree *tree;
tree = container_of(barrier.prev, struct audit_tree, list);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 573385b..3c8fb2e 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -962,7 +962,7 @@ static inline int audit_add_rule(struct user_namespace *ns,
}
}
if (tree) {
- err = audit_add_tree_rule(&entry->rule);
+ err = audit_add_tree_rule(ns, &entry->rule);
if (err) {
mutex_unlock(&audit_filter_mutex);
goto error;
--
1.8.1.4
We can allow audit kernel side netlink sock of uninit
user namespace to send message to the right auditd.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 18cf5ce..d39296b 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -361,9 +361,9 @@ static int audit_set_failure(int state, kuid_t loginuid, u32 sessionid, u32 sid)
* This only holds messages is audit_default is set, aka booting with audit=1
* or building your kernel that way.
*/
-static void audit_hold_skb(struct sk_buff *skb)
+static void audit_hold_skb(struct user_namespace *ns, struct sk_buff *skb)
{
- struct sk_buff_head *list = &init_user_ns.audit.hold_queue;
+ struct sk_buff_head *list = &ns->audit.hold_queue;
if (audit_default &&
skb_queue_len(list) < audit_backlog_limit)
@@ -376,7 +376,7 @@ static void audit_hold_skb(struct sk_buff *skb)
* For one reason or another this nlh isn't getting delivered to the userspace
* audit daemon, just send it to printk.
*/
-static void audit_printk_skb(struct sk_buff *skb)
+static void audit_printk_skb(struct user_namespace *ns, struct sk_buff *skb)
{
struct nlmsghdr *nlh = nlmsg_hdr(skb);
char *data = nlmsg_data(nlh);
@@ -388,24 +388,24 @@ static void audit_printk_skb(struct sk_buff *skb)
audit_log_lost("printk limit exceeded\n");
}
- audit_hold_skb(skb);
+ audit_hold_skb(ns, skb);
}
-static void kauditd_send_skb(struct sk_buff *skb)
+static void kauditd_send_skb(struct user_namespace *ns, 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(init_user_ns.audit.sock, skb,
- init_user_ns.audit.portid, 0);
+ err = netlink_unicast(ns->audit.sock, skb,
+ ns->audit.portid, 0);
if (err < 0) {
BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */
printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n",
- init_user_ns.audit.pid);
+ ns->audit.pid);
audit_log_lost("auditd disappeared\n");
- init_user_ns.audit.pid = 0;
+ ns->audit.pid = 0;
/* we might get lucky and get this in the next auditd */
- audit_hold_skb(skb);
+ audit_hold_skb(ns, skb);
} else
/* drop the extra reference if sent ok */
consume_skb(skb);
@@ -437,7 +437,7 @@ static int kauditd_thread(void *dummy)
skb = skb_dequeue(hold_queue);
if (unlikely(skb)) {
while (skb && ns->audit.pid) {
- kauditd_send_skb(skb);
+ kauditd_send_skb(ns, skb);
skb = skb_dequeue(hold_queue);
}
}
@@ -447,9 +447,9 @@ static int kauditd_thread(void *dummy)
wake_up(&audit_backlog_wait);
if (skb) {
if (ns->audit.pid)
- kauditd_send_skb(skb);
+ kauditd_send_skb(ns, skb);
else
- audit_printk_skb(skb);
+ audit_printk_skb(ns, skb);
} else {
DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_INTERRUPTIBLE);
@@ -1529,7 +1529,7 @@ void audit_log_end(struct audit_buffer *ab)
ab->skb);
wake_up_interruptible(&kauditd_wait);
} else {
- audit_printk_skb(ab->skb);
+ audit_printk_skb(&init_user_ns, ab->skb);
}
ab->skb = NULL;
}
--
1.8.1.4
This patch makes audit_log user namespace awared.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/audit.h | 12 ++++++------
kernel/audit.c | 11 ++++++-----
net/core/dev.c | 12 +++++++-----
security/selinux/avc.c | 3 ++-
security/selinux/hooks.c | 3 ++-
security/selinux/selinuxfs.c | 9 ++++++---
security/selinux/ss/services.c | 24 +++++++++++++++---------
security/smack/smack_lsm.c | 3 ++-
8 files changed, 46 insertions(+), 31 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 3f5dbe3..3af4d5d 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -395,9 +395,9 @@ static inline void audit_ptrace(struct task_struct *t)
#ifdef CONFIG_AUDIT
/* These are defined in audit.c */
/* Public API */
-extern __printf(4, 5)
-void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
- const char *fmt, ...);
+extern __printf(5, 6)
+void audit_log(struct user_namespace *ns, struct audit_context *ctx,
+ gfp_t gfp_mask, int type, const char *fmt, ...);
extern struct audit_buffer *
audit_log_start(struct user_namespace *ns, struct audit_context *ctx,
@@ -448,9 +448,9 @@ extern int audit_receive_filter(int type, int pid, int seq,
u32 sessionid, u32 sid);
#define audit_enabled(ns) (ns->audit.enabled)
#else /* CONFIG_AUDIT */
-static inline __printf(4, 5)
-void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
- const char *fmt, ...)
+static inline __printf(5, 6)
+void audit_log(struct user_namespace *ns, struct audit_context *ctx,
+ gfp_t gfp_mask, int type, const char *fmt, ...)
{ }
static inline
struct audit_buffer *audit_log_start(struct user_namespace *ns,
diff --git a/kernel/audit.c b/kernel/audit.c
index da1c0ad..59e5cca 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -998,7 +998,8 @@ static int __init audit_init(void)
audit_set_user_ns(&init_user_ns);
- audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
+ audit_log(&init_user_ns, NULL, GFP_KERNEL,
+ AUDIT_KERNEL, "initialized");
return 0;
}
@@ -1541,18 +1542,18 @@ void audit_log_end(struct user_namespace *ns, struct audit_buffer *ab)
* audit_log_vformat, and audit_log_end. It may be called
* in any context.
*/
-void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
- const char *fmt, ...)
+void audit_log(struct user_namespace *ns, struct audit_context *ctx,
+ gfp_t gfp_mask, int type, const char *fmt, ...)
{
struct audit_buffer *ab;
va_list args;
- ab = audit_log_start(&init_user_ns, ctx, gfp_mask, type);
+ ab = audit_log_start(ns, ctx, gfp_mask, type);
if (ab) {
va_start(args, fmt);
audit_log_vformat(ab, fmt, args);
va_end(args);
- audit_log_end(&init_user_ns, ab);
+ audit_log_end(ns, ab);
}
}
diff --git a/net/core/dev.c b/net/core/dev.c
index 128ee39..53a4af7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4455,19 +4455,21 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc)
}
}
if (dev->flags != old_flags) {
+ struct user_namespace *ns = current_user_ns();
pr_info("device %s %s promiscuous mode\n",
dev->name,
dev->flags & IFF_PROMISC ? "entered" : "left");
- if (audit_enabled(current_user_ns())) {
+ if (audit_enabled(ns)) {
current_uid_gid(&uid, &gid);
- audit_log(current->audit_context, GFP_ATOMIC,
+ audit_log(ns, current->audit_context,
+ GFP_ATOMIC,
AUDIT_ANOM_PROMISCUOUS,
"dev=%s prom=%d old_prom=%d auid=%u uid=%u gid=%u ses=%u",
dev->name, (dev->flags & IFF_PROMISC),
(old_flags & IFF_PROMISC),
- from_kuid(&init_user_ns, audit_get_loginuid(current)),
- from_kuid(&init_user_ns, uid),
- from_kgid(&init_user_ns, gid),
+ from_kuid(ns, audit_get_loginuid(current)),
+ from_kuid(ns, uid),
+ from_kgid(ns, gid),
audit_get_sessionid(current));
}
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index dad36a6..5559be3 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -172,7 +172,8 @@ void __init avc_init(void)
avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
0, SLAB_PANIC, NULL);
- audit_log(current->audit_context, GFP_KERNEL, AUDIT_KERNEL, "AVC INITIALIZED\n");
+ audit_log(current_user_ns(), current->audit_context,
+ GFP_KERNEL, AUDIT_KERNEL, "AVC INITIALIZED\n");
}
int avc_get_hash_stats(char *page)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3e5a906..ac924af 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4523,7 +4523,8 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
if (err) {
if (err == -EINVAL) {
- audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
+ audit_log(current_user_ns(), current->audit_context,
+ GFP_KERNEL, AUDIT_SELINUX_ERR,
"SELinux: unrecognized netlink message"
" type=%hu for sclass=%hu\n",
nlh->nlmsg_type, sksec->sclass);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index ff42773..4969a5d 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -171,7 +171,8 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
length = task_has_security(current, SECURITY__SETENFORCE);
if (length)
goto out;
- audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
+ audit_log(current_user_ns(), current->audit_context,
+ GFP_KERNEL, AUDIT_MAC_STATUS,
"enforcing=%d old_enforcing=%d auid=%u ses=%u",
new_value, selinux_enforcing,
from_kuid(&init_user_ns, audit_get_loginuid(current)),
@@ -303,7 +304,8 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf,
length = selinux_disable();
if (length)
goto out;
- audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
+ audit_log(current_user_ns(), current->audit_context,
+ GFP_KERNEL, AUDIT_MAC_STATUS,
"selinux=0 auid=%u ses=%u",
from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
@@ -549,7 +551,8 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
length = count;
out1:
- audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
+ audit_log(current_user_ns(), current->audit_context,
+ GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
"policy loaded auid=%u ses=%u",
from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 9cdd1e5..81c6f71 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -728,7 +728,8 @@ static int security_validtrans_handle_fail(struct context *ocontext,
goto out;
if (context_struct_to_string(tcontext, &t, &tlen))
goto out;
- audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ audit_log(current_user_ns(), current->audit_context,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR,
"security_validate_transition: denied for"
" oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
@@ -875,7 +876,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
&old_name, &length) &&
!context_struct_to_string(new_context,
&new_name, &length)) {
- audit_log(current->audit_context,
+ audit_log(current_user_ns(), current->audit_context,
GFP_ATOMIC, AUDIT_SELINUX_ERR,
"op=security_bounded_transition "
"result=denied "
@@ -1345,7 +1346,8 @@ static int compute_sid_handle_invalid_context(
goto out;
if (context_struct_to_string(newcontext, &n, &nlen))
goto out;
- audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ audit_log(current_user_ns(), current->audit_context,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR,
"security_compute_sid: invalid context %s"
" for scontext=%s"
" tcontext=%s"
@@ -2436,8 +2438,8 @@ int security_set_bools(int len, int *values)
for (i = 0; i < len; i++) {
if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
- audit_log(current->audit_context, GFP_ATOMIC,
- AUDIT_MAC_CONFIG_CHANGE,
+ audit_log(current_user_ns(), current->audit_context,
+ GFP_ATOMIC, AUDIT_MAC_CONFIG_CHANGE,
"bool=%s val=%d old_val=%d auid=%u ses=%u",
sym_name(&policydb, SYM_BOOLS, i),
!!values[i],
@@ -2570,7 +2572,8 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
rc = convert_context_handle_invalid_context(&newcon);
if (rc) {
if (!context_struct_to_string(&newcon, &s, &len)) {
- audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ audit_log(current_user_ns(), current->audit_context,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR,
"security_sid_mls_copy: invalid context %s", s);
kfree(s);
}
@@ -2941,7 +2944,8 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
int match = 0;
if (!rule) {
- audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ audit_log(current_user_ns(), actx,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR,
"selinux_audit_rule_match: missing rule\n");
return -ENOENT;
}
@@ -2949,7 +2953,8 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
read_lock(&policy_rwlock);
if (rule->au_seqno < latest_granting) {
- audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ audit_log(current_user_ns(), actx,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR,
"selinux_audit_rule_match: stale rule\n");
match = -ESTALE;
goto out;
@@ -2957,7 +2962,8 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
ctxt = sidtab_search(&sidtab, sid);
if (!ctxt) {
- audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ audit_log(current_user_ns(), actx,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR,
"selinux_audit_rule_match: unrecognized SID %d\n",
sid);
match = -ENOENT;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index d52c780..816d3bb 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3292,7 +3292,8 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
char *rule = vrule;
if (!rule) {
- audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ audit_log(current_user_ns(), actx,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR,
"Smack: missing rule\n");
return -ENOENT;
}
--
1.8.1.4
Now,all the callers of audit_enabled is user namespace
awared, we can rename audit_enable_ns to audit_enabled.
Signed-off-by: Gao feng <[email protected]>
---
drivers/tty/tty_audit.c | 4 ++--
include/linux/audit.h | 6 ++----
include/net/xfrm.h | 2 +-
kernel/audit_watch.c | 2 +-
kernel/auditsc.c | 4 ++--
net/core/dev.c | 2 +-
net/netfilter/x_tables.c | 2 +-
net/netfilter/xt_AUDIT.c | 2 +-
net/netlabel/netlabel_user.c | 2 +-
security/apparmor/lib.c | 2 +-
10 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index f2d6811..8bb92bb 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -99,7 +99,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, kuid_t loginuid,
{
if (buf->valid == 0)
return;
- if (audit_enabled_ns(task_cred_xxx(tsk, user_ns)) == 0) {
+ if (audit_enabled(task_cred_xxx(tsk, user_ns)) == 0) {
buf->valid = 0;
return;
}
@@ -182,7 +182,7 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch)
tty_audit_buf_put(buf);
}
- if (should_audit && audit_enabled_ns(current_user_ns())) {
+ if (should_audit && audit_enabled(current_user_ns())) {
kuid_t auid;
unsigned int sessionid;
diff --git a/include/linux/audit.h b/include/linux/audit.h
index a46efa3..3f5dbe3 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -446,8 +446,7 @@ extern int audit_filter_type(int type);
extern int audit_receive_filter(int type, int pid, int seq,
void *data, size_t datasz, kuid_t loginuid,
u32 sessionid, u32 sid);
-#define audit_enabled (init_user_ns.audit.enabled)
-#define audit_enabled_ns (ns->audit.enabled)
+#define audit_enabled(ns) (ns->audit.enabled)
#else /* CONFIG_AUDIT */
static inline __printf(4, 5)
void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
@@ -495,8 +494,7 @@ static inline void audit_set_user_ns(struct user_namespace *ns)
static inline void audit_free_user_ns(struct user_namespace *ns)
{ }
-#define audit_enabled 0
-#define audit_enabled_ns(ns) 0
+#define audit_enabled(ns) 0
#endif /* CONFIG_AUDIT */
static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
{
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index bb4d6b2..e625ae9 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -685,7 +685,7 @@ static inline struct audit_buffer *xfrm_audit_start(const char *op)
struct audit_buffer *audit_buf = NULL;
struct user_namespace *ns = current_user_ns();
- if (audit_enabled_ns(ns) == 0)
+ if (audit_enabled(ns) == 0)
return NULL;
audit_buf = audit_log_start(ns, current->audit_context,
GFP_ATOMIC, AUDIT_MAC_IPSEC_EVENT);
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 4dcc331..f82edc7 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -240,7 +240,7 @@ static void audit_watch_log_rule_change(struct audit_krule *r,
{
struct user_namespace *ns = current_user_ns();
- if (audit_enabled_ns(ns)) {
+ if (audit_enabled(ns)) {
struct audit_buffer *ab;
ab = audit_log_start(ns, NULL, GFP_NOFS,
AUDIT_CONFIG_CHANGE);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e579b75..8930158 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1782,7 +1782,7 @@ void __audit_syscall_entry(int arch, int major,
BUG_ON(context->in_syscall || context->name_count);
- if (!audit_enabled_ns(ns))
+ if (!audit_enabled(ns))
return;
context->arch = arch;
@@ -2734,7 +2734,7 @@ void audit_core_dumps(long signr)
struct audit_buffer *ab;
struct user_namespace *ns = current_user_ns();
- if (!audit_enabled_ns(ns))
+ if (!audit_enabled(ns))
return;
if (signr == SIGQUIT) /* don't care for those */
diff --git a/net/core/dev.c b/net/core/dev.c
index 651ad69..128ee39 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4458,7 +4458,7 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc)
pr_info("device %s %s promiscuous mode\n",
dev->name,
dev->flags & IFF_PROMISC ? "entered" : "left");
- if (audit_enabled_ns(current_user_ns())) {
+ if (audit_enabled(current_user_ns())) {
current_uid_gid(&uid, &gid);
audit_log(current->audit_context, GFP_ATOMIC,
AUDIT_ANOM_PROMISCUOUS,
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 8be219e..9571d7e 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -858,7 +858,7 @@ xt_replace_table(struct xt_table *table,
local_bh_enable();
#ifdef CONFIG_AUDIT
- if (audit_enabled_ns(ns)) {
+ if (audit_enabled(ns)) {
struct audit_buffer *ab;
ab = audit_log_start(ns, current->audit_context,
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index a0b102a..1079a1ac 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -126,7 +126,7 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
struct user_namespace *ns = net->user_ns;
struct audit_buffer *ab;
- if (audit_enabled_ns(ns) == 0)
+ if (audit_enabled(ns) == 0)
goto errout;
ab = audit_log_start(ns, NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index e9e4e84..098eaa2 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -102,7 +102,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
u32 secctx_len;
struct user_namespace *ns = current_user_ns();
- if (audit_enabled_ns(ns) == 0)
+ if (audit_enabled(ns) == 0)
return NULL;
audit_buf = audit_log_start(ns, current->audit_context,
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 9cae5ce..3058bb1d 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -63,7 +63,7 @@ char *aa_split_fqname(char *fqname, char **ns_name)
*/
void aa_info_message(const char *str)
{
- if (audit_enabled_ns(current_user_ns())) {
+ if (audit_enabled(current_user_ns())) {
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
sa.type = LSM_AUDIT_DATA_NONE;
--
1.8.1.4
We should use the proper user namespace to filter the syscall.
Signed-off-by: Gao feng <[email protected]>
---
kernel/auditsc.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 29c3e05..5401d21 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -866,14 +866,15 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
* also not high enough that we already know we have to write an audit
* record (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT).
*/
-static enum audit_state audit_filter_syscall(struct task_struct *tsk,
+static enum audit_state audit_filter_syscall(struct user_namespace *ns,
+ struct task_struct *tsk,
struct audit_context *ctx,
struct list_head *list)
{
struct audit_entry *e;
enum audit_state state;
- if (init_user_ns.audit.pid && tsk->tgid == init_user_ns.audit.pid)
+ if (ns->audit.pid && tsk->tgid == ns->audit.pid)
return AUDIT_DISABLED;
rcu_read_lock();
@@ -976,7 +977,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
context->return_code = return_code;
if (context->in_syscall && !context->dummy) {
- audit_filter_syscall(tsk, context,
+ audit_filter_syscall(ns, tsk, context,
&ns->audit.filter_list[AUDIT_FILTER_EXIT]);
audit_filter_inodes(tsk, context);
}
@@ -1784,7 +1785,7 @@ void __audit_syscall_entry(int arch, int major,
context->dummy = !audit_n_rules;
if (!context->dummy && state == AUDIT_BUILD_CONTEXT) {
context->prio = 0;
- state = audit_filter_syscall(tsk, context,
+ state = audit_filter_syscall(ns, tsk, context,
&ns->audit.filter_list[AUDIT_FILTER_ENTRY]);
}
if (state == AUDIT_DISABLED)
--
1.8.1.4
Now all of the audit caller have been namespace aware,
we can rename audit_log_start_ns to audit_log_start,
we just need a namespace awared audit interface.
Signed-off-by: Gao feng <[email protected]>
---
drivers/tty/tty_audit.c | 4 +-
include/linux/audit.h | 28 ++++-------
include/net/xfrm.h | 4 +-
kernel/audit.c | 94 ++++++++++++++++---------------------
kernel/audit_tree.c | 4 +-
kernel/audit_watch.c | 4 +-
kernel/auditfilter.c | 4 +-
kernel/auditsc.c | 56 +++++++++++-----------
net/ipv4/cipso_ipv4.c | 4 +-
net/netfilter/x_tables.c | 4 +-
net/netfilter/xt_AUDIT.c | 4 +-
net/netlabel/netlabel_domainhash.c | 4 +-
net/netlabel/netlabel_unlabeled.c | 8 ++--
net/netlabel/netlabel_user.c | 4 +-
net/xfrm/xfrm_policy.c | 4 +-
net/xfrm/xfrm_state.c | 14 +++---
security/integrity/ima/ima_api.c | 6 +--
security/integrity/ima/ima_audit.c | 6 +--
security/integrity/ima/ima_policy.c | 4 +-
security/lsm_audit.c | 6 +--
security/selinux/hooks.c | 16 +++----
security/selinux/ss/services.c | 6 +--
22 files changed, 131 insertions(+), 157 deletions(-)
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index b20ef14..7dfa931 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -67,7 +67,7 @@ static void tty_audit_log(const char *description, struct task_struct *tsk,
struct audit_buffer *ab;
struct user_namespace *ns = task_cred_xxx(tsk, user_ns);
- ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_TTY);
+ ab = audit_log_start(ns, NULL, GFP_KERNEL, AUDIT_TTY);
if (ab) {
char name[sizeof(tsk->comm)];
kuid_t uid = task_uid(tsk);
@@ -83,7 +83,7 @@ static void tty_audit_log(const char *description, struct task_struct *tsk,
audit_log_untrustedstring(ab, name);
audit_log_format(ab, " data=");
audit_log_n_hex(ab, data, size);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
}
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 885e842..a46efa3 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -400,17 +400,13 @@ void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
const char *fmt, ...);
extern struct audit_buffer *
-audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
-
-extern struct audit_buffer *
-audit_log_start_ns(struct user_namespace *ns, struct audit_context *ctx,
- gfp_t gfp_mask, int type);
+audit_log_start(struct user_namespace *ns, struct audit_context *ctx,
+ gfp_t gfp_mask, int type);
extern __printf(2, 3)
void audit_log_format(struct audit_buffer *ab, const char *fmt, ...);
-extern void audit_log_end(struct audit_buffer *ab);
-extern void audit_log_end_ns(struct user_namespace *ns,
- struct audit_buffer *ab);
+extern void audit_log_end(struct user_namespace *ns,
+ struct audit_buffer *ab);
extern int audit_string_contains_control(const char *string,
size_t len);
extern void audit_log_n_hex(struct audit_buffer *ab,
@@ -458,25 +454,17 @@ void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
const char *fmt, ...)
{ }
static inline
-struct audit_buffer *audit_log_start(struct audit_context *ctx,
+struct audit_buffer *audit_log_start(struct user_namespace *ns,
+ struct audit_context *ctx,
gfp_t gfp_mask, int type)
{
return NULL;
}
-static inline
-struct audit_buffer *audit_log_start_ns(struct user_namespace *ns,
- struct audit_context *ctx,
- gfp_t gfp_mask, int type)
-{
- return NULL;
-}
static inline __printf(2, 3)
void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
{ }
-static inline void audit_log_end(struct audit_buffer *ab)
-{ }
-static inline void audit_log_end_ns(struct user_namespace *ns,
- struct audit_buffer *ab)
+static inline void audit_log_end(struct user_namespace *ns,
+ struct audit_buffer *ab)
{ }
static inline void audit_log_n_hex(struct audit_buffer *ab,
const unsigned char *buf, size_t len)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 1a99744..bb4d6b2 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -687,8 +687,8 @@ static inline struct audit_buffer *xfrm_audit_start(const char *op)
if (audit_enabled_ns(ns) == 0)
return NULL;
- audit_buf = audit_log_start_ns(ns, current->audit_context,
- GFP_ATOMIC, AUDIT_MAC_IPSEC_EVENT);
+ audit_buf = audit_log_start(ns, current->audit_context,
+ GFP_ATOMIC, AUDIT_MAC_IPSEC_EVENT);
if (audit_buf == NULL)
return NULL;
audit_log_format(audit_buf, "op=%s", op);
diff --git a/kernel/audit.c b/kernel/audit.c
index 926d59b..da1c0ad 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -249,7 +249,7 @@ static int audit_log_config_change(char *function_name, int new, int old,
struct user_namespace *ns = current_user_ns();
int rc = 0;
- ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ ab = audit_log_start(ns, NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (unlikely(!ab))
return rc;
audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new,
@@ -268,7 +268,7 @@ static int audit_log_config_change(char *function_name, int new, int old,
}
}
audit_log_format(ab, " res=%d", allow_changes);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
return rc;
}
@@ -619,7 +619,7 @@ static int audit_log_common_recv_msg(struct user_namespace *ns,
return rc;
}
- *ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, msg_type);
+ *ab = audit_log_start(ns, NULL, GFP_KERNEL, msg_type);
if (unlikely(!*ab))
return rc;
audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u",
@@ -759,7 +759,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
audit_log_n_untrustedstring(ab, data, size);
}
audit_set_pid(ab, NETLINK_CB(skb).portid);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
break;
case AUDIT_ADD:
@@ -772,7 +772,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
audit_log_format(ab, " audit_enabled=%d res=0",
ns->audit.enabled);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
return -EPERM;
}
/* fallthrough */
@@ -791,7 +791,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
audit_log_format(ab, " audit_enabled=%d res=0",
ns->audit.enabled);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
return -EPERM;
}
/* fallthrough */
@@ -807,7 +807,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
loginuid, sessionid, sid);
audit_log_format(ab, " op=trim res=1");
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
break;
case AUDIT_MAKE_EQUIV: {
void *bufp = data;
@@ -843,7 +843,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
audit_log_format(ab, " new=");
audit_log_untrustedstring(ab, new);
audit_log_format(ab, " res=%d", !err);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
kfree(old);
kfree(new);
break;
@@ -1153,10 +1153,24 @@ static void wait_for_auditd(struct user_namespace *ns,
remove_wait_queue(&ns->audit.backlog_wait, &wait);
}
-struct audit_buffer *audit_log_start_ns(struct user_namespace *ns,
- struct audit_context *ctx,
- gfp_t gfp_mask,
- int type)
+/**
+ * audit_log_start - obtain an audit buffer
+ * @ctx: audit_context (may be NULL)
+ * @gfp_mask: type of allocation
+ * @type: audit message type
+ *
+ * Returns audit_buffer pointer on success or NULL on error.
+ *
+ * Obtain an audit buffer. This routine does locking to obtain the
+ * audit buffer, but then no locking is required for calls to
+ * audit_log_*format. If the task (ctx) is a task that is currently in a
+ * syscall, then the syscall is marked as auditable and an audit record
+ * will be written at syscall exit. If there is no associated task, then
+ * task context (ctx) should be NULL.
+ */
+struct audit_buffer *audit_log_start(struct user_namespace *ns,
+ struct audit_context *ctx,
+ gfp_t gfp_mask, int type)
{
struct audit_buffer *ab = NULL;
struct timespec t;
@@ -1215,27 +1229,6 @@ struct audit_buffer *audit_log_start_ns(struct user_namespace *ns,
/**
- * audit_log_start - obtain an audit buffer
- * @ctx: audit_context (may be NULL)
- * @gfp_mask: type of allocation
- * @type: audit message type
- *
- * Returns audit_buffer pointer on success or NULL on error.
- *
- * Obtain an audit buffer. This routine does locking to obtain the
- * audit buffer, but then no locking is required for calls to
- * audit_log_*format. If the task (ctx) is a task that is currently in a
- * syscall, then the syscall is marked as auditable and an audit record
- * will be written at syscall exit. If there is no associated task, then
- * task context (ctx) should be NULL.
- */
-struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
- int type)
-{
- return audit_log_start_ns(&init_user_ns, ctx, gfp_mask, type);
-}
-
-/**
* audit_expand - expand skb in the audit buffer
* @ab: audit_buffer
* @extra: space to add at tail of the skb
@@ -1491,7 +1484,7 @@ void audit_log_link_denied(const char *operation, struct path *link)
struct audit_buffer *ab;
struct user_namespace *ns = current_user_ns();
- ab = audit_log_start_ns(ns, current->audit_context, GFP_KERNEL,
+ ab = audit_log_start(ns, current->audit_context, GFP_KERNEL,
AUDIT_ANOM_LINK);
if (!ab)
return;
@@ -1502,10 +1495,19 @@ void audit_log_link_denied(const char *operation, struct path *link)
audit_log_format(ab, " dev=");
audit_log_untrustedstring(ab, link->dentry->d_inode->i_sb->s_id);
audit_log_format(ab, " ino=%lu", link->dentry->d_inode->i_ino);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
-void audit_log_end_ns(struct user_namespace *ns, struct audit_buffer *ab)
+/**
+ * audit_log_end - end one audit record
+ * @ab: the audit_buffer
+ *
+ * The netlink_* functions cannot be called inside an irq context, so
+ * the audit buffer is placed on a queue and a tasklet is scheduled to
+ * remove them from the queue outside the irq context. May be called in
+ * any context.
+ */
+void audit_log_end(struct user_namespace *ns, struct audit_buffer *ab)
{
if (!ab)
return;
@@ -1528,20 +1530,6 @@ void audit_log_end_ns(struct user_namespace *ns, struct audit_buffer *ab)
}
/**
- * audit_log_end - end one audit record
- * @ab: the audit_buffer
- *
- * The netlink_* functions cannot be called inside an irq context, so
- * the audit buffer is placed on a queue and a tasklet is scheduled to
- * remove them from the queue outside the irq context. May be called in
- * any context.
- */
-void audit_log_end(struct audit_buffer *ab)
-{
- audit_log_end_ns(&init_user_ns, ab);
-}
-
-/**
* audit_log - Log an audit record
* @ctx: audit context
* @gfp_mask: type of allocation
@@ -1559,12 +1547,12 @@ void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
struct audit_buffer *ab;
va_list args;
- ab = audit_log_start_ns(&init_user_ns, ctx, gfp_mask, type);
+ ab = audit_log_start(&init_user_ns, ctx, gfp_mask, type);
if (ab) {
va_start(args, fmt);
audit_log_vformat(ab, fmt, args);
va_end(args);
- audit_log_end_ns(&init_user_ns, ab);
+ audit_log_end(&init_user_ns, ab);
}
}
@@ -1639,9 +1627,7 @@ void audit_free_user_ns(struct user_namespace *ns)
}
EXPORT_SYMBOL(audit_log_start);
-EXPORT_SYMBOL(audit_log_start_ns);
EXPORT_SYMBOL(audit_log_end);
-EXPORT_SYMBOL(audit_log_end_ns);
EXPORT_SYMBOL(audit_log_format);
EXPORT_SYMBOL(audit_log);
EXPORT_SYMBOL(audit_set_user_ns);
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 521766d..20ffef8 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -453,7 +453,7 @@ static void audit_log_remove_rule(struct user_namespace *ns,
{
struct audit_buffer *ab;
- ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ ab = audit_log_start(ns, NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (unlikely(!ab))
return;
audit_log_format(ab, "op=");
@@ -462,7 +462,7 @@ static void audit_log_remove_rule(struct user_namespace *ns,
audit_log_untrustedstring(ab, rule->tree->pathname);
audit_log_key(ab, rule->filterkey);
audit_log_format(ab, " list=%d res=1", rule->listnr);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
static void kill_rules(struct user_namespace *ns, struct audit_tree *tree)
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 1bac505..4dcc331 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -242,7 +242,7 @@ static void audit_watch_log_rule_change(struct audit_krule *r,
if (audit_enabled_ns(ns)) {
struct audit_buffer *ab;
- ab = audit_log_start_ns(ns, NULL, GFP_NOFS,
+ ab = audit_log_start(ns, NULL, GFP_NOFS,
AUDIT_CONFIG_CHANGE);
if (unlikely(!ab))
return;
@@ -254,7 +254,7 @@ static void audit_watch_log_rule_change(struct audit_krule *r,
audit_log_untrustedstring(ab, w->path);
audit_log_key(ab, r->filterkey);
audit_log_format(ab, " list=%d res=1", r->listnr);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
}
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 8af148b..6052f57 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1125,7 +1125,7 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
if (!ns->audit.enabled)
return;
- ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ ab = audit_log_start(ns, NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (!ab)
return;
audit_log_format(ab, "auid=%u ses=%u",
@@ -1144,7 +1144,7 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
audit_log_string(ab, action);
audit_log_key(ab, rule->filterkey);
audit_log_format(ab, " list=%d res=%d", rule->listnr, res);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
/**
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 3c5ced9..a65020a 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1195,7 +1195,7 @@ static int audit_log_pid_context(struct user_namespace *ns,
u32 len;
int rc = 0;
- ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_OBJ_PID);
+ ab = audit_log_start(ns, context, GFP_KERNEL, AUDIT_OBJ_PID);
if (!ab)
return rc;
@@ -1211,7 +1211,7 @@ static int audit_log_pid_context(struct user_namespace *ns,
}
audit_log_format(ab, " ocomm=");
audit_log_untrustedstring(ab, comm);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
return rc;
}
@@ -1313,8 +1313,8 @@ static int audit_log_single_execve_arg(struct audit_context *context,
room_left -= to_send;
if (room_left < 0) {
*len_sent = 0;
- audit_log_end_ns(ns, *ab);
- *ab = audit_log_start_ns(ns, context,
+ audit_log_end(ns, *ab);
+ *ab = audit_log_start(ns, context,
GFP_KERNEL, AUDIT_EXECVE);
if (!*ab)
return 0;
@@ -1439,7 +1439,7 @@ static void show_special(struct user_namespace *ns,
struct audit_buffer *ab;
int i;
- ab = audit_log_start_ns(ns, context, GFP_KERNEL, context->type);
+ ab = audit_log_start(ns, context, GFP_KERNEL, context->type);
if (!ab)
return;
@@ -1470,8 +1470,8 @@ static void show_special(struct user_namespace *ns,
}
}
if (context->ipc.has_perm) {
- audit_log_end_ns(ns, ab);
- ab = audit_log_start_ns(ns, context, GFP_KERNEL,
+ audit_log_end(ns, ab);
+ ab = audit_log_start(ns, context, GFP_KERNEL,
AUDIT_IPC_SET_PERM);
if (unlikely(!ab))
return;
@@ -1528,7 +1528,7 @@ static void show_special(struct user_namespace *ns,
context->mmap.flags);
break; }
}
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
static void audit_log_name(struct user_namespace *ns,
@@ -1536,7 +1536,7 @@ static void audit_log_name(struct user_namespace *ns,
int record_num, int *call_panic)
{
struct audit_buffer *ab;
- ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_PATH);
+ ab = audit_log_start(ns, context, GFP_KERNEL, AUDIT_PATH);
if (!ab)
return; /* audit_panic has been called */
@@ -1591,7 +1591,7 @@ static void audit_log_name(struct user_namespace *ns,
audit_log_fcaps(ab, n);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
@@ -1605,7 +1605,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
/* tsk == current */
context->personality = tsk->personality;
- ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_SYSCALL);
+ ab = audit_log_start(ns, context, GFP_KERNEL, AUDIT_SYSCALL);
if (!ab)
return; /* audit_panic has been called */
audit_log_format(ab, "arch=%x syscall=%d",
@@ -1627,11 +1627,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
audit_log_task_info(ab, tsk);
audit_log_key(ab, context->filterkey);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
for (aux = context->aux; aux; aux = aux->next) {
- ab = audit_log_start_ns(ns, context, GFP_KERNEL, aux->type);
+ ab = audit_log_start(ns, context, GFP_KERNEL, aux->type);
if (!ab)
continue; /* audit_panic has been called */
@@ -1657,28 +1657,28 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
break; }
}
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
if (context->type)
show_special(ns, context, &call_panic);
if (context->fds[0] >= 0) {
- ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_FD_PAIR);
+ ab = audit_log_start(ns, context, GFP_KERNEL, AUDIT_FD_PAIR);
if (ab) {
audit_log_format(ab, "fd0=%d fd1=%d",
context->fds[0], context->fds[1]);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
}
if (context->sockaddr_len) {
- ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_SOCKADDR);
+ ab = audit_log_start(ns, context, GFP_KERNEL, AUDIT_SOCKADDR);
if (ab) {
audit_log_format(ab, "saddr=");
audit_log_n_hex(ab, (void *)context->sockaddr,
context->sockaddr_len);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
}
@@ -1704,10 +1704,10 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
call_panic = 1;
if (context->pwd.dentry && context->pwd.mnt) {
- ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_CWD);
+ ab = audit_log_start(ns, context, GFP_KERNEL, AUDIT_CWD);
if (ab) {
audit_log_d_path(ab, " cwd=", &context->pwd);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
}
@@ -1716,9 +1716,9 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
audit_log_name(ns, context, n, i++, &call_panic);
/* Send end of event record to help user space know we are finished */
- ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_EOE);
+ ab = audit_log_start(ns, context, GFP_KERNEL, AUDIT_EOE);
if (ab)
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
if (call_panic)
audit_panic("error converting sid to string");
}
@@ -2337,7 +2337,7 @@ int audit_set_loginuid(kuid_t loginuid)
struct audit_buffer *ab;
struct user_namespace *ns = current_user_ns();
- ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_LOGIN);
+ ab = audit_log_start(ns, NULL, GFP_KERNEL, AUDIT_LOGIN);
if (ab) {
audit_log_format(ab, "login pid=%d uid=%u "
"old auid=%u new auid=%u"
@@ -2347,7 +2347,7 @@ int audit_set_loginuid(kuid_t loginuid)
from_kuid(&init_user_ns, task->loginuid),
from_kuid(&init_user_ns, loginuid),
task->sessionid, sessionid);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
}
task->sessionid = sessionid;
@@ -2740,11 +2740,11 @@ void audit_core_dumps(long signr)
if (signr == SIGQUIT) /* don't care for those */
return;
- ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
+ ab = audit_log_start(ns, NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
if (unlikely(!ab))
return;
audit_log_abend(ns, ab, "memory violation", signr);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
void __audit_seccomp(unsigned long syscall, long signr, int code)
@@ -2752,7 +2752,7 @@ void __audit_seccomp(unsigned long syscall, long signr, int code)
struct audit_buffer *ab;
struct user_namespace *ns = current_user_ns();
- ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_SECCOMP);
+ ab = audit_log_start(ns, NULL, GFP_KERNEL, AUDIT_SECCOMP);
if (unlikely(!ab))
return;
audit_log_task(ns, ab);
@@ -2761,7 +2761,7 @@ void __audit_seccomp(unsigned long syscall, long signr, int code)
audit_log_format(ab, " compat=%d", is_compat_task());
audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current));
audit_log_format(ab, " code=0x%x", code);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
struct list_head *audit_killed_trees(void)
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index b021445..d365d84 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -532,7 +532,7 @@ doi_add_return:
audit_log_format(audit_buf,
" cipso_doi=%u cipso_type=%s res=%u",
doi, type_str, ret_val == 0 ? 1 : 0);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
return ret_val;
@@ -622,7 +622,7 @@ doi_remove_return:
audit_log_format(audit_buf,
" cipso_doi=%u res=%u",
doi, ret_val == 0 ? 1 : 0);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
return ret_val;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index ba90a1b..8be219e 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -861,13 +861,13 @@ xt_replace_table(struct xt_table *table,
if (audit_enabled_ns(ns)) {
struct audit_buffer *ab;
- ab = audit_log_start_ns(ns, current->audit_context,
+ ab = audit_log_start(ns, current->audit_context,
GFP_KERNEL, AUDIT_NETFILTER_CFG);
if (ab) {
audit_log_format(ab, "table=%s family=%u entries=%u",
table->name, table->af,
private->number);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
}
#endif
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index b1ffba2..a0b102a 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -129,7 +129,7 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
if (audit_enabled_ns(ns) == 0)
goto errout;
- ab = audit_log_start_ns(ns, NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
+ ab = audit_log_start(ns, NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
if (ab == NULL)
goto errout;
@@ -174,7 +174,7 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
audit_log_secctx(ab, skb->secmark);
#endif
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
errout:
return XT_CONTINUE;
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
index 7fab4b8..7c5d381 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -241,7 +241,7 @@ static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry,
break;
}
audit_log_format(audit_buf, " res=%u", result == 0 ? 1 : 0);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
}
@@ -462,7 +462,7 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry,
" nlbl_domain=%s res=%u",
entry->domain ? entry->domain : "(default)",
ret_val == 0 ? 1 : 0);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
if (ret_val == 0) {
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 7708078..4d62cb7 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -465,7 +465,7 @@ unlhsh_add_return:
security_release_secctx(secctx, secctx_len);
}
audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
return ret_val;
}
@@ -521,7 +521,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
security_release_secctx(secctx, secctx_len);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
if (entry == NULL)
@@ -582,7 +582,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
security_release_secctx(secctx, secctx_len);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
if (entry == NULL)
@@ -766,7 +766,7 @@ static void netlbl_unlabel_acceptflg_set(u8 value,
if (audit_buf != NULL) {
audit_log_format(audit_buf,
" unlbl_accept=%u old=%u", value, old_val);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
}
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index d7550a2..e9e4e84 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -105,8 +105,8 @@ struct audit_buffer *netlbl_audit_start_common(int type,
if (audit_enabled_ns(ns) == 0)
return NULL;
- audit_buf = audit_log_start_ns(ns, current->audit_context,
- GFP_ATOMIC, type);
+ audit_buf = audit_log_start(ns, current->audit_context,
+ GFP_ATOMIC, type);
if (audit_buf == NULL)
return NULL;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f3cc1b9..6aaa5a7 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -3008,7 +3008,7 @@ void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
xfrm_audit_common_policyinfo(xp, audit_buf);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_policy_add);
@@ -3023,7 +3023,7 @@ void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
xfrm_audit_common_policyinfo(xp, audit_buf);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_policy_delete);
#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 50115d9..9c824e7 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2119,7 +2119,7 @@ void xfrm_audit_state_add(struct xfrm_state *x, int result,
xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
xfrm_audit_helper_sainfo(x, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_add);
@@ -2134,7 +2134,7 @@ void xfrm_audit_state_delete(struct xfrm_state *x, int result,
xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
xfrm_audit_helper_sainfo(x, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_delete);
@@ -2152,7 +2152,7 @@ void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
* of audit message */
spi = ntohl(x->id.spi);
audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_replay_overflow);
@@ -2169,7 +2169,7 @@ void xfrm_audit_state_replay(struct xfrm_state *x,
spi = ntohl(x->id.spi);
audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
spi, spi, ntohl(net_seq));
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_replay);
@@ -2181,7 +2181,7 @@ void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family)
if (audit_buf == NULL)
return;
xfrm_audit_helper_pktinfo(skb, family, audit_buf);
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound_simple);
@@ -2198,7 +2198,7 @@ void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
spi = ntohl(net_spi);
audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
spi, spi, ntohl(net_seq));
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound);
@@ -2218,7 +2218,7 @@ void xfrm_audit_state_icvfail(struct xfrm_state *x,
audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
spi, spi, ntohl(net_seq));
}
- audit_log_end_ns(current_user_ns(), audit_buf);
+ audit_log_end(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_icvfail);
#endif /* CONFIG_AUDITSYSCALL */
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index a94b54e..e60147f 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -223,8 +223,8 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
hex_byte_pack(hash + (i * 2), iint->ima_xattr.digest[i]);
hash[i * 2] = '\0';
- ab = audit_log_start_ns(ns, current->audit_context, GFP_KERNEL,
- AUDIT_INTEGRITY_RULE);
+ ab = audit_log_start(ns, current->audit_context, GFP_KERNEL,
+ AUDIT_INTEGRITY_RULE);
if (!ab)
return;
@@ -234,7 +234,7 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
audit_log_untrustedstring(ab, hash);
audit_log_task_info(ab, current);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
iint->flags |= IMA_AUDITED;
}
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
index e7a205b..91e559e 100644
--- a/security/integrity/ima/ima_audit.c
+++ b/security/integrity/ima/ima_audit.c
@@ -39,8 +39,8 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
return;
ns = current_user_ns();
- ab = audit_log_start_ns(ns, current->audit_context,
- GFP_KERNEL, audit_msgno);
+ ab = audit_log_start(ns, current->audit_context,
+ GFP_KERNEL, audit_msgno);
audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u",
current->pid,
from_kuid(ns, current_cred()->uid),
@@ -63,5 +63,5 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
audit_log_format(ab, " ino=%lu", inode->i_ino);
}
audit_log_format(ab, " res=%d", !result);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index c817d35..43e9af6 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -416,7 +416,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
int result = 0;
struct user_namespace *ns = current_user_ns();
- ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
+ ab = audit_log_start(ns, NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
entry->uid = INVALID_UID;
entry->fowner = INVALID_UID;
@@ -634,7 +634,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
else if (entry->func == MODULE_CHECK)
ima_appraise |= IMA_APPRAISE_MODULES;
audit_log_format(ab, "res=%d", !result);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
return result;
}
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 90fcd08..ace11d3 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -399,8 +399,8 @@ void common_lsm_audit(struct common_audit_data *a,
ns = current_user_ns();
/* we use GFP_ATOMIC so we won't sleep */
- ab = audit_log_start_ns(ns, current->audit_context,
- GFP_ATOMIC, AUDIT_AVC);
+ ab = audit_log_start(ns, current->audit_context,
+ GFP_ATOMIC, AUDIT_AVC);
if (ab == NULL)
return;
@@ -413,5 +413,5 @@ void common_lsm_audit(struct common_audit_data *a,
if (post_audit)
post_audit(ab, a);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 93b6c72..3e5a906 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2799,11 +2799,11 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
str = "";
audit_size = 0;
}
- ab = audit_log_start_ns(ns, current->audit_context,
- GFP_ATOMIC, AUDIT_SELINUX_ERR);
+ ab = audit_log_start(ns, current->audit_context,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR);
audit_log_format(ab, "op=setxattr invalid_context=");
audit_log_n_untrustedstring(ab, value, audit_size);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
return rc;
}
@@ -5338,13 +5338,13 @@ static int selinux_setprocattr(struct task_struct *p,
audit_size = size - 1;
else
audit_size = size;
- ab = audit_log_start_ns(ns,
- current->audit_context,
- GFP_ATOMIC,
- AUDIT_SELINUX_ERR);
+ ab = audit_log_start(ns,
+ current->audit_context,
+ GFP_ATOMIC,
+ AUDIT_SELINUX_ERR);
audit_log_format(ab, "op=fscreate invalid_context=");
audit_log_n_untrustedstring(ab, value, audit_size);
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
return error;
}
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 140a383..9cdd1e5 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -503,8 +503,8 @@ static void security_dump_masked_av(struct context *scontext,
/* audit a message */
ns = current_user_ns();
- ab = audit_log_start_ns(ns, current->audit_context,
- GFP_ATOMIC, AUDIT_SELINUX_ERR);
+ ab = audit_log_start(ns, current->audit_context,
+ GFP_ATOMIC, AUDIT_SELINUX_ERR);
if (!ab)
goto out;
@@ -524,7 +524,7 @@ static void security_dump_masked_av(struct context *scontext,
? permission_names[index] : "????");
need_comma = true;
}
- audit_log_end_ns(ns, ab);
+ audit_log_end(ns, ab);
out:
/* release scontext/tcontext */
kfree(tcontext_name);
--
1.8.1.4
This patch reduce the permission check of setting audit.
We already finish the user namespace support for audit,
now we can allow the root user of uninit userns to set
and use the audit subsystem.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 59e5cca..8a27197 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -571,11 +571,6 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
{
int err = 0;
- /* Only support the initial namespaces for now. */
- if ((current_user_ns() != &init_user_ns) ||
- (task_active_pid_ns(current) != &init_pid_ns))
- return -EPERM;
-
switch (msg_type) {
case AUDIT_GET:
case AUDIT_LIST:
@@ -590,13 +585,13 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
case AUDIT_TTY_SET:
case AUDIT_TRIM:
case AUDIT_MAKE_EQUIV:
- if (!capable(CAP_AUDIT_CONTROL))
+ if (!ns_capable(current_user_ns(), CAP_AUDIT_CONTROL))
err = -EPERM;
break;
case AUDIT_USER:
case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
- if (!capable(CAP_AUDIT_WRITE))
+ if (!ns_capable(current_user_ns(), CAP_AUDIT_WRITE))
err = -EPERM;
break;
default: /* bad msg */
--
1.8.1.4
Now we can log audit message in the user namespace which current
task belongs to.
Signed-off-by: Gao feng <[email protected]>
---
include/net/xfrm.h | 7 ++++---
net/xfrm/xfrm_policy.c | 4 ++--
net/xfrm/xfrm_state.c | 14 +++++++-------
3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index ae16531..1a99744 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -683,11 +683,12 @@ struct xfrm_audit {
static inline struct audit_buffer *xfrm_audit_start(const char *op)
{
struct audit_buffer *audit_buf = NULL;
+ struct user_namespace *ns = current_user_ns();
- if (audit_enabled == 0)
+ if (audit_enabled_ns(ns) == 0)
return NULL;
- audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC,
- AUDIT_MAC_IPSEC_EVENT);
+ audit_buf = audit_log_start_ns(ns, current->audit_context,
+ GFP_ATOMIC, AUDIT_MAC_IPSEC_EVENT);
if (audit_buf == NULL)
return NULL;
audit_log_format(audit_buf, "op=%s", op);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 23cea0f..f3cc1b9 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -3008,7 +3008,7 @@ void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
xfrm_audit_common_policyinfo(xp, audit_buf);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_policy_add);
@@ -3023,7 +3023,7 @@ void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
xfrm_audit_common_policyinfo(xp, audit_buf);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_policy_delete);
#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 78f66fa..50115d9 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2119,7 +2119,7 @@ void xfrm_audit_state_add(struct xfrm_state *x, int result,
xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
xfrm_audit_helper_sainfo(x, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_add);
@@ -2134,7 +2134,7 @@ void xfrm_audit_state_delete(struct xfrm_state *x, int result,
xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
xfrm_audit_helper_sainfo(x, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_delete);
@@ -2152,7 +2152,7 @@ void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
* of audit message */
spi = ntohl(x->id.spi);
audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_replay_overflow);
@@ -2169,7 +2169,7 @@ void xfrm_audit_state_replay(struct xfrm_state *x,
spi = ntohl(x->id.spi);
audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
spi, spi, ntohl(net_seq));
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_replay);
@@ -2181,7 +2181,7 @@ void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family)
if (audit_buf == NULL)
return;
xfrm_audit_helper_pktinfo(skb, family, audit_buf);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound_simple);
@@ -2198,7 +2198,7 @@ void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
spi = ntohl(net_spi);
audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
spi, spi, ntohl(net_seq));
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound);
@@ -2218,7 +2218,7 @@ void xfrm_audit_state_icvfail(struct xfrm_state *x,
audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
spi, spi, ntohl(net_seq));
}
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_icvfail);
#endif /* CONFIG_AUDITSYSCALL */
--
1.8.1.4
This patch makes kauditd_task per user namespace,
Since right now we only allow user in init user
namesapce to send audit netlink message to kernel,
so actually the kauditd_task belongs to other user
namespace will still not run.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/user_namespace.h | 1 +
kernel/audit.c | 25 +++++++++++++++----------
2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 53420a4..24f7c2f 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -23,6 +23,7 @@ struct audit_ctrl {
struct sock *sock;
struct sk_buff_head queue;
struct sk_buff_head hold_queue;
+ struct task_struct *kauditd_task;
};
#endif
diff --git a/kernel/audit.c b/kernel/audit.c
index 61562c5..839c4c0 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -129,7 +129,6 @@ static DEFINE_SPINLOCK(audit_freelist_lock);
static int audit_freelist_count;
static LIST_HEAD(audit_freelist);
-static struct task_struct *kauditd_task;
static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
@@ -418,8 +417,9 @@ static void kauditd_send_skb(struct sk_buff *skb)
static int kauditd_thread(void *dummy)
{
struct sk_buff *skb;
- struct sk_buff_head *queue = &init_user_ns.audit.queue;
- struct sk_buff_head *hold_queue = &init_user_ns.audit.hold_queue;
+ struct user_namespace *ns = dummy;
+ struct sk_buff_head *queue = &ns->audit.queue;
+ struct sk_buff_head *hold_queue = &ns->audit.hold_queue;
set_freezable();
while (!kthread_should_stop()) {
@@ -663,14 +663,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
ns = current_user_ns();
/* As soon as there's any sign of userspace auditd,
* start kauditd to talk to it */
- if (!kauditd_task) {
- kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");
- if (IS_ERR(kauditd_task)) {
- err = PTR_ERR(kauditd_task);
- kauditd_task = NULL;
- return err;
- }
+ if (!ns->audit.kauditd_task) {
+ struct task_struct *tsk;
+
+ tsk = kthread_run(kauditd_thread, ns, "kauditd");
+ if (IS_ERR(tsk))
+ return PTR_ERR(tsk);
+
+ ns->audit.kauditd_task = tsk;
}
+
loginuid = audit_get_loginuid(current);
sessionid = audit_get_sessionid(current);
security_task_getsecid(current, &sid);
@@ -1615,6 +1617,9 @@ void audit_free_user_ns(struct user_namespace *ns)
skb_queue_purge(&ns->audit.queue);
skb_queue_purge(&ns->audit.hold_queue);
+
+ if (ns->audit.kauditd_task)
+ kthread_stop(ns->audit.kauditd_task);
}
EXPORT_SYMBOL(audit_log_start);
--
1.8.1.4
Now, we can log filter related audit message to the user namespace
which the task belongs to.
Signed-off-by: Gao feng <[email protected]>
---
kernel/auditfilter.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index f2afe9b..8af148b 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1120,15 +1120,16 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
int res)
{
struct audit_buffer *ab;
+ struct user_namespace *ns = current_user_ns();
- if (!audit_enabled)
+ if (!ns->audit.enabled)
return;
- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (!ab)
return;
audit_log_format(ab, "auid=%u ses=%u",
- from_kuid(&init_user_ns, loginuid), sessionid);
+ from_kuid(ns, loginuid), sessionid);
if (sid) {
char *ctx = NULL;
u32 len;
@@ -1143,7 +1144,7 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
audit_log_string(ab, action);
audit_log_key(ab, rule->filterkey);
audit_log_format(ab, " list=%d res=%d", rule->listnr, res);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
/**
--
1.8.1.4
We should use the proper user namespace's audit.enabled,
not the init_user_ns's audit.enabled.
Signed-off-by: Gao feng <[email protected]>
---
drivers/tty/tty_audit.c | 4 ++--
kernel/auditsc.c | 2 +-
net/core/dev.c | 2 +-
security/apparmor/lib.c | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index 7dfa931..f2d6811 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -99,7 +99,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, kuid_t loginuid,
{
if (buf->valid == 0)
return;
- if (audit_enabled == 0) {
+ if (audit_enabled_ns(task_cred_xxx(tsk, user_ns)) == 0) {
buf->valid = 0;
return;
}
@@ -182,7 +182,7 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch)
tty_audit_buf_put(buf);
}
- if (should_audit && audit_enabled) {
+ if (should_audit && audit_enabled_ns(current_user_ns())) {
kuid_t auid;
unsigned int sessionid;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index a65020a..e579b75 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1782,7 +1782,7 @@ void __audit_syscall_entry(int arch, int major,
BUG_ON(context->in_syscall || context->name_count);
- if (!audit_enabled)
+ if (!audit_enabled_ns(ns))
return;
context->arch = arch;
diff --git a/net/core/dev.c b/net/core/dev.c
index 40b1fad..651ad69 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4458,7 +4458,7 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc)
pr_info("device %s %s promiscuous mode\n",
dev->name,
dev->flags & IFF_PROMISC ? "entered" : "left");
- if (audit_enabled) {
+ if (audit_enabled_ns(current_user_ns())) {
current_uid_gid(&uid, &gid);
audit_log(current->audit_context, GFP_ATOMIC,
AUDIT_ANOM_PROMISCUOUS,
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 7430298..9cae5ce 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -63,7 +63,7 @@ char *aa_split_fqname(char *fqname, char **ns_name)
*/
void aa_info_message(const char *str)
{
- if (audit_enabled) {
+ if (audit_enabled_ns(current_user_ns())) {
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
sa.type = LSM_AUDIT_DATA_NONE;
--
1.8.1.4
Now we can log audit message in the user namespace which current
task belongs to.
Signed-off-by: Gao feng <[email protected]>
---
net/ipv4/cipso_ipv4.c | 4 ++--
net/netlabel/netlabel_domainhash.c | 4 ++--
net/netlabel/netlabel_unlabeled.c | 8 ++++----
net/netlabel/netlabel_user.c | 8 +++++---
4 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 667c1d4..b021445 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -532,7 +532,7 @@ doi_add_return:
audit_log_format(audit_buf,
" cipso_doi=%u cipso_type=%s res=%u",
doi, type_str, ret_val == 0 ? 1 : 0);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
return ret_val;
@@ -622,7 +622,7 @@ doi_remove_return:
audit_log_format(audit_buf,
" cipso_doi=%u res=%u",
doi, ret_val == 0 ? 1 : 0);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
return ret_val;
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
index d8d4243..7fab4b8 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -241,7 +241,7 @@ static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry,
break;
}
audit_log_format(audit_buf, " res=%u", result == 0 ? 1 : 0);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
}
@@ -462,7 +462,7 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry,
" nlbl_domain=%s res=%u",
entry->domain ? entry->domain : "(default)",
ret_val == 0 ? 1 : 0);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
if (ret_val == 0) {
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 8a6c6ea..7708078 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -465,7 +465,7 @@ unlhsh_add_return:
security_release_secctx(secctx, secctx_len);
}
audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
return ret_val;
}
@@ -521,7 +521,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
security_release_secctx(secctx, secctx_len);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
if (entry == NULL)
@@ -582,7 +582,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
security_release_secctx(secctx, secctx_len);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
if (entry == NULL)
@@ -766,7 +766,7 @@ static void netlbl_unlabel_acceptflg_set(u8 value,
if (audit_buf != NULL) {
audit_log_format(audit_buf,
" unlbl_accept=%u old=%u", value, old_val);
- audit_log_end(audit_buf);
+ audit_log_end_ns(current_user_ns(), audit_buf);
}
}
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 9650c4a..d7550a2 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -100,16 +100,18 @@ struct audit_buffer *netlbl_audit_start_common(int type,
struct audit_buffer *audit_buf;
char *secctx;
u32 secctx_len;
+ struct user_namespace *ns = current_user_ns();
- if (audit_enabled == 0)
+ if (audit_enabled_ns(ns) == 0)
return NULL;
- audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, type);
+ audit_buf = audit_log_start_ns(ns, current->audit_context,
+ GFP_ATOMIC, type);
if (audit_buf == NULL)
return NULL;
audit_log_format(audit_buf, "netlabel: auid=%u ses=%u",
- from_kuid(&init_user_ns, audit_info->loginuid),
+ from_kuid(ns, audit_info->loginuid),
audit_info->sessionid);
if (audit_info->secid != 0 &&
--
1.8.1.4
We can log audit message in the user namespace which current
task belongs to.
Signed-off-by: Gao feng <[email protected]>
---
drivers/tty/tty_audit.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index 6953dc8..b20ef14 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -65,8 +65,9 @@ static void tty_audit_log(const char *description, struct task_struct *tsk,
int minor, unsigned char *data, size_t size)
{
struct audit_buffer *ab;
+ struct user_namespace *ns = task_cred_xxx(tsk, user_ns);
- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
+ ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_TTY);
if (ab) {
char name[sizeof(tsk->comm)];
kuid_t uid = task_uid(tsk);
@@ -82,7 +83,7 @@ static void tty_audit_log(const char *description, struct task_struct *tsk,
audit_log_untrustedstring(ab, name);
audit_log_format(ab, " data=");
audit_log_n_hex(ab, data, size);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
}
--
1.8.1.4
Now, we can log watch related audit message to the user namespace
which the task belongs to.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit_watch.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 6be4cbe..1bac505 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -235,22 +235,26 @@ out:
return new;
}
-static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watch *w, char *op)
+static void audit_watch_log_rule_change(struct audit_krule *r,
+ struct audit_watch *w, char *op)
{
- if (audit_enabled) {
+ struct user_namespace *ns = current_user_ns();
+
+ if (audit_enabled_ns(ns)) {
struct audit_buffer *ab;
- ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE);
+ ab = audit_log_start_ns(ns, NULL, GFP_NOFS,
+ AUDIT_CONFIG_CHANGE);
if (unlikely(!ab))
return;
audit_log_format(ab, "auid=%u ses=%u op=",
- from_kuid(&init_user_ns, audit_get_loginuid(current)),
+ from_kuid(ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
audit_log_string(ab, op);
audit_log_format(ab, " path=");
audit_log_untrustedstring(ab, w->path);
audit_log_key(ab, r->filterkey);
audit_log_format(ab, " list=%d res=1", r->listnr);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
}
@@ -262,6 +266,7 @@ static void audit_update_watch(struct audit_parent *parent,
struct audit_watch *owatch, *nwatch, *nextw;
struct audit_krule *r, *nextr;
struct audit_entry *oentry, *nentry;
+ struct user_namespace *ns = current_user_ns();
mutex_lock(&audit_filter_mutex);
/* Run all of the watches on this parent looking for the one that
@@ -274,7 +279,7 @@ static void audit_update_watch(struct audit_parent *parent,
/* If the update involves invalidating rules, do the inode-based
* filtering now, so we don't omit records. */
if (invalidating && !audit_dummy_context())
- audit_filter_inodes(current_user_ns(), current,
+ audit_filter_inodes(ns, current,
current->audit_context);
/* updating ino will likely change which audit_hash_list we
@@ -311,7 +316,7 @@ static void audit_update_watch(struct audit_parent *parent,
nentry->rule.watch = nwatch;
list_add(&nentry->rule.rlist, &nwatch->rules);
list_add_rcu(&nentry->list,
- &init_user_ns.audit.inode_hash[h]);
+ &ns->audit.inode_hash[h]);
list_replace(&oentry->rule.list,
&nentry->rule.list);
}
--
1.8.1.4
We should use the right inode_hash list to filter the
task.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.h | 5 +++--
kernel/audit_watch.c | 3 ++-
kernel/auditsc.c | 14 ++++++++------
3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/kernel/audit.h b/kernel/audit.h
index 7934598..0079cdd 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -157,11 +157,12 @@ static inline int audit_signal_info(int sig, struct task_struct *t)
return __audit_signal_info(sig, t);
return 0;
}
-extern void audit_filter_inodes(struct task_struct *, struct audit_context *);
+extern void audit_filter_inodes(struct user_namespace *ns,
+ struct task_struct *, struct audit_context *);
extern struct list_head *audit_killed_trees(void);
#else
#define audit_signal_info(s,t) AUDIT_DISABLED
-#define audit_filter_inodes(t,c) AUDIT_DISABLED
+#define audit_filter_inodes(n, t, c) AUDIT_DISABLED
#endif
extern struct mutex audit_cmd_mutex;
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 27c7a3b..6be4cbe 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -274,7 +274,8 @@ static void audit_update_watch(struct audit_parent *parent,
/* If the update involves invalidating rules, do the inode-based
* filtering now, so we don't omit records. */
if (invalidating && !audit_dummy_context())
- audit_filter_inodes(current, current->audit_context);
+ audit_filter_inodes(current_user_ns(), current,
+ current->audit_context);
/* updating ino will likely change which audit_hash_list we
* are on so we need a new watch for the new list */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 5401d21..3e3e7c7 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -900,12 +900,13 @@ static enum audit_state audit_filter_syscall(struct user_namespace *ns,
* Given an audit_name check the inode hash table to see if they match.
* Called holding the rcu read lock to protect the use of audit_inode_hash
*/
-static int audit_filter_inode_name(struct task_struct *tsk,
+static int audit_filter_inode_name(struct user_namespace *ns,
+ struct task_struct *tsk,
struct audit_names *n,
struct audit_context *ctx) {
int word, bit;
int h = audit_hash_ino((u32)n->ino);
- struct list_head *list = &init_user_ns.audit.inode_hash[h];
+ struct list_head *list = &ns->audit.inode_hash[h];
struct audit_entry *e;
enum audit_state state;
@@ -931,17 +932,18 @@ static int audit_filter_inode_name(struct task_struct *tsk,
* buckets applicable to the inode numbers in audit_names.
* Regarding audit_state, same rules apply as for audit_filter_syscall().
*/
-void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
+void audit_filter_inodes(struct user_namespace *ns,
+ struct task_struct *tsk, struct audit_context *ctx)
{
struct audit_names *n;
- if (init_user_ns.audit.pid && tsk->tgid == init_user_ns.audit.pid)
+ if (ns->audit.pid && tsk->tgid == ns->audit.pid)
return;
rcu_read_lock();
list_for_each_entry(n, &ctx->names_list, list) {
- if (audit_filter_inode_name(tsk, n, ctx))
+ if (audit_filter_inode_name(ns, tsk, n, ctx))
break;
}
rcu_read_unlock();
@@ -979,7 +981,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
if (context->in_syscall && !context->dummy) {
audit_filter_syscall(ns, tsk, context,
&ns->audit.filter_list[AUDIT_FILTER_EXIT]);
- audit_filter_inodes(tsk, context);
+ audit_filter_inodes(ns, tsk, context);
}
tsk->audit_context = NULL;
--
1.8.1.4
Now, we can log task related audit message to the user namespace
which the task belongs to.
Signed-off-by: Gao feng <[email protected]>
---
kernel/auditsc.c | 114 +++++++++++++++++++++++++++++++------------------------
1 file changed, 64 insertions(+), 50 deletions(-)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 544eb82..3c5ced9 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1185,7 +1185,8 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
EXPORT_SYMBOL(audit_log_task_info);
-static int audit_log_pid_context(struct audit_context *context, pid_t pid,
+static int audit_log_pid_context(struct user_namespace *ns,
+ struct audit_context *context, pid_t pid,
kuid_t auid, kuid_t uid, unsigned int sessionid,
u32 sid, char *comm)
{
@@ -1194,13 +1195,13 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
u32 len;
int rc = 0;
- ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
+ ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_OBJ_PID);
if (!ab)
return rc;
audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
- from_kuid(&init_user_ns, auid),
- from_kuid(&init_user_ns, uid), sessionid);
+ from_kuid(ns, auid),
+ from_kuid(ns, uid), sessionid);
if (security_secid_to_secctx(sid, &ctx, &len)) {
audit_log_format(ab, " obj=(none)");
rc = 1;
@@ -1210,7 +1211,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
}
audit_log_format(ab, " ocomm=");
audit_log_untrustedstring(ab, comm);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
return rc;
}
@@ -1240,6 +1241,7 @@ static int audit_log_single_execve_arg(struct audit_context *context,
size_t len, len_left, to_send;
size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN;
unsigned int i, has_cntl = 0, too_long = 0;
+ struct user_namespace *ns;
int ret;
/* strnlen_user includes the null we don't want to send */
@@ -1293,6 +1295,7 @@ static int audit_log_single_execve_arg(struct audit_context *context,
if (len > max_execve_audit_len)
too_long = 1;
+ ns = current_user_ns();
/* rewalk the argument actually logging the message */
for (i = 0; len_left > 0; i++) {
int room_left;
@@ -1310,8 +1313,9 @@ static int audit_log_single_execve_arg(struct audit_context *context,
room_left -= to_send;
if (room_left < 0) {
*len_sent = 0;
- audit_log_end(*ab);
- *ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE);
+ audit_log_end_ns(ns, *ab);
+ *ab = audit_log_start_ns(ns, context,
+ GFP_KERNEL, AUDIT_EXECVE);
if (!*ab)
return 0;
}
@@ -1429,12 +1433,13 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
audit_log_format(ab, " cap_fe=%d cap_fver=%x", name->fcap.fE, name->fcap_ver);
}
-static void show_special(struct audit_context *context, int *call_panic)
+static void show_special(struct user_namespace *ns,
+ struct audit_context *context, int *call_panic)
{
struct audit_buffer *ab;
int i;
- ab = audit_log_start(context, GFP_KERNEL, context->type);
+ ab = audit_log_start_ns(ns, context, GFP_KERNEL, context->type);
if (!ab)
return;
@@ -1465,9 +1470,9 @@ static void show_special(struct audit_context *context, int *call_panic)
}
}
if (context->ipc.has_perm) {
- audit_log_end(ab);
- ab = audit_log_start(context, GFP_KERNEL,
- AUDIT_IPC_SET_PERM);
+ audit_log_end_ns(ns, ab);
+ ab = audit_log_start_ns(ns, context, GFP_KERNEL,
+ AUDIT_IPC_SET_PERM);
if (unlikely(!ab))
return;
audit_log_format(ab,
@@ -1523,14 +1528,15 @@ static void show_special(struct audit_context *context, int *call_panic)
context->mmap.flags);
break; }
}
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
-static void audit_log_name(struct audit_context *context, struct audit_names *n,
+static void audit_log_name(struct user_namespace *ns,
+ struct audit_context *context, struct audit_names *n,
int record_num, int *call_panic)
{
struct audit_buffer *ab;
- ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
+ ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_PATH);
if (!ab)
return; /* audit_panic has been called */
@@ -1565,8 +1571,8 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
MAJOR(n->dev),
MINOR(n->dev),
n->mode,
- from_kuid(&init_user_ns, n->uid),
- from_kgid(&init_user_ns, n->gid),
+ from_kuid(ns, n->uid),
+ from_kgid(ns, n->gid),
MAJOR(n->rdev),
MINOR(n->rdev));
}
@@ -1585,7 +1591,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
audit_log_fcaps(ab, n);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
@@ -1594,11 +1600,12 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
struct audit_buffer *ab;
struct audit_aux_data *aux;
struct audit_names *n;
+ struct user_namespace *ns = task_cred_xxx(tsk, user_ns);
/* tsk == current */
context->personality = tsk->personality;
- ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
+ ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_SYSCALL);
if (!ab)
return; /* audit_panic has been called */
audit_log_format(ab, "arch=%x syscall=%d",
@@ -1620,11 +1627,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
audit_log_task_info(ab, tsk);
audit_log_key(ab, context->filterkey);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
for (aux = context->aux; aux; aux = aux->next) {
- ab = audit_log_start(context, GFP_KERNEL, aux->type);
+ ab = audit_log_start_ns(ns, context, GFP_KERNEL, aux->type);
if (!ab)
continue; /* audit_panic has been called */
@@ -1650,28 +1657,28 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
break; }
}
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
if (context->type)
- show_special(context, &call_panic);
+ show_special(ns, context, &call_panic);
if (context->fds[0] >= 0) {
- ab = audit_log_start(context, GFP_KERNEL, AUDIT_FD_PAIR);
+ ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_FD_PAIR);
if (ab) {
audit_log_format(ab, "fd0=%d fd1=%d",
context->fds[0], context->fds[1]);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
}
if (context->sockaddr_len) {
- ab = audit_log_start(context, GFP_KERNEL, AUDIT_SOCKADDR);
+ ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_SOCKADDR);
if (ab) {
audit_log_format(ab, "saddr=");
audit_log_n_hex(ab, (void *)context->sockaddr,
context->sockaddr_len);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
}
@@ -1679,7 +1686,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
struct audit_aux_data_pids *axs = (void *)aux;
for (i = 0; i < axs->pid_count; i++)
- if (audit_log_pid_context(context, axs->target_pid[i],
+ if (audit_log_pid_context(ns, context,
+ axs->target_pid[i],
axs->target_auid[i],
axs->target_uid[i],
axs->target_sessionid[i],
@@ -1689,28 +1697,28 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
}
if (context->target_pid &&
- audit_log_pid_context(context, context->target_pid,
+ audit_log_pid_context(ns, context, context->target_pid,
context->target_auid, context->target_uid,
context->target_sessionid,
context->target_sid, context->target_comm))
call_panic = 1;
if (context->pwd.dentry && context->pwd.mnt) {
- ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
+ ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_CWD);
if (ab) {
audit_log_d_path(ab, " cwd=", &context->pwd);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
}
i = 0;
list_for_each_entry(n, &context->names_list, list)
- audit_log_name(context, n, i++, &call_panic);
+ audit_log_name(ns, context, n, i++, &call_panic);
/* Send end of event record to help user space know we are finished */
- ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
+ ab = audit_log_start_ns(ns, context, GFP_KERNEL, AUDIT_EOE);
if (ab)
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
if (call_panic)
audit_panic("error converting sid to string");
}
@@ -2327,8 +2335,9 @@ int audit_set_loginuid(kuid_t loginuid)
sessionid = atomic_inc_return(&session_id);
if (context && context->in_syscall) {
struct audit_buffer *ab;
+ struct user_namespace *ns = current_user_ns();
- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
+ ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_LOGIN);
if (ab) {
audit_log_format(ab, "login pid=%d uid=%u "
"old auid=%u new auid=%u"
@@ -2338,7 +2347,7 @@ int audit_set_loginuid(kuid_t loginuid)
from_kuid(&init_user_ns, task->loginuid),
from_kuid(&init_user_ns, loginuid),
task->sessionid, sessionid);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
}
task->sessionid = sessionid;
@@ -2560,8 +2569,9 @@ int __audit_signal_info(int sig, struct task_struct *t)
struct task_struct *tsk = current;
struct audit_context *ctx = tsk->audit_context;
kuid_t uid = current_uid(), t_uid = task_uid(t);
+ int audit_pid = current_user_ns()->audit.pid;
- if (init_user_ns.audit.pid && t->tgid == init_user_ns.audit.pid) {
+ if (audit_pid && t->tgid == audit_pid) {
if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) {
audit_sig_pid = tsk->pid;
if (uid_valid(tsk->loginuid))
@@ -2683,7 +2693,8 @@ void __audit_mmap_fd(int fd, int flags)
context->type = AUDIT_MMAP;
}
-static void audit_log_task(struct audit_buffer *ab)
+static void audit_log_task(struct user_namespace *ns,
+ struct audit_buffer *ab)
{
kuid_t auid, uid;
kgid_t gid;
@@ -2694,18 +2705,19 @@ static void audit_log_task(struct audit_buffer *ab)
current_uid_gid(&uid, &gid);
audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
- from_kuid(&init_user_ns, auid),
- from_kuid(&init_user_ns, uid),
- from_kgid(&init_user_ns, gid),
+ from_kuid(ns, auid),
+ from_kuid(ns, uid),
+ from_kgid(ns, gid),
sessionid);
audit_log_task_context(ab);
audit_log_format(ab, " pid=%d comm=", current->pid);
audit_log_untrustedstring(ab, current->comm);
}
-static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
+static void audit_log_abend(struct user_namespace *ns,
+ struct audit_buffer *ab, char *reason, long signr)
{
- audit_log_task(ab);
+ audit_log_task(ns, ab);
audit_log_format(ab, " reason=");
audit_log_string(ab, reason);
audit_log_format(ab, " sig=%ld", signr);
@@ -2720,34 +2732,36 @@ static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
void audit_core_dumps(long signr)
{
struct audit_buffer *ab;
+ struct user_namespace *ns = current_user_ns();
- if (!audit_enabled)
+ if (!audit_enabled_ns(ns))
return;
if (signr == SIGQUIT) /* don't care for those */
return;
- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
+ ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
if (unlikely(!ab))
return;
- audit_log_abend(ab, "memory violation", signr);
- audit_log_end(ab);
+ audit_log_abend(ns, ab, "memory violation", signr);
+ audit_log_end_ns(ns, ab);
}
void __audit_seccomp(unsigned long syscall, long signr, int code)
{
struct audit_buffer *ab;
+ struct user_namespace *ns = current_user_ns();
- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP);
+ ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_SECCOMP);
if (unlikely(!ab))
return;
- audit_log_task(ab);
+ audit_log_task(ns, ab);
audit_log_format(ab, " sig=%ld", signr);
audit_log_format(ab, " syscall=%ld", syscall);
audit_log_format(ab, " compat=%d", is_compat_task());
audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current));
audit_log_format(ab, " code=0x%x", code);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
struct list_head *audit_killed_trees(void)
--
1.8.1.4
This patch translates the call of interface audit_log_start to
the namespace aware interface audit_log_start_ns.
After we finish translation, we can rename audit_log_start_ns
to audit_log_start.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index f723fe2..926d59b 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1489,9 +1489,10 @@ void audit_log_key(struct audit_buffer *ab, char *key)
void audit_log_link_denied(const char *operation, struct path *link)
{
struct audit_buffer *ab;
+ struct user_namespace *ns = current_user_ns();
- ab = audit_log_start(current->audit_context, GFP_KERNEL,
- AUDIT_ANOM_LINK);
+ ab = audit_log_start_ns(ns, current->audit_context, GFP_KERNEL,
+ AUDIT_ANOM_LINK);
if (!ab)
return;
audit_log_format(ab, "op=%s action=denied", operation);
@@ -1501,7 +1502,7 @@ void audit_log_link_denied(const char *operation, struct path *link)
audit_log_format(ab, " dev=");
audit_log_untrustedstring(ab, link->dentry->d_inode->i_sb->s_id);
audit_log_format(ab, " ino=%lu", link->dentry->d_inode->i_ino);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
void audit_log_end_ns(struct user_namespace *ns, struct audit_buffer *ab)
@@ -1558,12 +1559,12 @@ void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
struct audit_buffer *ab;
va_list args;
- ab = audit_log_start(ctx, gfp_mask, type);
+ ab = audit_log_start_ns(&init_user_ns, ctx, gfp_mask, type);
if (ab) {
va_start(args, fmt);
audit_log_vformat(ab, fmt, args);
va_end(args);
- audit_log_end(ab);
+ audit_log_end_ns(&init_user_ns, ab);
}
}
--
1.8.1.4
Now we can log audit message in the user namespace which current
task belongs to.
Signed-off-by: Gao feng <[email protected]>
---
security/integrity/ima/ima_api.c | 7 ++++---
security/integrity/ima/ima_audit.c | 11 +++++++----
security/integrity/ima/ima_policy.c | 5 +++--
3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 1c03e8f1..a94b54e 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -213,6 +213,7 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
{
struct audit_buffer *ab;
char hash[(IMA_DIGEST_SIZE * 2) + 1];
+ struct user_namespace *ns = current_user_ns();
int i;
if (iint->flags & IMA_AUDITED)
@@ -222,8 +223,8 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
hex_byte_pack(hash + (i * 2), iint->ima_xattr.digest[i]);
hash[i * 2] = '\0';
- ab = audit_log_start(current->audit_context, GFP_KERNEL,
- AUDIT_INTEGRITY_RULE);
+ ab = audit_log_start_ns(ns, current->audit_context, GFP_KERNEL,
+ AUDIT_INTEGRITY_RULE);
if (!ab)
return;
@@ -233,7 +234,7 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
audit_log_untrustedstring(ab, hash);
audit_log_task_info(ab, current);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
iint->flags |= IMA_AUDITED;
}
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
index c586faa..e7a205b 100644
--- a/security/integrity/ima/ima_audit.c
+++ b/security/integrity/ima/ima_audit.c
@@ -33,15 +33,18 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
const char *cause, int result, int audit_info)
{
struct audit_buffer *ab;
+ struct user_namespace *ns;
if (!ima_audit && audit_info == 1) /* Skip informational messages */
return;
- ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno);
+ ns = current_user_ns();
+ ab = audit_log_start_ns(ns, current->audit_context,
+ GFP_KERNEL, audit_msgno);
audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u",
current->pid,
- from_kuid(&init_user_ns, current_cred()->uid),
- from_kuid(&init_user_ns, audit_get_loginuid(current)),
+ from_kuid(ns, current_cred()->uid),
+ from_kuid(ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
audit_log_task_context(ab);
audit_log_format(ab, " op=");
@@ -60,5 +63,5 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
audit_log_format(ab, " ino=%lu", inode->i_ino);
}
audit_log_format(ab, " res=%d", !result);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 399433a..c817d35 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -414,8 +414,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
struct audit_buffer *ab;
char *p;
int result = 0;
+ struct user_namespace *ns = current_user_ns();
- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
+ ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
entry->uid = INVALID_UID;
entry->fowner = INVALID_UID;
@@ -633,7 +634,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
else if (entry->func == MODULE_CHECK)
ima_appraise |= IMA_APPRAISE_MODULES;
audit_log_format(ab, "res=%d", !result);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
return result;
}
--
1.8.1.4
Now, we can log audit tree related message in the right
user namespace.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.h | 4 ++--
kernel/audit_tree.c | 27 ++++++++++++++-------------
kernel/auditsc.c | 6 ++++--
3 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/kernel/audit.h b/kernel/audit.h
index 0079cdd..64ee671 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -129,7 +129,7 @@ extern void audit_trim_trees(void);
extern int audit_tag_tree(char *old, char *new);
extern const char *audit_tree_path(struct audit_tree *);
extern void audit_put_tree(struct audit_tree *);
-extern void audit_kill_trees(struct list_head *);
+extern void audit_kill_trees(struct user_namespace *ns, struct list_head *);
#else
#define audit_remove_tree_rule(rule) BUG()
#define audit_add_tree_rule(ns, rule) -EINVAL
@@ -138,7 +138,7 @@ extern void audit_kill_trees(struct list_head *);
#define audit_put_tree(tree) (void)0
#define audit_tag_tree(old, new) -EINVAL
#define audit_tree_path(rule) "" /* never called */
-#define audit_kill_trees(list) BUG()
+#define audit_kill_trees(ns, list) BUG()
#endif
extern char *audit_unpack_string(void **, size_t *, size_t);
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 4531d73..521766d 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -448,11 +448,12 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
return 0;
}
-static void audit_log_remove_rule(struct audit_krule *rule)
+static void audit_log_remove_rule(struct user_namespace *ns,
+ struct audit_krule *rule)
{
struct audit_buffer *ab;
- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (unlikely(!ab))
return;
audit_log_format(ab, "op=");
@@ -461,10 +462,10 @@ static void audit_log_remove_rule(struct audit_krule *rule)
audit_log_untrustedstring(ab, rule->tree->pathname);
audit_log_key(ab, rule->filterkey);
audit_log_format(ab, " list=%d res=1", rule->listnr);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
-static void kill_rules(struct audit_tree *tree)
+static void kill_rules(struct user_namespace *ns, struct audit_tree *tree)
{
struct audit_krule *rule, *next;
struct audit_entry *entry;
@@ -475,7 +476,7 @@ static void kill_rules(struct audit_tree *tree)
list_del_init(&rule->rlist);
if (rule->tree) {
/* not a half-baked one */
- audit_log_remove_rule(rule);
+ audit_log_remove_rule(ns, rule);
rule->tree = NULL;
list_del_rcu(&entry->list);
list_del(&entry->rule.list);
@@ -503,7 +504,7 @@ static void prune_one(struct audit_tree *victim)
/* trim the uncommitted chunks from tree */
-static void trim_marked(struct audit_tree *tree)
+static void trim_marked(struct user_namespace *ns, struct audit_tree *tree)
{
struct list_head *p, *q;
spin_lock(&hash_lock);
@@ -536,7 +537,7 @@ static void trim_marked(struct audit_tree *tree)
tree->goner = 1;
spin_unlock(&hash_lock);
mutex_lock(&audit_filter_mutex);
- kill_rules(tree);
+ kill_rules(ns, tree);
list_del_init(&tree->list);
mutex_unlock(&audit_filter_mutex);
prune_one(tree);
@@ -616,7 +617,7 @@ void audit_trim_trees(void)
node->index &= ~(1U<<31);
}
spin_unlock(&hash_lock);
- trim_marked(tree);
+ trim_marked(current_user_ns(), tree);
drop_collected_mounts(root_mnt);
skip_it:
put_tree(tree);
@@ -693,7 +694,7 @@ int audit_add_tree_rule(struct user_namespace *ns, struct audit_krule *rule)
node->index &= ~(1U<<31);
spin_unlock(&hash_lock);
} else {
- trim_marked(tree);
+ trim_marked(ns, tree);
goto Err;
}
@@ -797,7 +798,7 @@ int audit_tag_tree(char *old, char *new)
node->index &= ~(1U<<31);
spin_unlock(&hash_lock);
} else {
- trim_marked(tree);
+ trim_marked(ns, tree);
}
put_tree(tree);
@@ -847,7 +848,7 @@ static void audit_schedule_prune(void)
* ... and that one is done if evict_chunk() decides to delay until the end
* of syscall. Runs synchronously.
*/
-void audit_kill_trees(struct list_head *list)
+void audit_kill_trees(struct user_namespace *ns, struct list_head *list)
{
mutex_lock(&audit_cmd_mutex);
mutex_lock(&audit_filter_mutex);
@@ -856,7 +857,7 @@ void audit_kill_trees(struct list_head *list)
struct audit_tree *victim;
victim = list_entry(list->next, struct audit_tree, list);
- kill_rules(victim);
+ kill_rules(ns, victim);
list_del_init(&victim->list);
mutex_unlock(&audit_filter_mutex);
@@ -895,7 +896,7 @@ static void evict_chunk(struct audit_chunk *chunk)
list_del_init(&owner->same_root);
spin_unlock(&hash_lock);
if (!postponed) {
- kill_rules(owner);
+ kill_rules(current_user_ns(), owner);
list_move(&owner->list, &prune_list);
need_prune = 1;
} else {
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 3e3e7c7..544eb82 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1737,7 +1737,8 @@ void __audit_free(struct task_struct *tsk)
if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT)
audit_log_exit(context, tsk);
if (!list_empty(&context->killed_trees))
- audit_kill_trees(&context->killed_trees);
+ audit_kill_trees(task_cred_xxx(tsk, user_ns),
+ &context->killed_trees);
audit_free_context(context);
}
@@ -1815,6 +1816,7 @@ void __audit_syscall_exit(int success, long return_code)
{
struct task_struct *tsk = current;
struct audit_context *context;
+ struct user_namespace *ns = current_user_ns();
if (success)
success = AUDITSC_SUCCESS;
@@ -1832,7 +1834,7 @@ void __audit_syscall_exit(int success, long return_code)
context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
if (!list_empty(&context->killed_trees))
- audit_kill_trees(&context->killed_trees);
+ audit_kill_trees(ns, &context->killed_trees);
audit_free_names(context);
unroll_tree_refs(context, NULL, 0);
--
1.8.1.4
After this patch, ervery user namespace has one
audit_skb_hold_queue. Since we havn't finish the
preparations, only allow user to operate the skb
hold queue of init user namespace.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/user_namespace.h | 1 +
kernel/audit.c | 16 +++++++++-------
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index e322f20..53420a4 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -22,6 +22,7 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */
struct audit_ctrl {
struct sock *sock;
struct sk_buff_head queue;
+ struct sk_buff_head hold_queue;
};
#endif
diff --git a/kernel/audit.c b/kernel/audit.c
index 2a727af..61562c5 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -129,8 +129,6 @@ static DEFINE_SPINLOCK(audit_freelist_lock);
static int audit_freelist_count;
static LIST_HEAD(audit_freelist);
-/* queue of skbs to send to auditd when/if it comes back */
-static struct sk_buff_head audit_skb_hold_queue;
static struct task_struct *kauditd_task;
static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
@@ -370,9 +368,11 @@ static int audit_set_failure(int state, kuid_t loginuid, u32 sessionid, u32 sid)
*/
static void audit_hold_skb(struct sk_buff *skb)
{
+ struct sk_buff_head *list = &init_user_ns.audit.hold_queue;
+
if (audit_default &&
- skb_queue_len(&audit_skb_hold_queue) < audit_backlog_limit)
- skb_queue_tail(&audit_skb_hold_queue, skb);
+ skb_queue_len(list) < audit_backlog_limit)
+ skb_queue_tail(list, skb);
else
kfree_skb(skb);
}
@@ -419,6 +419,7 @@ static int kauditd_thread(void *dummy)
{
struct sk_buff *skb;
struct sk_buff_head *queue = &init_user_ns.audit.queue;
+ struct sk_buff_head *hold_queue = &init_user_ns.audit.hold_queue;
set_freezable();
while (!kthread_should_stop()) {
@@ -436,11 +437,11 @@ static int kauditd_thread(void *dummy)
* note and still have no friggin idea what i'm thinking today.
*/
if (audit_default && audit_pid) {
- skb = skb_dequeue(&audit_skb_hold_queue);
+ skb = skb_dequeue(hold_queue);
if (unlikely(skb)) {
while (skb && audit_pid) {
kauditd_send_skb(skb);
- skb = skb_dequeue(&audit_skb_hold_queue);
+ skb = skb_dequeue(hold_queue);
}
}
}
@@ -998,7 +999,6 @@ static int __init audit_init(void)
return -1;
audit_set_user_ns(&init_user_ns);
- skb_queue_head_init(&audit_skb_hold_queue);
audit_initialized = AUDIT_INITIALIZED;
audit_enabled = audit_default;
audit_ever_enabled |= !!audit_default;
@@ -1599,6 +1599,7 @@ void audit_set_user_ns(struct user_namespace *ns)
return;
skb_queue_head_init(&ns->audit.queue);
+ skb_queue_head_init(&ns->audit.hold_queue);
}
void audit_free_user_ns(struct user_namespace *ns)
@@ -1613,6 +1614,7 @@ void audit_free_user_ns(struct user_namespace *ns)
}
skb_queue_purge(&ns->audit.queue);
+ skb_queue_purge(&ns->audit.hold_queue);
}
EXPORT_SYMBOL(audit_log_start);
--
1.8.1.4
We can send the audit reply message to userspace auditd
process which running in the same user namespace with the
process which send the audit request message to kernel.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index cac4b21..ca9e046 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -144,6 +144,7 @@ struct audit_buffer {
struct audit_reply {
int pid;
struct sk_buff *skb;
+ struct user_namespace *ns;
};
static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
@@ -517,8 +518,9 @@ 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(init_user_ns.audit.sock, reply->skb,
+ netlink_unicast(reply->ns->audit.sock, reply->skb,
reply->pid, 0);
+ put_user_ns(reply->ns);
kfree(reply);
return 0;
}
@@ -552,11 +554,13 @@ static void audit_send_reply(int pid, int seq, int type, int done, int multi,
reply->pid = pid;
reply->skb = skb;
+ reply->ns = get_user_ns(current_user_ns());
tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");
if (!IS_ERR(tsk))
return;
kfree_skb(skb);
+ put_user_ns(reply->ns);
out:
kfree(reply);
}
@@ -859,7 +863,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
security_release_secctx(ctx, len);
return -ENOMEM;
}
- sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
+ sig_data->uid = from_kuid(ns, audit_sig_uid);
sig_data->pid = audit_sig_pid;
if (audit_sig_sid) {
memcpy(sig_data->ctx, ctx, len);
--
1.8.1.4
audit_inode_hash is used to hash inode related audit rules,
and the audit rule should be per user namespace. So we
should make audit_inode_hash per user namespace too.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/user_namespace.h | 2 ++
kernel/audit.c | 13 +++++--------
kernel/audit.h | 5 ++---
kernel/audit_watch.c | 5 +++--
kernel/auditfilter.c | 22 +++++++++++++---------
kernel/auditsc.c | 2 +-
6 files changed, 26 insertions(+), 23 deletions(-)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 5a778f8..c56e276 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -30,6 +30,8 @@ struct audit_ctrl {
struct task_struct *kauditd_task;
wait_queue_head_t kauditd_wait;
wait_queue_head_t backlog_wait;
+#define AUDIT_INODE_BUCKETS 32
+ struct list_head inode_hash[AUDIT_INODE_BUCKETS];
bool ever_enabled;
};
#endif
diff --git a/kernel/audit.c b/kernel/audit.c
index ca9e046..d254827 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -107,9 +107,6 @@ u32 audit_sig_sid = 0;
*/
static atomic_t audit_lost = ATOMIC_INIT(0);
-/* Hash for inode-based rules */
-struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
-
/* The audit_freelist is a list of pre-allocated audit buffers (if more
* than AUDIT_MAXFREE are in use, the audit buffer is freed instead of
* being placed on the freelist). */
@@ -989,8 +986,6 @@ static struct pernet_operations audit_net_ops = {
/* Initialize audit support at boot time. */
static int __init audit_init(void)
{
- int i;
-
if (init_user_ns.audit.initialized == AUDIT_DISABLED)
return 0;
@@ -1004,9 +999,6 @@ static int __init audit_init(void)
audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
- for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
- INIT_LIST_HEAD(&audit_inode_hash[i]);
-
return 0;
}
__initcall(audit_init);
@@ -1602,6 +1594,8 @@ EXPORT_SYMBOL(audit_log_secctx);
void audit_set_user_ns(struct user_namespace *ns)
{
+ int i;
+
if (init_user_ns.audit.initialized == AUDIT_DISABLED)
return;
@@ -1612,6 +1606,9 @@ void audit_set_user_ns(struct user_namespace *ns)
init_waitqueue_head(&ns->audit.kauditd_wait);
init_waitqueue_head(&ns->audit.backlog_wait);
+ for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
+ INIT_LIST_HEAD(&ns->audit.inode_hash[i]);
+
ns->audit.initialized = AUDIT_INITIALIZED;
}
diff --git a/kernel/audit.h b/kernel/audit.h
index ced93fe..a01c892 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -61,13 +61,12 @@ struct audit_entry {
extern int audit_ever_enabled;
-#define AUDIT_INODE_BUCKETS 32
-extern struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
-
+#ifdef CONFIG_AUDIT
static inline int audit_hash_ino(u32 ino)
{
return (ino & (AUDIT_INODE_BUCKETS-1));
}
+#endif
/* Indicates that audit should log the full pathname. */
#define AUDIT_NAME_FULL -1
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 22831c4..27c7a3b 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -309,7 +309,8 @@ static void audit_update_watch(struct audit_parent *parent,
audit_get_watch(nwatch);
nentry->rule.watch = nwatch;
list_add(&nentry->rule.rlist, &nwatch->rules);
- list_add_rcu(&nentry->list, &audit_inode_hash[h]);
+ list_add_rcu(&nentry->list,
+ &init_user_ns.audit.inode_hash[h]);
list_replace(&oentry->rule.list,
&nentry->rule.list);
}
@@ -441,7 +442,7 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
audit_put_parent(parent);
h = audit_hash_ino((u32)watch->ino);
- *list = &audit_inode_hash[h];
+ *list = &init_user_ns.audit.inode_hash[h];
error:
path_put(&parent_path);
return ret;
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 2674368..573385b 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -885,7 +885,8 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old)
/* Find an existing audit rule.
* Caller must hold audit_filter_mutex to prevent stale rule data. */
-static struct audit_entry *audit_find_rule(struct audit_entry *entry,
+static struct audit_entry *audit_find_rule(struct user_namespace *ns,
+ struct audit_entry *entry,
struct list_head **p)
{
struct audit_entry *e, *found = NULL;
@@ -894,11 +895,11 @@ static struct audit_entry *audit_find_rule(struct audit_entry *entry,
if (entry->rule.inode_f) {
h = audit_hash_ino(entry->rule.inode_f->val);
- *p = list = &audit_inode_hash[h];
+ *p = list = &ns->audit.inode_hash[h];
} else if (entry->rule.watch) {
/* we don't know the inode number, so must walk entire hash */
for (h = 0; h < AUDIT_INODE_BUCKETS; h++) {
- list = &audit_inode_hash[h];
+ list = &ns->audit.inode_hash[h];
list_for_each_entry(e, list, list)
if (!audit_compare_rule(&entry->rule, &e->rule)) {
found = e;
@@ -924,7 +925,8 @@ static u64 prio_low = ~0ULL/2;
static u64 prio_high = ~0ULL/2 - 1;
/* Add rule to given filterlist if not a duplicate. */
-static inline int audit_add_rule(struct audit_entry *entry)
+static inline int audit_add_rule(struct user_namespace *ns,
+ struct audit_entry *entry)
{
struct audit_entry *e;
struct audit_watch *watch = entry->rule.watch;
@@ -941,7 +943,7 @@ static inline int audit_add_rule(struct audit_entry *entry)
#endif
mutex_lock(&audit_filter_mutex);
- e = audit_find_rule(entry, &list);
+ e = audit_find_rule(ns, entry, &list);
if (e) {
mutex_unlock(&audit_filter_mutex);
err = -EEXIST;
@@ -1003,7 +1005,8 @@ error:
}
/* Remove an existing rule from filterlist. */
-static inline int audit_del_rule(struct audit_entry *entry)
+static inline int audit_del_rule(struct user_namespace *ns,
+ struct audit_entry *entry)
{
struct audit_entry *e;
struct audit_watch *watch = entry->rule.watch;
@@ -1020,7 +1023,7 @@ static inline int audit_del_rule(struct audit_entry *entry)
#endif
mutex_lock(&audit_filter_mutex);
- e = audit_find_rule(entry, &list);
+ e = audit_find_rule(ns, entry, &list);
if (!e) {
mutex_unlock(&audit_filter_mutex);
ret = -ENOENT;
@@ -1162,6 +1165,7 @@ int audit_receive_filter(int type, int pid, int seq, void *data,
struct audit_netlink_list *dest;
int err = 0;
struct audit_entry *entry;
+ struct user_namespace *ns = current_user_ns();
switch (type) {
case AUDIT_LIST:
@@ -1201,7 +1205,7 @@ int audit_receive_filter(int type, int pid, int seq, void *data,
if (IS_ERR(entry))
return PTR_ERR(entry);
- err = audit_add_rule(entry);
+ err = audit_add_rule(ns, entry);
audit_log_rule_change(loginuid, sessionid, sid, "add rule",
&entry->rule, !err);
@@ -1217,7 +1221,7 @@ int audit_receive_filter(int type, int pid, int seq, void *data,
if (IS_ERR(entry))
return PTR_ERR(entry);
- err = audit_del_rule(entry);
+ err = audit_del_rule(ns, entry);
audit_log_rule_change(loginuid, sessionid, sid, "remove rule",
&entry->rule, !err);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 290cce6..55bd99e 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -902,7 +902,7 @@ static int audit_filter_inode_name(struct task_struct *tsk,
struct audit_context *ctx) {
int word, bit;
int h = audit_hash_ino((u32)n->ino);
- struct list_head *list = &audit_inode_hash[h];
+ struct list_head *list = &init_user_ns.audit.inode_hash[h];
struct audit_entry *e;
enum audit_state state;
--
1.8.1.4
We should reply the audit filter list request to the proper
user namespace.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 3 ++-
kernel/audit.h | 1 +
kernel/auditfilter.c | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 1ca1714..f723fe2 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -474,8 +474,9 @@ int audit_send_list(void *_dest)
mutex_unlock(&audit_cmd_mutex);
while ((skb = __skb_dequeue(&dest->q)) != NULL)
- netlink_unicast(init_user_ns.audit.sock, skb, pid, 0);
+ netlink_unicast(dest->user_ns->audit.sock, skb, pid, 0);
+ put_user_ns(dest->user_ns);
kfree(dest);
return 0;
diff --git a/kernel/audit.h b/kernel/audit.h
index a509796..7934598 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -85,6 +85,7 @@ extern void audit_panic(const char *message);
struct audit_netlink_list {
int pid;
struct sk_buff_head q;
+ struct user_namespace *user_ns;
};
int audit_send_list(void *);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index cf7fe98..f2afe9b 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1180,6 +1180,7 @@ int audit_receive_filter(int type, int pid, int seq, void *data,
return -ENOMEM;
dest->pid = pid;
skb_queue_head_init(&dest->q);
+ dest->user_ns = get_user_ns(ns);
mutex_lock(&audit_filter_mutex);
if (type == AUDIT_LIST)
--
1.8.1.4
Since update_lsm_rules will update all audit_krule, we still
have to make audit_rules_list global. this patch add a field
user_ns to struct audit_krule to point out which user namespace
this audit rule belongs to.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/audit.h | 1 +
kernel/auditfilter.c | 19 +++++++++++++++----
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index f16db07..885e842 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -59,6 +59,7 @@ struct audit_krule {
struct audit_field *inode_f; /* quick access to an inode field */
struct audit_watch *watch; /* associated watch */
struct audit_tree *tree; /* associated watched tree */
+ struct user_namespace *user_ns; /* belongs to this user namespace */
struct list_head rlist; /* entry in audit_{watch,tree}.rules list */
struct list_head list; /* for AUDIT_LIST* purposes only */
u64 prio;
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index dbf05a9..cf7fe98 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -822,6 +822,7 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old)
new->buflen = old->buflen;
new->inode_f = old->inode_f;
new->field_count = old->field_count;
+ new->user_ns = old->user_ns;
/*
* note that we are OK with not refcounting here; audit_match_tree()
@@ -965,6 +966,7 @@ static inline int audit_add_rule(struct user_namespace *ns,
entry->rule.prio = --prio_low;
}
+ entry->rule.user_ns = get_user_ns(ns);
if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
list_add(&entry->rule.list,
&audit_rules_list[entry->rule.listnr]);
@@ -1026,6 +1028,7 @@ static inline int audit_del_rule(struct user_namespace *ns,
list_del_rcu(&e->list);
list_del(&e->rule.list);
+ put_user_ns(e->rule.user_ns);
call_rcu(&e->rcu, audit_free_rule_rcu);
#ifdef CONFIG_AUDITSYSCALL
@@ -1048,7 +1051,8 @@ out:
/* List rules using struct audit_rule. Exists for backward
* compatibility with userspace. */
-static void audit_list(int pid, int seq, struct sk_buff_head *q)
+static void audit_list(struct user_namespace *ns,
+ int pid, int seq, struct sk_buff_head *q)
{
struct sk_buff *skb;
struct audit_krule *r;
@@ -1060,6 +1064,9 @@ static void audit_list(int pid, int seq, struct sk_buff_head *q)
list_for_each_entry(r, &audit_rules_list[i], list) {
struct audit_rule *rule;
+ if (r->user_ns != ns)
+ continue;
+
rule = audit_krule_to_rule(r);
if (unlikely(!rule))
break;
@@ -1076,7 +1083,8 @@ static void audit_list(int pid, int seq, struct sk_buff_head *q)
}
/* List rules using struct audit_rule_data. */
-static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
+static void audit_list_rules(struct user_namespace *ns,
+ int pid, int seq, struct sk_buff_head *q)
{
struct sk_buff *skb;
struct audit_krule *r;
@@ -1088,6 +1096,9 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
list_for_each_entry(r, &audit_rules_list[i], list) {
struct audit_rule_data *data;
+ if (r->user_ns != ns)
+ continue;
+
data = audit_krule_to_data(r);
if (unlikely(!data))
break;
@@ -1172,9 +1183,9 @@ int audit_receive_filter(int type, int pid, int seq, void *data,
mutex_lock(&audit_filter_mutex);
if (type == AUDIT_LIST)
- audit_list(pid, seq, &dest->q);
+ audit_list(ns, pid, seq, &dest->q);
else
- audit_list_rules(pid, seq, &dest->q);
+ audit_list_rules(ns, pid, seq, &dest->q);
mutex_unlock(&audit_filter_mutex);
tsk = kthread_run(audit_send_list, dest, "audit_send_list");
--
1.8.1.4
This patch just make the audit filter list per user namespace.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/user_namespace.h | 2 ++
kernel/audit.c | 4 ++++
kernel/auditfilter.c | 23 +++++++----------------
kernel/auditsc.c | 12 +++++++++---
kernel/user.c | 19 +++++++++++++++++++
5 files changed, 41 insertions(+), 19 deletions(-)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index c870e28..d1dd5b9 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -6,6 +6,7 @@
#include <linux/sched.h>
#include <linux/err.h>
#include <linux/skbuff.h>
+#include <uapi/linux/audit.h>
#define UID_GID_MAP_MAX_EXTENTS 5
@@ -33,6 +34,7 @@ struct audit_ctrl {
#define AUDIT_INODE_BUCKETS 32
struct list_head inode_hash[AUDIT_INODE_BUCKETS];
struct list_head tree_list;
+ struct list_head filter_list[AUDIT_NR_FILTERS];
bool ever_enabled;
};
#endif
diff --git a/kernel/audit.c b/kernel/audit.c
index a0544b1..1ca1714 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1609,6 +1609,10 @@ void audit_set_user_ns(struct user_namespace *ns)
for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
INIT_LIST_HEAD(&ns->audit.inode_hash[i]);
+ if (ns != &init_user_ns)
+ for (i = 0; i < AUDIT_NR_FILTERS; i++)
+ INIT_LIST_HEAD(&ns->audit.filter_list[i]);
+
INIT_LIST_HEAD(&ns->audit.tree_list);
ns->audit.initialized = AUDIT_INITIALIZED;
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 3c8fb2e..dbf05a9 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -44,18 +44,6 @@
* be written directly provided audit_filter_mutex is held.
*/
-/* Audit filter lists, defined in <linux/audit.h> */
-struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
- LIST_HEAD_INIT(audit_filter_list[0]),
- LIST_HEAD_INIT(audit_filter_list[1]),
- LIST_HEAD_INIT(audit_filter_list[2]),
- LIST_HEAD_INIT(audit_filter_list[3]),
- LIST_HEAD_INIT(audit_filter_list[4]),
- LIST_HEAD_INIT(audit_filter_list[5]),
-#if AUDIT_NR_FILTERS != 6
-#error Fix audit_filter_list initialiser
-#endif
-};
static struct list_head audit_rules_list[AUDIT_NR_FILTERS] = {
LIST_HEAD_INIT(audit_rules_list[0]),
LIST_HEAD_INIT(audit_rules_list[1]),
@@ -908,7 +896,7 @@ static struct audit_entry *audit_find_rule(struct user_namespace *ns,
}
goto out;
} else {
- *p = list = &audit_filter_list[entry->rule.listnr];
+ *p = list = &ns->audit.filter_list[entry->rule.listnr];
}
list_for_each_entry(e, list, list)
@@ -1416,10 +1404,12 @@ int audit_filter_user(void)
{
enum audit_state state = AUDIT_DISABLED;
struct audit_entry *e;
+ struct user_namespace *ns = current_user_ns();
int ret = 1;
rcu_read_lock();
- list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
+ list_for_each_entry_rcu(e, &ns->audit.filter_list[AUDIT_FILTER_USER],
+ list) {
if (audit_filter_user_rules(&e->rule, &state)) {
if (state == AUDIT_DISABLED)
ret = 0;
@@ -1434,13 +1424,14 @@ int audit_filter_user(void)
int audit_filter_type(int type)
{
struct audit_entry *e;
+ struct user_namespace *ns = current_user_ns();
int result = 0;
rcu_read_lock();
- if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
+ if (list_empty(&ns->audit.filter_list[AUDIT_FILTER_TYPE]))
goto unlock_and_return;
- list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
+ list_for_each_entry_rcu(e, &ns->audit.filter_list[AUDIT_FILTER_TYPE],
list) {
int i;
for (i = 0; i < e->rule.field_count; i++) {
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 55bd99e..29c3e05 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -844,9 +844,11 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
{
struct audit_entry *e;
enum audit_state state;
+ struct user_namespace *ns = current_user_ns();
rcu_read_lock();
- list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
+ list_for_each_entry_rcu(e, &ns->audit.filter_list[AUDIT_FILTER_TASK],
+ list) {
if (audit_filter_rules(tsk, &e->rule, NULL, NULL,
&state, true)) {
if (state == AUDIT_RECORD_CONTEXT)
@@ -949,6 +951,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
long return_code)
{
struct audit_context *context = tsk->audit_context;
+ struct user_namespace *ns = task_cred_xxx(tsk, user_ns);
if (!context)
return NULL;
@@ -973,7 +976,8 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
context->return_code = return_code;
if (context->in_syscall && !context->dummy) {
- audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
+ audit_filter_syscall(tsk, context,
+ &ns->audit.filter_list[AUDIT_FILTER_EXIT]);
audit_filter_inodes(tsk, context);
}
@@ -1759,6 +1763,7 @@ void __audit_syscall_entry(int arch, int major,
struct task_struct *tsk = current;
struct audit_context *context = tsk->audit_context;
enum audit_state state;
+ struct user_namespace *ns = current_user_ns();
if (!context)
return;
@@ -1779,7 +1784,8 @@ void __audit_syscall_entry(int arch, int major,
context->dummy = !audit_n_rules;
if (!context->dummy && state == AUDIT_BUILD_CONTEXT) {
context->prio = 0;
- state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]);
+ state = audit_filter_syscall(tsk, context,
+ &ns->audit.filter_list[AUDIT_FILTER_ENTRY]);
}
if (state == AUDIT_DISABLED)
return;
diff --git a/kernel/user.c b/kernel/user.c
index 69b4c3d..637bd39 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -51,6 +51,25 @@ struct user_namespace init_user_ns = {
.owner = GLOBAL_ROOT_UID,
.group = GLOBAL_ROOT_GID,
.proc_inum = PROC_USER_INIT_INO,
+#ifdef CONFIG_AUDIT
+ .audit = {
+ .filter_list[0] =
+ LIST_HEAD_INIT(init_user_ns.audit.filter_list[0]),
+ .filter_list[1] =
+ LIST_HEAD_INIT(init_user_ns.audit.filter_list[1]),
+ .filter_list[2] =
+ LIST_HEAD_INIT(init_user_ns.audit.filter_list[2]),
+ .filter_list[3] =
+ LIST_HEAD_INIT(init_user_ns.audit.filter_list[3]),
+ .filter_list[4] =
+ LIST_HEAD_INIT(init_user_ns.audit.filter_list[4]),
+ .filter_list[5] =
+ LIST_HEAD_INIT(init_user_ns.audit.filter_list[5]),
+#if AUDIT_NR_FILTERS != 6
+#error Fix audit_filter_list of init_user_ns initialiser
+#endif
+ },
+#endif
.may_mount_sysfs = true,
.may_mount_proc = true,
};
--
1.8.1.4
Log the audit message in the user namespace which
current task belongs to.
Signed-off-by: Gao feng <[email protected]>
---
net/netfilter/x_tables.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 8b03028..ba90a1b 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -824,6 +824,7 @@ xt_replace_table(struct xt_table *table,
int *error)
{
struct xt_table_info *private;
+ struct user_namespace *ns = current_user_ns();
int ret;
ret = xt_jumpstack_alloc(newinfo);
@@ -857,16 +858,16 @@ xt_replace_table(struct xt_table *table,
local_bh_enable();
#ifdef CONFIG_AUDIT
- if (audit_enabled) {
+ if (audit_enabled_ns(ns)) {
struct audit_buffer *ab;
- ab = audit_log_start(current->audit_context, GFP_KERNEL,
- AUDIT_NETFILTER_CFG);
+ ab = audit_log_start_ns(ns, current->audit_context,
+ GFP_KERNEL, AUDIT_NETFILTER_CFG);
if (ab) {
audit_log_format(ab, "table=%s family=%u entries=%u",
table->name, table->af,
private->number);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
}
#endif
--
1.8.1.4
This interface audit_log_start_ns and audit_log_end_ns
will be used for logging audit logs in user namespace.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/audit.h | 25 ++++++++++++--
kernel/audit.c | 95 ++++++++++++++++++++++++++++++---------------------
2 files changed, 78 insertions(+), 42 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 33e6584..f16db07 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -398,10 +398,18 @@ extern __printf(4, 5)
void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
const char *fmt, ...);
-extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
+extern struct audit_buffer *
+audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
+
+extern struct audit_buffer *
+audit_log_start_ns(struct user_namespace *ns, struct audit_context *ctx,
+ gfp_t gfp_mask, int type);
+
extern __printf(2, 3)
void audit_log_format(struct audit_buffer *ab, const char *fmt, ...);
extern void audit_log_end(struct audit_buffer *ab);
+extern void audit_log_end_ns(struct user_namespace *ns,
+ struct audit_buffer *ab);
extern int audit_string_contains_control(const char *string,
size_t len);
extern void audit_log_n_hex(struct audit_buffer *ab,
@@ -448,8 +456,16 @@ static inline __printf(4, 5)
void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
const char *fmt, ...)
{ }
-static inline struct audit_buffer *audit_log_start(struct audit_context *ctx,
- gfp_t gfp_mask, int type)
+static inline
+struct audit_buffer *audit_log_start(struct audit_context *ctx,
+ gfp_t gfp_mask, int type)
+{
+ return NULL;
+}
+static inline
+struct audit_buffer *audit_log_start_ns(struct user_namespace *ns,
+ struct audit_context *ctx,
+ gfp_t gfp_mask, int type)
{
return NULL;
}
@@ -458,6 +474,9 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
{ }
static inline void audit_log_end(struct audit_buffer *ab)
{ }
+static inline void audit_log_end_ns(struct user_namespace *ns,
+ struct audit_buffer *ab)
+{ }
static inline void audit_log_n_hex(struct audit_buffer *ab,
const unsigned char *buf, size_t len)
{ }
diff --git a/kernel/audit.c b/kernel/audit.c
index 5ac9acd..594e4e1 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1139,47 +1139,35 @@ static inline void audit_get_stamp(struct audit_context *ctx,
/*
* Wait for auditd to drain the queue a little
*/
-static void wait_for_auditd(unsigned long sleep_time)
+static void wait_for_auditd(struct user_namespace *ns,
+ unsigned long sleep_time)
{
- const struct sk_buff_head *queue = &init_user_ns.audit.queue;
+ const struct sk_buff_head *queue = &ns->audit.queue;
DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&init_user_ns.audit.backlog_wait, &wait);
+ add_wait_queue(&ns->audit.backlog_wait, &wait);
if (audit_backlog_limit &&
skb_queue_len(queue) > audit_backlog_limit)
schedule_timeout(sleep_time);
__set_current_state(TASK_RUNNING);
- remove_wait_queue(&init_user_ns.audit.backlog_wait, &wait);
+ remove_wait_queue(&ns->audit.backlog_wait, &wait);
}
-/**
- * audit_log_start - obtain an audit buffer
- * @ctx: audit_context (may be NULL)
- * @gfp_mask: type of allocation
- * @type: audit message type
- *
- * Returns audit_buffer pointer on success or NULL on error.
- *
- * Obtain an audit buffer. This routine does locking to obtain the
- * audit buffer, but then no locking is required for calls to
- * audit_log_*format. If the task (ctx) is a task that is currently in a
- * syscall, then the syscall is marked as auditable and an audit record
- * will be written at syscall exit. If there is no associated task, then
- * task context (ctx) should be NULL.
- */
-struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
- int type)
+struct audit_buffer *audit_log_start_ns(struct user_namespace *ns,
+ struct audit_context *ctx,
+ gfp_t gfp_mask,
+ int type)
{
struct audit_buffer *ab = NULL;
struct timespec t;
unsigned int uninitialized_var(serial);
int reserve;
unsigned long timeout_start = jiffies;
- struct sk_buff_head *queue = &init_user_ns.audit.queue;
+ struct sk_buff_head *queue = &ns->audit.queue;
- if (init_user_ns.audit.initialized != AUDIT_INITIALIZED)
+ if (ns->audit.initialized != AUDIT_INITIALIZED)
return NULL;
if (unlikely(audit_filter_type(type)))
@@ -1199,7 +1187,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
sleep_time = timeout_start + audit_backlog_wait_time -
jiffies;
if ((long)sleep_time > 0)
- wait_for_auditd(sleep_time);
+ wait_for_auditd(ns, sleep_time);
continue;
}
if (audit_rate_check() && printk_ratelimit())
@@ -1210,7 +1198,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
audit_backlog_limit);
audit_log_lost("backlog limit exceeded");
audit_backlog_wait_time = audit_backlog_wait_overflow;
- wake_up(&init_user_ns.audit.backlog_wait);
+ wake_up(&ns->audit.backlog_wait);
return NULL;
}
@@ -1227,6 +1215,28 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
return ab;
}
+
+/**
+ * audit_log_start - obtain an audit buffer
+ * @ctx: audit_context (may be NULL)
+ * @gfp_mask: type of allocation
+ * @type: audit message type
+ *
+ * Returns audit_buffer pointer on success or NULL on error.
+ *
+ * Obtain an audit buffer. This routine does locking to obtain the
+ * audit buffer, but then no locking is required for calls to
+ * audit_log_*format. If the task (ctx) is a task that is currently in a
+ * syscall, then the syscall is marked as auditable and an audit record
+ * will be written at syscall exit. If there is no associated task, then
+ * task context (ctx) should be NULL.
+ */
+struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
+ int type)
+{
+ return audit_log_start_ns(&init_user_ns, ctx, gfp_mask, type);
+}
+
/**
* audit_expand - expand skb in the audit buffer
* @ab: audit_buffer
@@ -1496,16 +1506,7 @@ void audit_log_link_denied(const char *operation, struct path *link)
audit_log_end(ab);
}
-/**
- * audit_log_end - end one audit record
- * @ab: the audit_buffer
- *
- * The netlink_* functions cannot be called inside an irq context, so
- * the audit buffer is placed on a queue and a tasklet is scheduled to
- * remove them from the queue outside the irq context. May be called in
- * any context.
- */
-void audit_log_end(struct audit_buffer *ab)
+void audit_log_end_ns(struct user_namespace *ns, struct audit_buffer *ab)
{
if (!ab)
return;
@@ -1515,12 +1516,12 @@ void audit_log_end(struct audit_buffer *ab)
struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
nlh->nlmsg_len = ab->skb->len - NLMSG_HDRLEN;
- if (init_user_ns.audit.pid) {
- skb_queue_tail(&init_user_ns.audit.queue,
+ if (ns->audit.pid) {
+ skb_queue_tail(&ns->audit.queue,
ab->skb);
- wake_up_interruptible(&init_user_ns.audit.kauditd_wait);
+ wake_up_interruptible(&ns->audit.kauditd_wait);
} else {
- audit_printk_skb(&init_user_ns, ab->skb);
+ audit_printk_skb(ns, ab->skb);
}
ab->skb = NULL;
}
@@ -1528,6 +1529,20 @@ void audit_log_end(struct audit_buffer *ab)
}
/**
+ * audit_log_end - end one audit record
+ * @ab: the audit_buffer
+ *
+ * The netlink_* functions cannot be called inside an irq context, so
+ * the audit buffer is placed on a queue and a tasklet is scheduled to
+ * remove them from the queue outside the irq context. May be called in
+ * any context.
+ */
+void audit_log_end(struct audit_buffer *ab)
+{
+ audit_log_end_ns(&init_user_ns, ab);
+}
+
+/**
* audit_log - Log an audit record
* @ctx: audit context
* @gfp_mask: type of allocation
@@ -1614,7 +1629,9 @@ void audit_free_user_ns(struct user_namespace *ns)
}
EXPORT_SYMBOL(audit_log_start);
+EXPORT_SYMBOL(audit_log_start_ns);
EXPORT_SYMBOL(audit_log_end);
+EXPORT_SYMBOL(audit_log_end_ns);
EXPORT_SYMBOL(audit_log_format);
EXPORT_SYMBOL(audit_log);
EXPORT_SYMBOL(audit_set_user_ns);
--
1.8.1.4
Because We want to avoid the DoS attack caused by other user
namespace,so don't make audit_rate_limit per user namespace.
And only init user namespace has rights to change it.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kernel/audit.c b/kernel/audit.c
index bf8b59c..8a3ea47 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -308,6 +308,9 @@ static int audit_do_config_change(char *function_name, int *to_change,
static int audit_set_rate_limit(int limit, kuid_t loginuid, u32 sessionid,
u32 sid)
{
+ if (current_user_ns() != &init_user_ns)
+ return -EPERM;
+
return audit_do_config_change("audit_rate_limit", &audit_rate_limit,
limit, loginuid, sessionid, sid);
}
--
1.8.1.4
kauditd_task is added to the wait queue kaudit_wait when
there is no audit message being generated in user namespace,
so the kaudit_wait should be per user namespace too.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/user_namespace.h | 1 +
kernel/audit.c | 8 ++++----
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index c7b5bf7..7c2c65c 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -28,6 +28,7 @@ struct audit_ctrl {
struct sk_buff_head queue;
struct sk_buff_head hold_queue;
struct task_struct *kauditd_task;
+ wait_queue_head_t kauditd_wait;
bool ever_enabled;
};
#endif
diff --git a/kernel/audit.c b/kernel/audit.c
index f5e106f..ad03f4f 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -117,7 +117,6 @@ static DEFINE_SPINLOCK(audit_freelist_lock);
static int audit_freelist_count;
static LIST_HEAD(audit_freelist);
-static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
/* Serialize requests from userspace. */
@@ -454,7 +453,7 @@ static int kauditd_thread(void *dummy)
} else {
DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&kauditd_wait, &wait);
+ add_wait_queue(&ns->audit.kauditd_wait, &wait);
if (!skb_queue_len(queue)) {
try_to_freeze();
@@ -462,7 +461,7 @@ static int kauditd_thread(void *dummy)
}
__set_current_state(TASK_RUNNING);
- remove_wait_queue(&kauditd_wait, &wait);
+ remove_wait_queue(&ns->audit.kauditd_wait, &wait);
}
}
return 0;
@@ -1528,7 +1527,7 @@ void audit_log_end(struct audit_buffer *ab)
if (init_user_ns.audit.pid) {
skb_queue_tail(&init_user_ns.audit.queue,
ab->skb);
- wake_up_interruptible(&kauditd_wait);
+ wake_up_interruptible(&init_user_ns.audit.kauditd_wait);
} else {
audit_printk_skb(&init_user_ns, ab->skb);
}
@@ -1599,6 +1598,7 @@ void audit_set_user_ns(struct user_namespace *ns)
skb_queue_head_init(&ns->audit.hold_queue);
ns->audit.enabled = audit_default;
ns->audit.ever_enabled |= !!audit_default;
+ init_waitqueue_head(&ns->audit.kauditd_wait);
ns->audit.initialized = AUDIT_INITIALIZED;
}
--
1.8.1.4
we can log audit message in the user namespace which
netfilter xt_AUDIT rules belongs to.
Signed-off-by: Gao feng <[email protected]>
---
net/netfilter/xt_AUDIT.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index 3228d7f..b1ffba2 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -122,12 +122,14 @@ static unsigned int
audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_audit_info *info = par->targinfo;
+ struct net *net = dev_net(par->in ? par->in : par->out);
+ struct user_namespace *ns = net->user_ns;
struct audit_buffer *ab;
- if (audit_enabled == 0)
+ if (audit_enabled_ns(ns) == 0)
goto errout;
- ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
+ ab = audit_log_start_ns(ns, NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
if (ab == NULL)
goto errout;
@@ -172,7 +174,7 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
audit_log_secctx(ab, skb->secmark);
#endif
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
errout:
return XT_CONTINUE;
--
1.8.1.4
As we know, netlink sockets can communicate with each other
only when they in the same net namespace. this works
well until we try to add namespace support for other
subsystems which use netlink.
Don't like ipv4,route table,it is not suited to make this
subsytems belongs to net namespace, Such as audit and crypto
subsystems,they are more suitable to user namespace.
So we must have the ability to make the netlink sockets in
same user namespace can communicate with each other.
This patch adds a new function pointer "compare" for
netlink_table, we can decide if the netlink sockets can
communicate with each other through this netlink_table
self-defined compare function.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/netlink.h | 1 +
net/netlink/af_netlink.c | 26 ++++++++++++++++++++------
net/netlink/af_netlink.h | 1 +
3 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 6358da5..f78b430 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -46,6 +46,7 @@ struct netlink_kernel_cfg {
void (*input)(struct sk_buff *skb);
struct mutex *cb_mutex;
void (*bind)(int group);
+ bool (*compare)(struct net *net, struct sock *sk);
};
extern struct sock *__netlink_kernel_create(struct net *net, int unit,
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 12ac6b4..41cc3c8 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -854,16 +854,23 @@ netlink_unlock_table(void)
wake_up(&nl_table_wait);
}
+static bool netlink_compare(struct net *net, struct sock *sk)
+{
+ return net_eq(sock_net(sk), net);
+}
+
static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid)
{
- struct nl_portid_hash *hash = &nl_table[protocol].hash;
+ struct netlink_table *table = &nl_table[protocol];
+ struct nl_portid_hash *hash = &table->hash;
struct hlist_head *head;
struct sock *sk;
read_lock(&nl_table_lock);
head = nl_portid_hashfn(hash, portid);
sk_for_each(sk, head) {
- if (net_eq(sock_net(sk), net) && (nlk_sk(sk)->portid == portid)) {
+ if (table->compare(net, sk) &&
+ (nlk_sk(sk)->portid == portid)) {
sock_hold(sk);
goto found;
}
@@ -976,7 +983,8 @@ netlink_update_listeners(struct sock *sk)
static int netlink_insert(struct sock *sk, struct net *net, u32 portid)
{
- struct nl_portid_hash *hash = &nl_table[sk->sk_protocol].hash;
+ struct netlink_table *table = &nl_table[sk->sk_protocol];
+ struct nl_portid_hash *hash = &table->hash;
struct hlist_head *head;
int err = -EADDRINUSE;
struct sock *osk;
@@ -986,7 +994,8 @@ static int netlink_insert(struct sock *sk, struct net *net, u32 portid)
head = nl_portid_hashfn(hash, portid);
len = 0;
sk_for_each(osk, head) {
- if (net_eq(sock_net(osk), net) && (nlk_sk(osk)->portid == portid))
+ if (table->compare(net, osk) &&
+ (nlk_sk(osk)->portid == portid))
break;
len++;
}
@@ -1161,6 +1170,7 @@ static int netlink_release(struct socket *sock)
kfree_rcu(old, rcu);
nl_table[sk->sk_protocol].module = NULL;
nl_table[sk->sk_protocol].bind = NULL;
+ nl_table[sk->sk_protocol].compare = NULL;
nl_table[sk->sk_protocol].flags = 0;
nl_table[sk->sk_protocol].registered = 0;
}
@@ -1183,7 +1193,8 @@ static int netlink_autobind(struct socket *sock)
{
struct sock *sk = sock->sk;
struct net *net = sock_net(sk);
- struct nl_portid_hash *hash = &nl_table[sk->sk_protocol].hash;
+ struct netlink_table *table = &nl_table[sk->sk_protocol];
+ struct nl_portid_hash *hash = &table->hash;
struct hlist_head *head;
struct sock *osk;
s32 portid = task_tgid_vnr(current);
@@ -1195,7 +1206,7 @@ retry:
netlink_table_grab();
head = nl_portid_hashfn(hash, portid);
sk_for_each(osk, head) {
- if (!net_eq(sock_net(osk), net))
+ if (!table->compare(net, osk))
continue;
if (nlk_sk(osk)->portid == portid) {
/* Bind collision, search negative portid values. */
@@ -2282,9 +2293,12 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module,
rcu_assign_pointer(nl_table[unit].listeners, listeners);
nl_table[unit].cb_mutex = cb_mutex;
nl_table[unit].module = module;
+ nl_table[unit].compare = netlink_compare;
if (cfg) {
nl_table[unit].bind = cfg->bind;
nl_table[unit].flags = cfg->flags;
+ if (cfg->compare)
+ nl_table[unit].compare = cfg->compare;
}
nl_table[unit].registered = 1;
} else {
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
index ed85222..eaa88d1 100644
--- a/net/netlink/af_netlink.h
+++ b/net/netlink/af_netlink.h
@@ -73,6 +73,7 @@ struct netlink_table {
struct mutex *cb_mutex;
struct module *module;
void (*bind)(int group);
+ bool (*compare)(struct net *net, struct sock *sock);
int registered;
};
--
1.8.1.4
We should user current_user_ns instead of init_user_ns.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index d39296b..f5e106f 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -251,13 +251,14 @@ static int audit_log_config_change(char *function_name, int new, int old,
int allow_changes)
{
struct audit_buffer *ab;
+ struct user_namespace *ns = current_user_ns();
int rc = 0;
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (unlikely(!ab))
return rc;
audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new,
- old, from_kuid(&init_user_ns, loginuid), sessionid);
+ old, from_kuid(ns, loginuid), sessionid);
if (sid) {
char *ctx = NULL;
u32 len;
--
1.8.1.4
Remove it.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 62f244b..5ac9acd 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1154,13 +1154,6 @@ static void wait_for_auditd(unsigned long sleep_time)
remove_wait_queue(&init_user_ns.audit.backlog_wait, &wait);
}
-/* Obtain an audit buffer. This routine does locking to obtain the
- * audit buffer, but then no locking is required for calls to
- * audit_log_*format. If the tsk is a task that is currently in a
- * syscall, then the syscall is marked as auditable and an audit record
- * will be written at syscall exit. If there is no associated task, tsk
- * should be NULL. */
-
/**
* audit_log_start - obtain an audit buffer
* @ctx: audit_context (may be NULL)
--
1.8.1.4
Tasks are added to audit_backlog_wait when the
audit_skb_queue of user namespace is full, so
audit_backlog_wait should be per user namespace too.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/user_namespace.h | 1 +
kernel/audit.c | 11 +++++------
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 7c2c65c..5a778f8 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -29,6 +29,7 @@ struct audit_ctrl {
struct sk_buff_head hold_queue;
struct task_struct *kauditd_task;
wait_queue_head_t kauditd_wait;
+ wait_queue_head_t backlog_wait;
bool ever_enabled;
};
#endif
diff --git a/kernel/audit.c b/kernel/audit.c
index ad03f4f..62f244b 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -117,8 +117,6 @@ static DEFINE_SPINLOCK(audit_freelist_lock);
static int audit_freelist_count;
static LIST_HEAD(audit_freelist);
-static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
-
/* Serialize requests from userspace. */
DEFINE_MUTEX(audit_cmd_mutex);
@@ -444,7 +442,7 @@ static int kauditd_thread(void *dummy)
}
skb = skb_dequeue(queue);
- wake_up(&audit_backlog_wait);
+ wake_up(&ns->audit.backlog_wait);
if (skb) {
if (ns->audit.pid)
kauditd_send_skb(ns, skb);
@@ -1146,14 +1144,14 @@ static void wait_for_auditd(unsigned long sleep_time)
const struct sk_buff_head *queue = &init_user_ns.audit.queue;
DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&audit_backlog_wait, &wait);
+ add_wait_queue(&init_user_ns.audit.backlog_wait, &wait);
if (audit_backlog_limit &&
skb_queue_len(queue) > audit_backlog_limit)
schedule_timeout(sleep_time);
__set_current_state(TASK_RUNNING);
- remove_wait_queue(&audit_backlog_wait, &wait);
+ remove_wait_queue(&init_user_ns.audit.backlog_wait, &wait);
}
/* Obtain an audit buffer. This routine does locking to obtain the
@@ -1219,7 +1217,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
audit_backlog_limit);
audit_log_lost("backlog limit exceeded");
audit_backlog_wait_time = audit_backlog_wait_overflow;
- wake_up(&audit_backlog_wait);
+ wake_up(&init_user_ns.audit.backlog_wait);
return NULL;
}
@@ -1599,6 +1597,7 @@ void audit_set_user_ns(struct user_namespace *ns)
ns->audit.enabled = audit_default;
ns->audit.ever_enabled |= !!audit_default;
init_waitqueue_head(&ns->audit.kauditd_wait);
+ init_waitqueue_head(&ns->audit.backlog_wait);
ns->audit.initialized = AUDIT_INITIALIZED;
}
--
1.8.1.4
The audit log that generated in user namespace should be
received by the auditd running in this user namespace.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 594e4e1..c8329ce 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -604,25 +604,26 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
return err;
}
-static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
+static int audit_log_common_recv_msg(struct user_namespace *ns,
+ struct audit_buffer **ab, u16 msg_type,
kuid_t auid, u32 ses, u32 sid)
{
int rc = 0;
char *ctx = NULL;
u32 len;
- if (!init_user_ns.audit.enabled) {
+ if (!ns->audit.enabled) {
*ab = NULL;
return rc;
}
- *ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
+ *ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, msg_type);
if (unlikely(!*ab))
return rc;
audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u",
task_tgid_vnr(current),
- from_kuid(&init_user_ns, current_uid()),
- from_kuid(&init_user_ns, auid), ses);
+ from_kuid(ns, current_uid()),
+ from_kuid(ns, auid), ses);
if (sid) {
rc = security_secid_to_secctx(sid, &ctx, &len);
if (rc)
@@ -739,7 +740,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (err)
break;
}
- audit_log_common_recv_msg(&ab, msg_type,
+ audit_log_common_recv_msg(ns, &ab, msg_type,
loginuid, sessionid, sid);
if (msg_type != AUDIT_USER_TTY)
@@ -756,7 +757,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
audit_log_n_untrustedstring(ab, data, size);
}
audit_set_pid(ab, NETLINK_CB(skb).portid);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
}
break;
case AUDIT_ADD:
@@ -764,12 +765,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (nlmsg_len(nlh) < sizeof(struct audit_rule))
return -EINVAL;
if (ns->audit.enabled == AUDIT_LOCKED) {
- audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
+ audit_log_common_recv_msg(ns, &ab, AUDIT_CONFIG_CHANGE,
loginuid, sessionid, sid);
audit_log_format(ab, " audit_enabled=%d res=0",
ns->audit.enabled);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
return -EPERM;
}
/* fallthrough */
@@ -783,12 +784,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
return -EINVAL;
if (ns->audit.enabled == AUDIT_LOCKED) {
- audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
+ audit_log_common_recv_msg(ns, &ab, AUDIT_CONFIG_CHANGE,
loginuid, sessionid, sid);
audit_log_format(ab, " audit_enabled=%d res=0",
ns->audit.enabled);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
return -EPERM;
}
/* fallthrough */
@@ -800,11 +801,11 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_TRIM:
audit_trim_trees();
- audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
+ audit_log_common_recv_msg(ns, &ab, AUDIT_CONFIG_CHANGE,
loginuid, sessionid, sid);
audit_log_format(ab, " op=trim res=1");
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
break;
case AUDIT_MAKE_EQUIV: {
void *bufp = data;
@@ -832,7 +833,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
/* OK, here comes... */
err = audit_tag_tree(old, new);
- audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
+ audit_log_common_recv_msg(ns, &ab, AUDIT_CONFIG_CHANGE,
loginuid, sessionid, sid);
audit_log_format(ab, " op=make_equiv old=");
@@ -840,7 +841,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
audit_log_format(ab, " new=");
audit_log_untrustedstring(ab, new);
audit_log_format(ab, " res=%d", !err);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
kfree(old);
kfree(new);
break;
--
1.8.1.4
Setting audit_failure to AUDIT_FAIL_PANIC may
cause system panic.
We should disallow uninit user namesapce to change it.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kernel/audit.c b/kernel/audit.c
index 8a3ea47..18cf5ce 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -345,6 +345,9 @@ static int audit_set_failure(int state, kuid_t loginuid, u32 sessionid, u32 sid)
&& state != AUDIT_FAIL_PANIC)
return -EINVAL;
+ if (current_user_ns() != &init_user_ns)
+ return -EPERM;
+
return audit_do_config_change("audit_failure", &audit_failure, state,
loginuid, sessionid, sid);
}
--
1.8.1.4
This patch makes audit_enabled per user namespace,
Right now,use audit_enabled of init user namespace to
decide if audit is enabled no matter which user namespace
we belong to.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/audit.h | 4 +++-
include/linux/user_namespace.h | 1 +
kernel/audit.c | 37 ++++++++++++++++++-------------------
3 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 684599b..33e6584 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -441,7 +441,8 @@ extern int audit_filter_type(int type);
extern int audit_receive_filter(int type, int pid, int seq,
void *data, size_t datasz, kuid_t loginuid,
u32 sessionid, u32 sid);
-extern int audit_enabled;
+#define audit_enabled (init_user_ns.audit.enabled)
+#define audit_enabled_ns (ns->audit.enabled)
#else /* CONFIG_AUDIT */
static inline __printf(4, 5)
void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
@@ -487,6 +488,7 @@ static inline void audit_set_user_ns(struct user_namespace *ns)
static inline void audit_free_user_ns(struct user_namespace *ns)
{ }
#define audit_enabled 0
+#define audit_enabled_ns(ns) 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 769a12b..3b2ed90 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -21,6 +21,7 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */
#ifdef CONFIG_AUDIT
struct audit_ctrl {
struct sock *sock;
+ int enabled;
int pid;
int portid;
struct sk_buff_head queue;
diff --git a/kernel/audit.c b/kernel/audit.c
index b946b29..4595a9e 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -76,11 +76,8 @@ static int audit_initialized;
#define AUDIT_OFF 0
#define AUDIT_ON 1
#define AUDIT_LOCKED 2
-int audit_enabled;
int audit_ever_enabled;
-EXPORT_SYMBOL_GPL(audit_enabled);
-
/* Default state when kernel boots without any parameters. */
static int audit_default;
@@ -285,14 +282,15 @@ static int audit_do_config_change(char *function_name, int *to_change,
u32 sid)
{
int allow_changes, rc = 0, old = *to_change;
+ struct user_namespace *ns = current_user_ns();
/* check if we are locked */
- if (audit_enabled == AUDIT_LOCKED)
+ if (ns->audit.enabled == AUDIT_LOCKED)
allow_changes = 0;
else
allow_changes = 1;
- if (audit_enabled != AUDIT_OFF) {
+ if (ns->audit.enabled != AUDIT_OFF) {
rc = audit_log_config_change(function_name, new, old, loginuid,
sessionid, sid, allow_changes);
if (rc)
@@ -322,14 +320,15 @@ static int audit_set_backlog_limit(int limit, kuid_t loginuid, u32 sessionid,
limit, loginuid, sessionid, sid);
}
-static int audit_set_enabled(int state, kuid_t loginuid, u32 sessionid, u32 sid)
+static int audit_set_enabled(struct user_namespace *ns, int state,
+ kuid_t loginuid, u32 sessionid, u32 sid)
{
int rc;
if (state < AUDIT_OFF || state > AUDIT_LOCKED)
return -EINVAL;
- rc = audit_do_config_change("audit_enabled", &audit_enabled, state,
- loginuid, sessionid, sid);
+ rc = audit_do_config_change("audit_enabled", &ns->audit.enabled,
+ state, loginuid, sessionid, sid);
if (!rc)
audit_ever_enabled |= !!state;
@@ -609,7 +608,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
char *ctx = NULL;
u32 len;
- if (!audit_enabled) {
+ if (!init_user_ns.audit.enabled) {
*ab = NULL;
return rc;
}
@@ -674,7 +673,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
switch (msg_type) {
case AUDIT_GET:
- status_set.enabled = audit_enabled;
+ status_set.enabled = ns->audit.enabled;
status_set.failure = audit_failure;
status_set.pid = ns->audit.pid;
status_set.rate_limit = audit_rate_limit;
@@ -690,7 +689,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
return -EINVAL;
status_get = (struct audit_status *)data;
if (status_get->mask & AUDIT_STATUS_ENABLED) {
- err = audit_set_enabled(status_get->enabled,
+ err = audit_set_enabled(ns, status_get->enabled,
loginuid, sessionid, sid);
if (err < 0)
return err;
@@ -704,7 +703,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (status_get->mask & AUDIT_STATUS_PID) {
int new_pid = status_get->pid;
- if (audit_enabled != AUDIT_OFF)
+ if (ns->audit.enabled != AUDIT_OFF)
audit_log_config_change("audit_pid", new_pid,
ns->audit.pid, loginuid,
sessionid, sid, 1);
@@ -725,7 +724,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_USER:
case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
- if (!audit_enabled && msg_type != AUDIT_USER_AVC)
+ if (!ns->audit.enabled && msg_type != AUDIT_USER_AVC)
return 0;
err = audit_filter_user();
@@ -761,12 +760,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_DEL:
if (nlmsg_len(nlh) < sizeof(struct audit_rule))
return -EINVAL;
- if (audit_enabled == AUDIT_LOCKED) {
+ if (ns->audit.enabled == AUDIT_LOCKED) {
audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
loginuid, sessionid, sid);
audit_log_format(ab, " audit_enabled=%d res=0",
- audit_enabled);
+ ns->audit.enabled);
audit_log_end(ab);
return -EPERM;
}
@@ -780,12 +779,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_DEL_RULE:
if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
return -EINVAL;
- if (audit_enabled == AUDIT_LOCKED) {
+ if (ns->audit.enabled == AUDIT_LOCKED) {
audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
loginuid, sessionid, sid);
audit_log_format(ab, " audit_enabled=%d res=0",
- audit_enabled);
+ ns->audit.enabled);
audit_log_end(ab);
return -EPERM;
}
@@ -995,7 +994,6 @@ static int __init audit_init(void)
audit_set_user_ns(&init_user_ns);
audit_initialized = AUDIT_INITIALIZED;
- audit_enabled = audit_default;
audit_ever_enabled |= !!audit_default;
audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
@@ -1017,7 +1015,7 @@ static int __init audit_enable(char *str)
printk(KERN_INFO "audit: %s", audit_default ? "enabled" : "disabled");
if (audit_initialized == AUDIT_INITIALIZED) {
- audit_enabled = audit_default;
+ init_user_ns.audit.enabled = audit_default;
audit_ever_enabled |= !!audit_default;
} else if (audit_initialized == AUDIT_UNINITIALIZED) {
printk(" (after initialization)");
@@ -1595,6 +1593,7 @@ void audit_set_user_ns(struct user_namespace *ns)
skb_queue_head_init(&ns->audit.queue);
skb_queue_head_init(&ns->audit.hold_queue);
+ ns->audit.enabled = audit_default;
}
void audit_free_user_ns(struct user_namespace *ns)
--
1.8.1.4
This patch allow to log audit config change in
uninit user namespace.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index c8329ce..cac4b21 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -251,7 +251,7 @@ static int audit_log_config_change(char *function_name, int new, int old,
struct user_namespace *ns = current_user_ns();
int rc = 0;
- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ ab = audit_log_start_ns(ns, NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (unlikely(!ab))
return rc;
audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new,
@@ -270,7 +270,7 @@ static int audit_log_config_change(char *function_name, int new, int old,
}
}
audit_log_format(ab, " res=%d", allow_changes);
- audit_log_end(ab);
+ audit_log_end_ns(ns, ab);
return rc;
}
--
1.8.1.4
After this patch, ervery user namespace has one
audit_skb_queue. Since we havn't finish the preparations,
only allow user to operate the skb queue of init user
namespace.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/audit.h | 4 ++++
include/linux/user_namespace.h | 2 ++
kernel/audit.c | 35 ++++++++++++++++++++++++++---------
kernel/user_namespace.c | 1 +
4 files changed, 33 insertions(+), 9 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 690d7d8..78f51ae 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -429,6 +429,7 @@ static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid)
{ }
#endif
+extern void audit_set_user_ns(struct user_namespace *ns);
extern void audit_free_user_ns(struct user_namespace *ns);
extern int audit_update_lsm_rules(void);
@@ -479,6 +480,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_set_user_ns(struct user_namespace *ns)
+{ }
+
static inline void audit_free_user_ns(struct user_namespace *ns)
{ }
#define audit_enabled 0
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 8797421..e322f20 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -5,6 +5,7 @@
#include <linux/nsproxy.h>
#include <linux/sched.h>
#include <linux/err.h>
+#include <linux/skbuff.h>
#define UID_GID_MAP_MAX_EXTENTS 5
@@ -20,6 +21,7 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */
#ifdef CONFIG_AUDIT
struct audit_ctrl {
struct sock *sock;
+ struct sk_buff_head queue;
};
#endif
diff --git a/kernel/audit.c b/kernel/audit.c
index 3ae8793..2a727af 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -129,7 +129,6 @@ static DEFINE_SPINLOCK(audit_freelist_lock);
static int audit_freelist_count;
static LIST_HEAD(audit_freelist);
-static struct sk_buff_head audit_skb_queue;
/* queue of skbs to send to auditd when/if it comes back */
static struct sk_buff_head audit_skb_hold_queue;
static struct task_struct *kauditd_task;
@@ -419,6 +418,7 @@ static void kauditd_send_skb(struct sk_buff *skb)
static int kauditd_thread(void *dummy)
{
struct sk_buff *skb;
+ struct sk_buff_head *queue = &init_user_ns.audit.queue;
set_freezable();
while (!kthread_should_stop()) {
@@ -445,7 +445,7 @@ static int kauditd_thread(void *dummy)
}
}
- skb = skb_dequeue(&audit_skb_queue);
+ skb = skb_dequeue(queue);
wake_up(&audit_backlog_wait);
if (skb) {
if (audit_pid)
@@ -457,7 +457,7 @@ static int kauditd_thread(void *dummy)
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&kauditd_wait, &wait);
- if (!skb_queue_len(&audit_skb_queue)) {
+ if (!skb_queue_len(queue)) {
try_to_freeze();
schedule();
}
@@ -653,11 +653,13 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
struct audit_sig_info *sig_data;
char *ctx = NULL;
u32 len;
+ struct user_namespace *ns;
err = audit_netlink_ok(skb, msg_type);
if (err)
return err;
+ ns = current_user_ns();
/* As soon as there's any sign of userspace auditd,
* start kauditd to talk to it */
if (!kauditd_task) {
@@ -682,7 +684,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
status_set.rate_limit = audit_rate_limit;
status_set.backlog_limit = audit_backlog_limit;
status_set.lost = atomic_read(&audit_lost);
- status_set.backlog = skb_queue_len(&audit_skb_queue);
+ status_set.backlog =
+ skb_queue_len(&ns->audit.queue);
audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0,
&status_set, sizeof(status_set));
break;
@@ -994,7 +997,7 @@ static int __init audit_init(void)
if (register_pernet_subsys(&audit_net_ops) < 0)
return -1;
- skb_queue_head_init(&audit_skb_queue);
+ audit_set_user_ns(&init_user_ns);
skb_queue_head_init(&audit_skb_hold_queue);
audit_initialized = AUDIT_INITIALIZED;
audit_enabled = audit_default;
@@ -1144,12 +1147,13 @@ static inline void audit_get_stamp(struct audit_context *ctx,
*/
static void wait_for_auditd(unsigned long sleep_time)
{
+ const struct sk_buff_head *queue = &init_user_ns.audit.queue;
DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&audit_backlog_wait, &wait);
if (audit_backlog_limit &&
- skb_queue_len(&audit_skb_queue) > audit_backlog_limit)
+ skb_queue_len(queue) > audit_backlog_limit)
schedule_timeout(sleep_time);
__set_current_state(TASK_RUNNING);
@@ -1186,6 +1190,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
unsigned int uninitialized_var(serial);
int reserve;
unsigned long timeout_start = jiffies;
+ struct sk_buff_head *queue = &init_user_ns.audit.queue;
if (audit_initialized != AUDIT_INITIALIZED)
return NULL;
@@ -1200,7 +1205,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
entries over the normal backlog limit */
while (audit_backlog_limit
- && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) {
+ && skb_queue_len(queue) > audit_backlog_limit + reserve) {
if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time) {
unsigned long sleep_time;
@@ -1214,7 +1219,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
printk(KERN_WARNING
"audit: audit_backlog=%d > "
"audit_backlog_limit=%d\n",
- skb_queue_len(&audit_skb_queue),
+ skb_queue_len(queue),
audit_backlog_limit);
audit_log_lost("backlog limit exceeded");
audit_backlog_wait_time = audit_backlog_wait_overflow;
@@ -1524,7 +1529,8 @@ void audit_log_end(struct audit_buffer *ab)
nlh->nlmsg_len = ab->skb->len - NLMSG_HDRLEN;
if (audit_pid) {
- skb_queue_tail(&audit_skb_queue, ab->skb);
+ skb_queue_tail(&init_user_ns.audit.queue,
+ ab->skb);
wake_up_interruptible(&kauditd_wait);
} else {
audit_printk_skb(ab->skb);
@@ -1587,6 +1593,14 @@ void audit_log_secctx(struct audit_buffer *ab, u32 secid)
EXPORT_SYMBOL(audit_log_secctx);
#endif
+void audit_set_user_ns(struct user_namespace *ns)
+{
+ if (audit_initialized == AUDIT_DISABLED)
+ return;
+
+ skb_queue_head_init(&ns->audit.queue);
+}
+
void audit_free_user_ns(struct user_namespace *ns)
{
if (audit_initialized == AUDIT_DISABLED)
@@ -1597,10 +1611,13 @@ void audit_free_user_ns(struct user_namespace *ns)
netlink_kernel_release(ns->audit.sock);
net_drop_ns(net);
}
+
+ skb_queue_purge(&ns->audit.queue);
}
EXPORT_SYMBOL(audit_log_start);
EXPORT_SYMBOL(audit_log_end);
EXPORT_SYMBOL(audit_log_format);
EXPORT_SYMBOL(audit_log);
+EXPORT_SYMBOL(audit_set_user_ns);
EXPORT_SYMBOL(audit_free_user_ns);
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 99de920..047921a 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -100,6 +100,7 @@ int create_user_ns(struct cred *new)
update_mnt_policy(ns);
+ audit_set_user_ns(ns);
return 0;
}
--
1.8.1.4
audit_initialized is used to identify if the audit
related resources have been initialized. it should
be per user namespace too.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/user_namespace.h | 1 +
kernel/audit.c | 21 +++++++++++----------
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index d5a22b2..c7b5bf7 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -21,6 +21,7 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */
#ifdef CONFIG_AUDIT
struct audit_ctrl {
struct sock *sock;
+ int initialized;
int enabled;
int pid;
int portid;
diff --git a/kernel/audit.c b/kernel/audit.c
index 9ea5b27..bf8b59c 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -66,12 +66,12 @@
#include "audit.h"
-/* No auditing will take place until audit_initialized == AUDIT_INITIALIZED.
+/* No auditing will take place until user namespace's
+ * audit.initialized == AUDIT_INITIALIZED.
* (Initialization happens after skb_init is called.) */
#define AUDIT_DISABLED -1
#define AUDIT_UNINITIALIZED 0
#define AUDIT_INITIALIZED 1
-static int audit_initialized;
#define AUDIT_OFF 0
#define AUDIT_ON 1
@@ -982,7 +982,7 @@ static int __init audit_init(void)
{
int i;
- if (audit_initialized == AUDIT_DISABLED)
+ if (init_user_ns.audit.initialized == AUDIT_DISABLED)
return 0;
printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
@@ -992,7 +992,6 @@ static int __init audit_init(void)
return -1;
audit_set_user_ns(&init_user_ns);
- audit_initialized = AUDIT_INITIALIZED;
audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
@@ -1008,14 +1007,14 @@ static int __init audit_enable(char *str)
{
audit_default = !!simple_strtol(str, NULL, 0);
if (!audit_default)
- audit_initialized = AUDIT_DISABLED;
+ init_user_ns.audit.initialized = AUDIT_DISABLED;
printk(KERN_INFO "audit: %s", audit_default ? "enabled" : "disabled");
- if (audit_initialized == AUDIT_INITIALIZED) {
+ if (init_user_ns.audit.initialized == AUDIT_INITIALIZED) {
init_user_ns.audit.enabled = audit_default;
init_user_ns.audit.ever_enabled |= !!audit_default;
- } else if (audit_initialized == AUDIT_UNINITIALIZED) {
+ } else if (init_user_ns.audit.initialized == AUDIT_UNINITIALIZED) {
printk(" (after initialization)");
} else {
printk(" (until reboot)");
@@ -1183,7 +1182,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
unsigned long timeout_start = jiffies;
struct sk_buff_head *queue = &init_user_ns.audit.queue;
- if (audit_initialized != AUDIT_INITIALIZED)
+ if (init_user_ns.audit.initialized != AUDIT_INITIALIZED)
return NULL;
if (unlikely(audit_filter_type(type)))
@@ -1586,18 +1585,20 @@ EXPORT_SYMBOL(audit_log_secctx);
void audit_set_user_ns(struct user_namespace *ns)
{
- if (audit_initialized == AUDIT_DISABLED)
+ if (init_user_ns.audit.initialized == AUDIT_DISABLED)
return;
skb_queue_head_init(&ns->audit.queue);
skb_queue_head_init(&ns->audit.hold_queue);
ns->audit.enabled = audit_default;
ns->audit.ever_enabled |= !!audit_default;
+
+ ns->audit.initialized = AUDIT_INITIALIZED;
}
void audit_free_user_ns(struct user_namespace *ns)
{
- if (audit_initialized == AUDIT_DISABLED)
+ if (init_user_ns.audit.initialized == AUDIT_DISABLED)
return;
if (ns->audit.sock) {
--
1.8.1.4
After this patch, audit_nlk_port is per user namespace.
Just like prev patch does,use audit_nlk_portid of init
user namespace in kauditd_send_skb.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/user_namespace.h | 1 +
kernel/audit.c | 11 ++---------
2 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index a6c6174..769a12b 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -22,6 +22,7 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */
struct audit_ctrl {
struct sock *sock;
int pid;
+ int portid;
struct sk_buff_head queue;
struct sk_buff_head hold_queue;
struct task_struct *kauditd_task;
diff --git a/kernel/audit.c b/kernel/audit.c
index 2ce7a21..b946b29 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -87,13 +87,6 @@ static int audit_default;
/* If auditing cannot proceed, audit_failure selects what happens. */
static int audit_failure = AUDIT_FAIL_PRINTK;
-/*
- * If audit records are to be written to the netlink socket, audit_pid
- * contains the pid of the auditd process and audit_nlk_portid contains
- * the portid to use to send netlink messages to that process.
- */
-static int audit_nlk_portid;
-
/* If audit_rate_limit is non-zero, limit the rate of sending audit records
* to that number per second. This prevents DoS attacks, but results in
* audit records being dropped. */
@@ -400,7 +393,7 @@ static void kauditd_send_skb(struct sk_buff *skb)
/* take a reference in case we can't send it and we want to hold it */
skb_get(skb);
err = netlink_unicast(init_user_ns.audit.sock, skb,
- audit_nlk_portid, 0);
+ init_user_ns.audit.portid, 0);
if (err < 0) {
BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */
printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n",
@@ -717,7 +710,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
sessionid, sid, 1);
ns->audit.pid = new_pid;
- audit_nlk_portid = NETLINK_CB(skb).portid;
+ ns->audit.portid = NETLINK_CB(skb).portid;
}
if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) {
err = audit_set_rate_limit(status_get->rate_limit,
--
1.8.1.4
It's better to define audit_ever_enabled as bool
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 4595a9e..1138ff5 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -76,7 +76,7 @@ static int audit_initialized;
#define AUDIT_OFF 0
#define AUDIT_ON 1
#define AUDIT_LOCKED 2
-int audit_ever_enabled;
+bool audit_ever_enabled;
/* Default state when kernel boots without any parameters. */
static int audit_default;
--
1.8.1.4
After this patch, audit_pid is per user namespace.
Since we havn't prepared to enable audit for uninit
user namespace now, use the audit_pid of init_user_ns
instead of the audit_pid of per user namespace.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/audit.h | 1 +
include/linux/user_namespace.h | 1 +
kernel/audit.c | 22 +++++++++++-----------
kernel/audit.h | 5 ++---
kernel/auditsc.c | 6 +++---
5 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 78f51ae..684599b 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -26,6 +26,7 @@
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <uapi/linux/audit.h>
+#include <linux/user_namespace.h>
struct audit_sig_info {
uid_t uid;
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 24f7c2f..a6c6174 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -21,6 +21,7 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */
#ifdef CONFIG_AUDIT
struct audit_ctrl {
struct sock *sock;
+ int pid;
struct sk_buff_head queue;
struct sk_buff_head hold_queue;
struct task_struct *kauditd_task;
diff --git a/kernel/audit.c b/kernel/audit.c
index 839c4c0..2ce7a21 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -92,7 +92,6 @@ static int audit_failure = AUDIT_FAIL_PRINTK;
* contains the pid of the auditd process and audit_nlk_portid contains
* the portid to use to send netlink messages to that process.
*/
-int audit_pid;
static int audit_nlk_portid;
/* If audit_rate_limit is non-zero, limit the rate of sending audit records
@@ -181,7 +180,7 @@ void audit_panic(const char *message)
break;
case AUDIT_FAIL_PANIC:
/* test audit_pid since printk is always losey, why bother? */
- if (audit_pid)
+ if (&init_user_ns.audit.pid)
panic("audit: %s\n", message);
break;
}
@@ -404,9 +403,10 @@ static void kauditd_send_skb(struct sk_buff *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);
+ printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n",
+ init_user_ns.audit.pid);
audit_log_lost("auditd disappeared\n");
- audit_pid = 0;
+ init_user_ns.audit.pid = 0;
/* we might get lucky and get this in the next auditd */
audit_hold_skb(skb);
} else
@@ -436,10 +436,10 @@ static int kauditd_thread(void *dummy)
* in 5 years when I want to play with this again I'll see this
* note and still have no friggin idea what i'm thinking today.
*/
- if (audit_default && audit_pid) {
+ if (audit_default && ns->audit.pid) {
skb = skb_dequeue(hold_queue);
if (unlikely(skb)) {
- while (skb && audit_pid) {
+ while (skb && ns->audit.pid) {
kauditd_send_skb(skb);
skb = skb_dequeue(hold_queue);
}
@@ -449,7 +449,7 @@ static int kauditd_thread(void *dummy)
skb = skb_dequeue(queue);
wake_up(&audit_backlog_wait);
if (skb) {
- if (audit_pid)
+ if (ns->audit.pid)
kauditd_send_skb(skb);
else
audit_printk_skb(skb);
@@ -683,7 +683,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_GET:
status_set.enabled = audit_enabled;
status_set.failure = audit_failure;
- status_set.pid = audit_pid;
+ status_set.pid = ns->audit.pid;
status_set.rate_limit = audit_rate_limit;
status_set.backlog_limit = audit_backlog_limit;
status_set.lost = atomic_read(&audit_lost);
@@ -713,10 +713,10 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (audit_enabled != AUDIT_OFF)
audit_log_config_change("audit_pid", new_pid,
- audit_pid, loginuid,
+ ns->audit.pid, loginuid,
sessionid, sid, 1);
- audit_pid = new_pid;
+ ns->audit.pid = new_pid;
audit_nlk_portid = NETLINK_CB(skb).portid;
}
if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) {
@@ -1530,7 +1530,7 @@ void audit_log_end(struct audit_buffer *ab)
struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
nlh->nlmsg_len = ab->skb->len - NLMSG_HDRLEN;
- if (audit_pid) {
+ if (init_user_ns.audit.pid) {
skb_queue_tail(&init_user_ns.audit.queue,
ab->skb);
wake_up_interruptible(&kauditd_wait);
diff --git a/kernel/audit.h b/kernel/audit.h
index 11468d9..ced93fe 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -61,8 +61,6 @@ struct audit_entry {
extern int audit_ever_enabled;
-extern int audit_pid;
-
#define AUDIT_INODE_BUCKETS 32
extern struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
@@ -153,7 +151,8 @@ extern u32 audit_sig_sid;
extern int __audit_signal_info(int sig, struct task_struct *t);
static inline int audit_signal_info(int sig, struct task_struct *t)
{
- if (unlikely((audit_pid && t->tgid == audit_pid) ||
+ if (unlikely((init_user_ns.audit.pid &&
+ t->tgid == init_user_ns.audit.pid) ||
(audit_signals && !audit_dummy_context())))
return __audit_signal_info(sig, t);
return 0;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index c682294..6c97f36 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -871,7 +871,7 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
struct audit_entry *e;
enum audit_state state;
- if (audit_pid && tsk->tgid == audit_pid)
+ if (init_user_ns.audit.pid && tsk->tgid == init_user_ns.audit.pid)
return AUDIT_DISABLED;
rcu_read_lock();
@@ -932,7 +932,7 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
{
struct audit_names *n;
- if (audit_pid && tsk->tgid == audit_pid)
+ if (init_user_ns.audit.pid && tsk->tgid == init_user_ns.audit.pid)
return;
rcu_read_lock();
@@ -2547,7 +2547,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
struct audit_context *ctx = tsk->audit_context;
kuid_t uid = current_uid(), t_uid = task_uid(t);
- if (audit_pid && t->tgid == audit_pid) {
+ if (init_user_ns.audit.pid && t->tgid == init_user_ns.audit.pid) {
if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) {
audit_sig_pid = tsk->pid;
if (uid_valid(tsk->loginuid))
--
1.8.1.4
We set audit_ever_enabled true after we enabled audit once.
and if audit_ever_enabled is true, we will allocate audit
context for task.
We should decide if to allocate audit context for tasks based on
if the audit is enabled once in the user namespace which the
task belongs to.
So audit_ever_enabled should be per user namespace too.
Signed-off-by: Gao feng <[email protected]>
---
include/linux/user_namespace.h | 1 +
kernel/audit.c | 7 +++----
kernel/auditsc.c | 5 ++++-
3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 3b2ed90..d5a22b2 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -27,6 +27,7 @@ struct audit_ctrl {
struct sk_buff_head queue;
struct sk_buff_head hold_queue;
struct task_struct *kauditd_task;
+ bool ever_enabled;
};
#endif
diff --git a/kernel/audit.c b/kernel/audit.c
index 1138ff5..9ea5b27 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -76,7 +76,6 @@ static int audit_initialized;
#define AUDIT_OFF 0
#define AUDIT_ON 1
#define AUDIT_LOCKED 2
-bool audit_ever_enabled;
/* Default state when kernel boots without any parameters. */
static int audit_default;
@@ -331,7 +330,7 @@ static int audit_set_enabled(struct user_namespace *ns, int state,
state, loginuid, sessionid, sid);
if (!rc)
- audit_ever_enabled |= !!state;
+ ns->audit.ever_enabled |= !!state;
return rc;
}
@@ -994,7 +993,6 @@ static int __init audit_init(void)
audit_set_user_ns(&init_user_ns);
audit_initialized = AUDIT_INITIALIZED;
- audit_ever_enabled |= !!audit_default;
audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
@@ -1016,7 +1014,7 @@ static int __init audit_enable(char *str)
if (audit_initialized == AUDIT_INITIALIZED) {
init_user_ns.audit.enabled = audit_default;
- audit_ever_enabled |= !!audit_default;
+ init_user_ns.audit.ever_enabled |= !!audit_default;
} else if (audit_initialized == AUDIT_UNINITIALIZED) {
printk(" (after initialization)");
} else {
@@ -1594,6 +1592,7 @@ void audit_set_user_ns(struct user_namespace *ns)
skb_queue_head_init(&ns->audit.queue);
skb_queue_head_init(&ns->audit.hold_queue);
ns->audit.enabled = audit_default;
+ ns->audit.ever_enabled |= !!audit_default;
}
void audit_free_user_ns(struct user_namespace *ns)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 6c97f36..290cce6 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1062,8 +1062,11 @@ int audit_alloc(struct task_struct *tsk)
struct audit_context *context;
enum audit_state state;
char *key = NULL;
+ struct user_namespace *ns = current_user_ns();
+ /* Use current_user_ns, since this new task may run
+ * in new user namespace */
- if (likely(!audit_ever_enabled))
+ if (likely(!ns->audit.ever_enabled))
return 0; /* Return if not auditing. */
state = audit_filter_task(tsk, &key);
--
1.8.1.4
After this patch, audit netlink sockets can
communicate with each other when they belong
to the same user namespace.
Signed-off-by: Gao feng <[email protected]>
---
kernel/audit.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/kernel/audit.c b/kernel/audit.c
index 766dcbf..3ae8793 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -937,6 +937,11 @@ static void audit_receive(struct sk_buff *skb)
mutex_unlock(&audit_cmd_mutex);
}
+static bool audit_compare(struct net *net, struct sock *sk)
+{
+ return (sock_net(sk)->user_ns == net->user_ns);
+}
+
static int __net_init audit_net_init(struct net *net)
{
struct user_namespace *ns = net->user_ns;
@@ -949,6 +954,7 @@ static int __net_init audit_net_init(struct net *net)
*/
struct netlink_kernel_cfg cfg = {
.input = audit_receive,
+ .compare = audit_compare,
};
sk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg);
--
1.8.1.4
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 <[email protected]>
---
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 <linux/freezer.h>
#include <linux/tty.h>
#include <linux/pid_namespace.h>
+#include <linux/user_namespace.h>
#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 <linux/ctype.h>
#include <linux/projid.h>
#include <linux/fs_struct.h>
+#include <linux/audit.h>
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
On Tue, May 07, 2013 at 10:20:30AM +0800, Gao feng wrote:
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 684599b..33e6584 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -441,7 +441,8 @@ extern int audit_filter_type(int type);
> extern int audit_receive_filter(int type, int pid, int seq,
> void *data, size_t datasz, kuid_t loginuid,
> u32 sessionid, u32 sid);
> -extern int audit_enabled;
> +#define audit_enabled (init_user_ns.audit.enabled)
> +#define audit_enabled_ns (ns->audit.enabled)
> #else /* CONFIG_AUDIT */
> static inline __printf(4, 5)
> void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
> @@ -487,6 +488,7 @@ static inline void audit_set_user_ns(struct user_namespace *ns)
> static inline void audit_free_user_ns(struct user_namespace *ns)
> { }
> #define audit_enabled 0
> +#define audit_enabled_ns(ns) 0
conflicting definitions here. maybe the first one should be
#define audit_enabled_ns(ns) (ns->audit.enabled)?
> @@ -285,14 +282,15 @@ static int audit_do_config_change(char *function_name, int *to_change,
> u32 sid)
> {
> int allow_changes, rc = 0, old = *to_change;
> + struct user_namespace *ns = current_user_ns();
>
> /* check if we are locked */
> - if (audit_enabled == AUDIT_LOCKED)
> + if (ns->audit.enabled == AUDIT_LOCKED)
then you don't use the macro you introduced?
> @@ -609,7 +608,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
> char *ctx = NULL;
> u32 len;
>
> - if (!audit_enabled) {
> + if (!init_user_ns.audit.enabled) {
> *ab = NULL;
> return rc;
> }
same here
--
Aristeu
On Tue, May 07, 2013 at 10:20:31AM +0800, Gao feng wrote:
> It's better to define audit_ever_enabled as bool
>
> Signed-off-by: Gao feng <[email protected]>
> ---
> kernel/audit.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 4595a9e..1138ff5 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -76,7 +76,7 @@ static int audit_initialized;
> #define AUDIT_OFF 0
> #define AUDIT_ON 1
> #define AUDIT_LOCKED 2
> -int audit_ever_enabled;
> +bool audit_ever_enabled;
I think you're better off placing this at the beginning of the series
and submitting it separately since it's only incidentally related to
this RFC.
Cheers,
-Matt Helsley
On 05/07/2013 11:44 PM, Aristeu Rozanski wrote:
> On Tue, May 07, 2013 at 10:20:30AM +0800, Gao feng wrote:
>> diff --git a/include/linux/audit.h b/include/linux/audit.h
>> index 684599b..33e6584 100644
>> --- a/include/linux/audit.h
>> +++ b/include/linux/audit.h
>> @@ -441,7 +441,8 @@ extern int audit_filter_type(int type);
>> extern int audit_receive_filter(int type, int pid, int seq,
>> void *data, size_t datasz, kuid_t loginuid,
>> u32 sessionid, u32 sid);
>> -extern int audit_enabled;
>> +#define audit_enabled (init_user_ns.audit.enabled)
>> +#define audit_enabled_ns (ns->audit.enabled)
>> #else /* CONFIG_AUDIT */
>> static inline __printf(4, 5)
>> void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
>> @@ -487,6 +488,7 @@ static inline void audit_set_user_ns(struct user_namespace *ns)
>> static inline void audit_free_user_ns(struct user_namespace *ns)
>> { }
>> #define audit_enabled 0
>> +#define audit_enabled_ns(ns) 0
>
> conflicting definitions here. maybe the first one should be
> #define audit_enabled_ns(ns) (ns->audit.enabled)?
>
Yes, it should be audit_enabled_ns(ns), I will fix this in next round.
>> @@ -285,14 +282,15 @@ static int audit_do_config_change(char *function_name, int *to_change,
>> u32 sid)
>> {
>> int allow_changes, rc = 0, old = *to_change;
>> + struct user_namespace *ns = current_user_ns();
>>
>> /* check if we are locked */
>> - if (audit_enabled == AUDIT_LOCKED)
>> + if (ns->audit.enabled == AUDIT_LOCKED)
>
> then you don't use the macro you introduced?
will fix this too.
>
>> @@ -609,7 +608,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
>> char *ctx = NULL;
>> u32 len;
>>
>> - if (!audit_enabled) {
>> + if (!init_user_ns.audit.enabled) {
>> *ab = NULL;
>> return rc;
>> }
>
> same here
>
Get it.
Thanks for your comments!
Gao
On 05/08/2013 10:06 AM, Matt Helsley wrote:
> On Tue, May 07, 2013 at 10:20:31AM +0800, Gao feng wrote:
>> It's better to define audit_ever_enabled as bool
>>
>> Signed-off-by: Gao feng <[email protected]>
>> ---
>> kernel/audit.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/kernel/audit.c b/kernel/audit.c
>> index 4595a9e..1138ff5 100644
>> --- a/kernel/audit.c
>> +++ b/kernel/audit.c
>> @@ -76,7 +76,7 @@ static int audit_initialized;
>> #define AUDIT_OFF 0
>> #define AUDIT_ON 1
>> #define AUDIT_LOCKED 2
>> -int audit_ever_enabled;
>> +bool audit_ever_enabled;
>
> I think you're better off placing this at the beginning of the series
> and submitting it separately since it's only incidentally related to
> this RFC.
>
Thanks for your suggestion. will send these cleanup patches separately.
Thanks
Gao
What kernel are these patches against?
On Tue, 2013-05-07 at 10:20 +0800, Gao feng wrote:
> This patchset try to add namespace support for audit.
>
> I choose to assign audit to the user namespace.
> Right now,there are six kinds of namespaces, such as
> net, mount, ipc, pid, uts and user. the first five
> namespaces have special usage. the audit isn't suitable to
> belong to these five namespaces, so the user namespace
> may be the best choice.
>
> Through I decide to make audit related resources per user
> namespace, but audit uses netlink to communicate between kernel
> space and user space, and the netlink is a private resource
> of per net namespace. So we need the capability to allow the
> netlink sockets to communicate with each other in the same user
> namespace even they are in different net namespace. [PATCH 2/48]
> does this job, it adds a new function "compare" for per netlink
> table to compare two sockets. it means the netlink protocols can
> has its own compare fuction, For other protocols, two netlink
> sockets are different if they belong to the different net namespace.
> For audit protocol, two sockets can be the same even they in different
> net namespace,we use user namespace not net namespace to make the
> decision.
>
> There is one point that some people may dislike,in [PATCH 1/48],
> the kernel side audit netlink socket is created only when we create
> the first netns for the userns, and this userns will hold the netns
> until we destroy this userns.
>
> The other patches just make the audit related resources per
> user namespace.
>
> This patchset is sent as an RFC,any comments are welcome.
>
> Gao feng (48):
> Audit: make audit kernel side netlink sock per userns
> netlink: Add compare function for netlink_table
> Audit: implement audit self-defined compare function
> Audit: make audit_skb_queue per user namespace
> Audit: make audit_skb_hold_queue per user namespace
> Audit: make kauditd_task per user namespace
> Audit: make audit_pid per user namespace
> Audit: make audit_nlk_portid per user namesapce
> Audit: make audit_enabled per user namespace
> Audit: change type of audit_ever_enabled to bool
> Audit: make audit_ever_enabled per user namespace
> Audit: make audit_initialized per user namespace
> Audit: only allow init user namespace to change audit_rate_limit
> Audit: only allow init user namespace to change audit_failure
> Audit: allow to send netlink message to auditd in uninit user
> namespace
> Audit: user proper user namespace in audit_log_config_change
> Audit: make kauditd_wait per user namespace
> Audit: make audit_backlog_wait per user namespace
> Audit: remove duplicate comments
> Audit: introduce new audit logging interface for user namespace
> Audit: pass proper user namespace to audit_log_common_recv_msg
> Audit: Log audit config change in uninit user namespace
> Audit: netfilter: Log xt table replace behavior in proper user
> namespace
> Audit: xt_AUDIT: Log audit message in proper user namespace
> Audit: send reply message to the auditd in proper user namespace
> Audit: make audit_inode_hash per user namespace
> Audit: make tree_list per user namespace
> Audit: make audit filter list per user namespace
> Audit: make audit_krule belongs to user namespace
> Audit: reply audit filter list request to proper user namespace
> Audit: pass proper user namespace to audit_filter_syscall
> Audit: pass proper user namespace to audit_filter_inode_name
> Audit: Log filter related audit message to proper user namespace
> Log audit tree related message in proper user namespace
> Audit: Log task related audit message to proper user namespace
> Audit: Log watch related audit message to proper user namespace
> Audit: translate audit_log_start to audit_log_start_ns
> Audit: tty: translate audit_log_start to audit_log_start_ns
> Audit: netlabel: translate audit_log_start to audit_log_start_ns
> Audit: ima: translate audit_log_start to audit_log_start_ns
> Audit: lsm: translate audit_log_start to audit_log_start_ns
> Audit: selinux: translate audit_log_start to audit_log_start_ns
> Audit: xfrm: translate audit_log_start to audit_log_start_ns
> Audit: rename audit_log_start_ns to audit_log_start
> Audit: user audit_enabled_ns to replace audit_enabled
> Audit: rename audit_enabled_ns to audit_enabled
> Audit: make audit_log user namespace awared
> Audit: allow root user of un-init user namespace to set audit
>
> drivers/tty/tty_audit.c | 9 +-
> include/linux/audit.h | 44 ++--
> include/linux/netlink.h | 1 +
> include/linux/user_namespace.h | 25 +++
> include/net/xfrm.h | 7 +-
> kernel/audit.c | 393 +++++++++++++++++++++---------------
> kernel/audit.h | 24 +--
> kernel/audit_tree.c | 49 ++---
> kernel/audit_watch.c | 23 ++-
> kernel/auditfilter.c | 76 +++----
> kernel/auditsc.c | 156 ++++++++------
> kernel/user.c | 19 ++
> kernel/user_namespace.c | 3 +
> net/core/dev.c | 12 +-
> net/ipv4/cipso_ipv4.c | 4 +-
> net/netfilter/x_tables.c | 9 +-
> net/netfilter/xt_AUDIT.c | 8 +-
> net/netlabel/netlabel_domainhash.c | 4 +-
> net/netlabel/netlabel_unlabeled.c | 8 +-
> net/netlabel/netlabel_user.c | 8 +-
> net/netlink/af_netlink.c | 26 ++-
> net/netlink/af_netlink.h | 1 +
> net/xfrm/xfrm_policy.c | 4 +-
> net/xfrm/xfrm_state.c | 14 +-
> security/apparmor/lib.c | 2 +-
> security/integrity/ima/ima_api.c | 5 +-
> security/integrity/ima/ima_audit.c | 11 +-
> security/integrity/ima/ima_policy.c | 5 +-
> security/lsm_audit.c | 8 +-
> security/selinux/avc.c | 3 +-
> security/selinux/hooks.c | 17 +-
> security/selinux/selinuxfs.c | 9 +-
> security/selinux/ss/services.c | 30 ++-
> security/smack/smack_lsm.c | 3 +-
> 34 files changed, 630 insertions(+), 390 deletions(-)
>
On 05/09/2013 12:55 AM, Eric Paris wrote:
> What kernel are these patches against?
>
This patchset is based on linus's tree.
The last commit is d7ab7302f970a254997687a1cdede421a5635c68
(Merge tag 'mfd-3.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/same)
Thanks
Gao
On 05/07/2013 10:20 AM, Gao feng wrote:
> + if (ns->audit.kauditd_task)
> + kthread_stop(ns->audit.kauditd_task);
This is buggy,will trigger warning scheduling while atomic:
I will take care this problem.
On 05/07/2013 10:20 AM, Gao feng wrote:
> This patchset try to add namespace support for audit.
>
> I choose to assign audit to the user namespace.
> Right now,there are six kinds of namespaces, such as
> net, mount, ipc, pid, uts and user. the first five
> namespaces have special usage. the audit isn't suitable to
> belong to these five namespaces, so the user namespace
> may be the best choice.
>
> Through I decide to make audit related resources per user
> namespace, but audit uses netlink to communicate between kernel
> space and user space, and the netlink is a private resource
> of per net namespace. So we need the capability to allow the
> netlink sockets to communicate with each other in the same user
> namespace even they are in different net namespace. [PATCH 2/48]
> does this job, it adds a new function "compare" for per netlink
> table to compare two sockets. it means the netlink protocols can
> has its own compare fuction, For other protocols, two netlink
> sockets are different if they belong to the different net namespace.
> For audit protocol, two sockets can be the same even they in different
> net namespace,we use user namespace not net namespace to make the
> decision.
>
> There is one point that some people may dislike,in [PATCH 1/48],
> the kernel side audit netlink socket is created only when we create
> the first netns for the userns, and this userns will hold the netns
> until we destroy this userns.
>
> The other patches just make the audit related resources per
> user namespace.
>
> This patchset is sent as an RFC,any comments are welcome.
>
Half of month passed, Can anybody give me some comments or advice or even
an ACK?
I think the key point is the first 3 patch. these patches add a compare
function per netlink_table, netlink sockets use this compare function to
decide if they can communicate with each other. For other netlink protocols
we use net namespace to make this decision. But for audit netlink protocol,
we use user namespace to make the decision. It means, for audit netlink sockets,
they can communicate when they in same user namespace and there is no need
for them to stay in same net namespace.
I don't know if anyone object to this and if there is a better solution.
Eric, Serge & David, can you give me some comments?
Thanks!
> Gao feng (48):
> Audit: make audit kernel side netlink sock per userns
> netlink: Add compare function for netlink_table
> Audit: implement audit self-defined compare function
> Audit: make audit_skb_queue per user namespace
> Audit: make audit_skb_hold_queue per user namespace
> Audit: make kauditd_task per user namespace
> Audit: make audit_pid per user namespace
> Audit: make audit_nlk_portid per user namesapce
> Audit: make audit_enabled per user namespace
> Audit: change type of audit_ever_enabled to bool
> Audit: make audit_ever_enabled per user namespace
> Audit: make audit_initialized per user namespace
> Audit: only allow init user namespace to change audit_rate_limit
> Audit: only allow init user namespace to change audit_failure
> Audit: allow to send netlink message to auditd in uninit user
> namespace
> Audit: user proper user namespace in audit_log_config_change
> Audit: make kauditd_wait per user namespace
> Audit: make audit_backlog_wait per user namespace
> Audit: remove duplicate comments
> Audit: introduce new audit logging interface for user namespace
> Audit: pass proper user namespace to audit_log_common_recv_msg
> Audit: Log audit config change in uninit user namespace
> Audit: netfilter: Log xt table replace behavior in proper user
> namespace
> Audit: xt_AUDIT: Log audit message in proper user namespace
> Audit: send reply message to the auditd in proper user namespace
> Audit: make audit_inode_hash per user namespace
> Audit: make tree_list per user namespace
> Audit: make audit filter list per user namespace
> Audit: make audit_krule belongs to user namespace
> Audit: reply audit filter list request to proper user namespace
> Audit: pass proper user namespace to audit_filter_syscall
> Audit: pass proper user namespace to audit_filter_inode_name
> Audit: Log filter related audit message to proper user namespace
> Log audit tree related message in proper user namespace
> Audit: Log task related audit message to proper user namespace
> Audit: Log watch related audit message to proper user namespace
> Audit: translate audit_log_start to audit_log_start_ns
> Audit: tty: translate audit_log_start to audit_log_start_ns
> Audit: netlabel: translate audit_log_start to audit_log_start_ns
> Audit: ima: translate audit_log_start to audit_log_start_ns
> Audit: lsm: translate audit_log_start to audit_log_start_ns
> Audit: selinux: translate audit_log_start to audit_log_start_ns
> Audit: xfrm: translate audit_log_start to audit_log_start_ns
> Audit: rename audit_log_start_ns to audit_log_start
> Audit: user audit_enabled_ns to replace audit_enabled
> Audit: rename audit_enabled_ns to audit_enabled
> Audit: make audit_log user namespace awared
> Audit: allow root user of un-init user namespace to set audit
>
> drivers/tty/tty_audit.c | 9 +-
> include/linux/audit.h | 44 ++--
> include/linux/netlink.h | 1 +
> include/linux/user_namespace.h | 25 +++
> include/net/xfrm.h | 7 +-
> kernel/audit.c | 393 +++++++++++++++++++++---------------
> kernel/audit.h | 24 +--
> kernel/audit_tree.c | 49 ++---
> kernel/audit_watch.c | 23 ++-
> kernel/auditfilter.c | 76 +++----
> kernel/auditsc.c | 156 ++++++++------
> kernel/user.c | 19 ++
> kernel/user_namespace.c | 3 +
> net/core/dev.c | 12 +-
> net/ipv4/cipso_ipv4.c | 4 +-
> net/netfilter/x_tables.c | 9 +-
> net/netfilter/xt_AUDIT.c | 8 +-
> net/netlabel/netlabel_domainhash.c | 4 +-
> net/netlabel/netlabel_unlabeled.c | 8 +-
> net/netlabel/netlabel_user.c | 8 +-
> net/netlink/af_netlink.c | 26 ++-
> net/netlink/af_netlink.h | 1 +
> net/xfrm/xfrm_policy.c | 4 +-
> net/xfrm/xfrm_state.c | 14 +-
> security/apparmor/lib.c | 2 +-
> security/integrity/ima/ima_api.c | 5 +-
> security/integrity/ima/ima_audit.c | 11 +-
> security/integrity/ima/ima_policy.c | 5 +-
> security/lsm_audit.c | 8 +-
> security/selinux/avc.c | 3 +-
> security/selinux/hooks.c | 17 +-
> security/selinux/selinuxfs.c | 9 +-
> security/selinux/ss/services.c | 30 ++-
> security/smack/smack_lsm.c | 3 +-
> 34 files changed, 630 insertions(+), 390 deletions(-)
>
Quoting Gao feng ([email protected]):
> On 05/07/2013 10:20 AM, Gao feng wrote:
> > This patchset try to add namespace support for audit.
> >
> > I choose to assign audit to the user namespace.
> > Right now,there are six kinds of namespaces, such as
> > net, mount, ipc, pid, uts and user. the first five
> > namespaces have special usage. the audit isn't suitable to
> > belong to these five namespaces, so the user namespace
> > may be the best choice.
> >
> > Through I decide to make audit related resources per user
> > namespace, but audit uses netlink to communicate between kernel
> > space and user space, and the netlink is a private resource
> > of per net namespace. So we need the capability to allow the
> > netlink sockets to communicate with each other in the same user
> > namespace even they are in different net namespace. [PATCH 2/48]
> > does this job, it adds a new function "compare" for per netlink
> > table to compare two sockets. it means the netlink protocols can
> > has its own compare fuction, For other protocols, two netlink
> > sockets are different if they belong to the different net namespace.
> > For audit protocol, two sockets can be the same even they in different
> > net namespace,we use user namespace not net namespace to make the
> > decision.
> >
> > There is one point that some people may dislike,in [PATCH 1/48],
> > the kernel side audit netlink socket is created only when we create
> > the first netns for the userns, and this userns will hold the netns
> > until we destroy this userns.
> >
> > The other patches just make the audit related resources per
> > user namespace.
> >
> > This patchset is sent as an RFC,any comments are welcome.
Hi,
thanks for sending this. I think you need to ping the selinux folks
for comment though. It appears to me that, after this patchset, the
kernel with CONFIG_USER_NS=y could not be LSPP-compliant, because
the selinux-generated audit messages do not always go to init_user_ns.
Additionally, the only type of namespacing selinux wants is where it
is enforced by policy compiler and installer using typenames - i.e.
'container1.user_t' vs 'user_t'. Selinux does not want user namespaces
to affect selinux enforcement at all. (at least last I knew, several
years ago at a mini-summit, I believe this was from Stephen Smalley).
I think it's good to have userspace-generated audit messages (i.e.
auditctl -m 'hi there') sent to the same user namespace. But the
selinux messages, near as I can tell, need to all go to init_user_ns.
thanks,
-serge
Quoting Serge Hallyn ([email protected]):
> Quoting Gao feng ([email protected]):
> > On 05/07/2013 10:20 AM, Gao feng wrote:
> > > This patchset try to add namespace support for audit.
> > >
> > > I choose to assign audit to the user namespace.
> > > Right now,there are six kinds of namespaces, such as
> > > net, mount, ipc, pid, uts and user. the first five
> > > namespaces have special usage. the audit isn't suitable to
> > > belong to these five namespaces, so the user namespace
> > > may be the best choice.
> > >
> > > Through I decide to make audit related resources per user
> > > namespace, but audit uses netlink to communicate between kernel
> > > space and user space, and the netlink is a private resource
> > > of per net namespace. So we need the capability to allow the
> > > netlink sockets to communicate with each other in the same user
> > > namespace even they are in different net namespace. [PATCH 2/48]
> > > does this job, it adds a new function "compare" for per netlink
> > > table to compare two sockets. it means the netlink protocols can
> > > has its own compare fuction, For other protocols, two netlink
> > > sockets are different if they belong to the different net namespace.
> > > For audit protocol, two sockets can be the same even they in different
> > > net namespace,we use user namespace not net namespace to make the
> > > decision.
> > >
> > > There is one point that some people may dislike,in [PATCH 1/48],
> > > the kernel side audit netlink socket is created only when we create
> > > the first netns for the userns, and this userns will hold the netns
> > > until we destroy this userns.
> > >
> > > The other patches just make the audit related resources per
> > > user namespace.
> > >
> > > This patchset is sent as an RFC,any comments are welcome.
>
> Hi,
>
> thanks for sending this. I think you need to ping the selinux folks
> for comment though. It appears to me that, after this patchset, the
> kernel with CONFIG_USER_NS=y could not be LSPP-compliant, because
> the selinux-generated audit messages do not always go to init_user_ns.
>
> Additionally, the only type of namespacing selinux wants is where it
> is enforced by policy compiler and installer using typenames - i.e.
> 'container1.user_t' vs 'user_t'. Selinux does not want user namespaces
> to affect selinux enforcement at all. (at least last I knew, several
> years ago at a mini-summit, I believe this was from Stephen Smalley).
That sort of sounds like I'm distancing myself from that, which I
don't mean to do. I agree with the decison: MAC (selinux, apparmor
and smack) should not be confuddled by user namespaces. (posix caps
are, as always, a bit different).
> I think it's good to have userspace-generated audit messages (i.e.
> auditctl -m 'hi there') sent to the same user namespace. But the
> selinux messages, near as I can tell, need to all go to init_user_ns.
>
> thanks,
> -serge
> _______________________________________________
> Containers mailing list
> [email protected]
> https://lists.linuxfoundation.org/mailman/listinfo/containers
On 06/07/2013 06:47 AM, Serge Hallyn wrote:
> Quoting Serge Hallyn ([email protected]):
>> Quoting Gao feng ([email protected]):
>>> On 05/07/2013 10:20 AM, Gao feng wrote:
>>>> This patchset try to add namespace support for audit.
>>>>
>>>> I choose to assign audit to the user namespace.
>>>> Right now,there are six kinds of namespaces, such as
>>>> net, mount, ipc, pid, uts and user. the first five
>>>> namespaces have special usage. the audit isn't suitable to
>>>> belong to these five namespaces, so the user namespace
>>>> may be the best choice.
>>>>
>>>> Through I decide to make audit related resources per user
>>>> namespace, but audit uses netlink to communicate between kernel
>>>> space and user space, and the netlink is a private resource
>>>> of per net namespace. So we need the capability to allow the
>>>> netlink sockets to communicate with each other in the same user
>>>> namespace even they are in different net namespace. [PATCH 2/48]
>>>> does this job, it adds a new function "compare" for per netlink
>>>> table to compare two sockets. it means the netlink protocols can
>>>> has its own compare fuction, For other protocols, two netlink
>>>> sockets are different if they belong to the different net namespace.
>>>> For audit protocol, two sockets can be the same even they in different
>>>> net namespace,we use user namespace not net namespace to make the
>>>> decision.
>>>>
>>>> There is one point that some people may dislike,in [PATCH 1/48],
>>>> the kernel side audit netlink socket is created only when we create
>>>> the first netns for the userns, and this userns will hold the netns
>>>> until we destroy this userns.
>>>>
>>>> The other patches just make the audit related resources per
>>>> user namespace.
>>>>
>>>> This patchset is sent as an RFC,any comments are welcome.
>>
>> Hi,
>>
>> thanks for sending this. I think you need to ping the selinux folks
>> for comment though. It appears to me that, after this patchset, the
>> kernel with CONFIG_USER_NS=y could not be LSPP-compliant, because
>> the selinux-generated audit messages do not always go to init_user_ns.
>>
>> Additionally, the only type of namespacing selinux wants is where it
>> is enforced by policy compiler and installer using typenames - i.e.
>> 'container1.user_t' vs 'user_t'. Selinux does not want user namespaces
>> to affect selinux enforcement at all. (at least last I knew, several
>> years ago at a mini-summit, I believe this was from Stephen Smalley).
>
> That sort of sounds like I'm distancing myself from that, which I
> don't mean to do. I agree with the decison: MAC (selinux, apparmor
> and smack) should not be confuddled by user namespaces. (posix caps
> are, as always, a bit different).
Thanks for your comments!
Very useful information, it sounds reasonable.
Let's just drop those patches.
Thanks,
Gao
>
>> I think it's good to have userspace-generated audit messages (i.e.
>> auditctl -m 'hi there') sent to the same user namespace. But the
>> selinux messages, near as I can tell, need to all go to init_user_ns.
>>
>> thanks,
>> -serge
>> _______________________________________________
>> Containers mailing list
>> [email protected]
>> https://lists.linuxfoundation.org/mailman/listinfo/containers
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
Quoting Gao feng ([email protected]):
> On 06/07/2013 06:47 AM, Serge Hallyn wrote:
> > Quoting Serge Hallyn ([email protected]):
> >> Quoting Gao feng ([email protected]):
> >>> On 05/07/2013 10:20 AM, Gao feng wrote:
> >>>> This patchset try to add namespace support for audit.
> >>>>
> >>>> I choose to assign audit to the user namespace.
> >>>> Right now,there are six kinds of namespaces, such as
> >>>> net, mount, ipc, pid, uts and user. the first five
> >>>> namespaces have special usage. the audit isn't suitable to
> >>>> belong to these five namespaces, so the user namespace
> >>>> may be the best choice.
> >>>>
> >>>> Through I decide to make audit related resources per user
> >>>> namespace, but audit uses netlink to communicate between kernel
> >>>> space and user space, and the netlink is a private resource
> >>>> of per net namespace. So we need the capability to allow the
> >>>> netlink sockets to communicate with each other in the same user
> >>>> namespace even they are in different net namespace. [PATCH 2/48]
> >>>> does this job, it adds a new function "compare" for per netlink
> >>>> table to compare two sockets. it means the netlink protocols can
> >>>> has its own compare fuction, For other protocols, two netlink
> >>>> sockets are different if they belong to the different net namespace.
> >>>> For audit protocol, two sockets can be the same even they in different
> >>>> net namespace,we use user namespace not net namespace to make the
> >>>> decision.
> >>>>
> >>>> There is one point that some people may dislike,in [PATCH 1/48],
> >>>> the kernel side audit netlink socket is created only when we create
> >>>> the first netns for the userns, and this userns will hold the netns
> >>>> until we destroy this userns.
> >>>>
> >>>> The other patches just make the audit related resources per
> >>>> user namespace.
> >>>>
> >>>> This patchset is sent as an RFC,any comments are welcome.
> >>
> >> Hi,
> >>
> >> thanks for sending this. I think you need to ping the selinux folks
> >> for comment though. It appears to me that, after this patchset, the
> >> kernel with CONFIG_USER_NS=y could not be LSPP-compliant, because
> >> the selinux-generated audit messages do not always go to init_user_ns.
> >>
> >> Additionally, the only type of namespacing selinux wants is where it
> >> is enforced by policy compiler and installer using typenames - i.e.
> >> 'container1.user_t' vs 'user_t'. Selinux does not want user namespaces
> >> to affect selinux enforcement at all. (at least last I knew, several
> >> years ago at a mini-summit, I believe this was from Stephen Smalley).
> >
> > That sort of sounds like I'm distancing myself from that, which I
> > don't mean to do. I agree with the decison: MAC (selinux, apparmor
> > and smack) should not be confuddled by user namespaces. (posix caps
> > are, as always, a bit different).
>
>
> Thanks for your comments!
>
> Very useful information, it sounds reasonable.
>
> Let's just drop those patches.
>
Hi Gao,
proceeding then,
The netfilter related changes I think make sense. They log to the userns
which owns the netns in question, which seems right.
However looking at Audit-tty-translate-audit_log_start-to-audit_log_sta.patch,
it appears to log to the userns of the task which is doing the operation.
Keeping in mind that an unprivileged user can create a new user namespace,
this doesn't seem right.
Also, you are introducing per-userns syscall filter. It looks like I
can then create a new userns to escape my existing syscall filter, since
the filters up the user_ns parent chain are not being applied. Is that
correct?
Did you have a particular rationale written out for what precisely you're
wanting to make per-userns? That would be helpful in trying to figure
out which bits are appropriate. Again I so far haven't seen a single
problem with the code itself, it's just a question of which bits we
actually want (and are safe).
-serge
On 06/11/2013 05:24 AM, Serge E. Hallyn wrote:
> Quoting Gao feng ([email protected]):
>> On 06/07/2013 06:47 AM, Serge Hallyn wrote:
>>> Quoting Serge Hallyn ([email protected]):
>>>> Quoting Gao feng ([email protected]):
>>>>> On 05/07/2013 10:20 AM, Gao feng wrote:
>>>>>> This patchset try to add namespace support for audit.
>>>>>>
>>>>>> I choose to assign audit to the user namespace.
>>>>>> Right now,there are six kinds of namespaces, such as
>>>>>> net, mount, ipc, pid, uts and user. the first five
>>>>>> namespaces have special usage. the audit isn't suitable to
>>>>>> belong to these five namespaces, so the user namespace
>>>>>> may be the best choice.
>>>>>>
>>>>>> Through I decide to make audit related resources per user
>>>>>> namespace, but audit uses netlink to communicate between kernel
>>>>>> space and user space, and the netlink is a private resource
>>>>>> of per net namespace. So we need the capability to allow the
>>>>>> netlink sockets to communicate with each other in the same user
>>>>>> namespace even they are in different net namespace. [PATCH 2/48]
>>>>>> does this job, it adds a new function "compare" for per netlink
>>>>>> table to compare two sockets. it means the netlink protocols can
>>>>>> has its own compare fuction, For other protocols, two netlink
>>>>>> sockets are different if they belong to the different net namespace.
>>>>>> For audit protocol, two sockets can be the same even they in different
>>>>>> net namespace,we use user namespace not net namespace to make the
>>>>>> decision.
>>>>>>
>>>>>> There is one point that some people may dislike,in [PATCH 1/48],
>>>>>> the kernel side audit netlink socket is created only when we create
>>>>>> the first netns for the userns, and this userns will hold the netns
>>>>>> until we destroy this userns.
>>>>>>
>>>>>> The other patches just make the audit related resources per
>>>>>> user namespace.
>>>>>>
>>>>>> This patchset is sent as an RFC,any comments are welcome.
>>>>
>>>> Hi,
>>>>
>>>> thanks for sending this. I think you need to ping the selinux folks
>>>> for comment though. It appears to me that, after this patchset, the
>>>> kernel with CONFIG_USER_NS=y could not be LSPP-compliant, because
>>>> the selinux-generated audit messages do not always go to init_user_ns.
>>>>
>>>> Additionally, the only type of namespacing selinux wants is where it
>>>> is enforced by policy compiler and installer using typenames - i.e.
>>>> 'container1.user_t' vs 'user_t'. Selinux does not want user namespaces
>>>> to affect selinux enforcement at all. (at least last I knew, several
>>>> years ago at a mini-summit, I believe this was from Stephen Smalley).
>>>
>>> That sort of sounds like I'm distancing myself from that, which I
>>> don't mean to do. I agree with the decison: MAC (selinux, apparmor
>>> and smack) should not be confuddled by user namespaces. (posix caps
>>> are, as always, a bit different).
>>
>>
>> Thanks for your comments!
>>
>> Very useful information, it sounds reasonable.
>>
>> Let's just drop those patches.
>>
>
> Hi Gao,
>
> proceeding then,
>
> The netfilter related changes I think make sense. They log to the userns
> which owns the netns in question, which seems right.
>
> However looking at Audit-tty-translate-audit_log_start-to-audit_log_sta.patch,
> it appears to log to the userns of the task which is doing the operation.
>
> Keeping in mind that an unprivileged user can create a new user namespace,
> this doesn't seem right.
>
> Also, you are introducing per-userns syscall filter. It looks like I
> can then create a new userns to escape my existing syscall filter, since
> the filters up the user_ns parent chain are not being applied. Is that
> correct?
Hi Serge,
I admit that the global resources related audit message should be logged to
parent and ancestor. but this is more complex than the way I implemented.
Because we should send message to all ancestor and we should consider not
to exceed the rate_limit of all ancestor.
I prefer to don't make these filters/rules per user namespace right now.
>
> Did you have a particular rationale written out for what precisely you're
> wanting to make per-userns? That would be helpful in trying to figure
> out which bits are appropriate. Again I so far haven't seen a single
> problem with the code itself, it's just a question of which bits we
> actually want (and are safe).
>
In my option, the audit rules(inode, tree_list, filter) , some of audit
controller related resources(enabled,pid,portid...) and skb queue, audit
netlink sockets,kauditd thread should be per-userns. The audit user message
which generated by the user in container should be per-userns too.
Since netns is not implemented as a hierarchy, and the network related
resources are not global. so network related audit message should be per-userns too.
The security related audit message should be send to init user namespace
as we discussed before. Maybe tty related audit message should be send
to init user namespace too, I have no idea now.
The next step, I will post a new patchset which only make the audit user
message and the basic audit resource per userns. I think this patchset
will easy to be reviewed and accepted, And will not influence the host.
This patchset contains the below patches:
Gao feng (21):
Audit: make audit kernel side netlink sock per userns
netlink: Add compare function for netlink_table
Audit: implement audit self-defined compare function
Audit: make audit_skb_queue per user namespace
Audit: make audit_skb_hold_queue per user namespace
Audit: make kauditd_task per user namespace
Audit: make audit_pid per user namespace
Audit: make audit_nlk_portid per user namesapce
Audit: make audit_enabled per user namespace
Audit: make audit_ever_enabled per user namespace
Audit: make audit_initialized per user namespace
Audit: only allow init user namespace to change rate limit
Audit: only allow init user namespace to change audit_failure
Audit: allow to send netlink message to auditd in uninit user
namespace
Audit: make kauditd_wait per user namespace
Audit: make audit_backlog_wait per user namespace
Audit: introduce new audit logging interface for user namespace
Audit: pass proper user namespace to audit_log_common_recv_msg
Audit: Log audit config change in uninit user namespace
Audit: send reply message to the auditd in proper user namespace
Audit: Allow GET,SET,USER MSG operations in uninit user namespace
include/linux/audit.h | 39 +++-
include/linux/netlink.h | 1 +
include/linux/user_namespace.h | 33 +++-
kernel/audit.c | 422 ++++++++++++++++++++++++++---------------
kernel/audit.h | 5 +-
kernel/auditsc.c | 11 +-
kernel/user_namespace.c | 3 +
net/netlink/af_netlink.c | 32 +++-
net/netlink/af_netlink.h | 1 +
9 files changed, 369 insertions(+), 178 deletions(-)
Do you have any comments or advice to this plan? After the above patchs
been accepted, I think it's easy to push other audit namespace related
patches into upstream.
Thanks,
Gao
> -serge
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
On Tue, 2013-06-11 at 13:59 +0800, Gao feng wrote:
> On 06/11/2013 05:24 AM, Serge E. Hallyn wrote:
> > Quoting Gao feng ([email protected]):
> >> On 06/07/2013 06:47 AM, Serge Hallyn wrote:
> >>> Quoting Serge Hallyn ([email protected]):
> >>>> Quoting Gao feng ([email protected]):
> >>>>> On 05/07/2013 10:20 AM, Gao feng wrote:
> In my option, the audit rules(inode, tree_list, filter) , some of audit
> controller related resources(enabled,pid,portid...) and skb queue, audit
> netlink sockets,kauditd thread should be per-userns. The audit user message
> which generated by the user in container should be per-userns too.
>
> Since netns is not implemented as a hierarchy, and the network related
> resources are not global. so network related audit message should be per-userns too.
>
> The security related audit message should be send to init user namespace
> as we discussed before. Maybe tty related audit message should be send
> to init user namespace too, I have no idea now.
>
> The next step, I will post a new patchset which only make the audit user
> message and the basic audit resource per userns. I think this patchset
> will easy to be reviewed and accepted, And will not influence the host.
> This patchset contains the below patches:
I think this would be easier for us do from a certification and
doumentation PoV if we had an audit namespace, not tied to the user
namespace. creating a new audit namespace should require
CAP_AUDIT_CONTROL in the user namespace which created the current audit
namespace.
Does that make sense? I don't mind messages staying completely inside
the current namespace, but that means we can't give unpriv users (even
if they have priv in their user namespace) a new audit namespace...
Quoting Eric Paris ([email protected]):
> On Tue, 2013-06-11 at 13:59 +0800, Gao feng wrote:
> > On 06/11/2013 05:24 AM, Serge E. Hallyn wrote:
> > > Quoting Gao feng ([email protected]):
> > >> On 06/07/2013 06:47 AM, Serge Hallyn wrote:
> > >>> Quoting Serge Hallyn ([email protected]):
> > >>>> Quoting Gao feng ([email protected]):
> > >>>>> On 05/07/2013 10:20 AM, Gao feng wrote:
>
> > In my option, the audit rules(inode, tree_list, filter) , some of audit
> > controller related resources(enabled,pid,portid...) and skb queue, audit
> > netlink sockets,kauditd thread should be per-userns. The audit user message
> > which generated by the user in container should be per-userns too.
> >
> > Since netns is not implemented as a hierarchy, and the network related
> > resources are not global. so network related audit message should be per-userns too.
> >
> > The security related audit message should be send to init user namespace
> > as we discussed before. Maybe tty related audit message should be send
> > to init user namespace too, I have no idea now.
> >
> > The next step, I will post a new patchset which only make the audit user
> > message and the basic audit resource per userns. I think this patchset
> > will easy to be reviewed and accepted, And will not influence the host.
> > This patchset contains the below patches:
>
> I think this would be easier for us do from a certification and
> doumentation PoV if we had an audit namespace, not tied to the user
> namespace. creating a new audit namespace should require
> CAP_AUDIT_CONTROL in the user namespace which created the current audit
> namespace.
>
> Does that make sense? I don't mind messages staying completely inside
> the current namespace, but that means we can't give unpriv users (even
> if they have priv in their user namespace) a new audit namespace...
I think that makes sense.
One of the goals for user namespace is to ensure that unprivileged users
can play with their environment without the risk of setuid-root apps on
the host being tricked by the new environment. This makes tying the
audit ns to the user ns trickier.
-serge