namespaces: log namespaces per task
Subsystems (11)
v7 cover namespaces: log namespaces per task
The purpose is to track namespace instances in use by logged processes from the perspective of init_*_ns by logging the namespace IDs (namespace device ID and namespace inode).
1/10 exposes proc's ns entries structure which lists a number of useful operations per namespace type for other subsystems to use.
2/10 creates and switches to a dedicated inode pool for the namespace filesystem.
3/10 add the nsfs device ID to ns_common for each namespace instance for quick access.
4/10 provides an example of usage for audit_log_task_info() which is used by syscall audits, among others.
Proposed output format:
This differs slightly from Aristeu's patch because of the label conflict with "pid=" due to including it in existing records rather than it being a seperate record. "pid=" here is the target pid for a potentially unactivated task for which the nsproxy has been created. It has now returned to being a seperate record. The nsfs device major/minor are listed in hexadecimal and namespace IDs are the ns inode.
type=NS_INFO msg=audit(1408577535.306:82): pid=310 dev=00:03 netns=7 utsns=3 ipcns=4 pidns=1 userns=2 mntns=5
5/10 change audit startup from __initcall to subsys_initcall to get it started earlier to be able to receive initial namespace log messages.
6/10 tracks the creation and deletion of namespaces, listing the type of namespace instance, nsfs device ID, related namespace id if there is one and the newly minted namespace ID.
Proposed output format for initial namespace creation:
type=AUDIT_NS_INIT_UTS msg=audit(1431115986.147:5): dev=00:03 old_utsns=(none) utsns=2 res=1 type=AUDIT_NS_INIT_USER msg=audit(1431115986.148:6): dev=00:03 old_userns=(none) userns=3 res=1 type=AUDIT_NS_INIT_PID msg=audit(1431115986.149:7): dev=00:03 old_pidns=(none) pidns=4 res=1 type=AUDIT_NS_INIT_MNT msg=audit(1431115986.150:8): dev=00:00 old_mntns=(none) mntns=5 res=1 type=AUDIT_NS_INIT_IPC msg=audit(1431115986.151:9): dev=00:03 old_ipcns=(none) ipcns=1 res=1 type=AUDIT_NS_INIT_NET msg=audit(1431115985.500:10): dev=00:03 old_netns=(none) netns=7 res=1
And a CLONE action would result in:
type=AUDIT_NS_INIT_NET msg=audit(1408577535.306:81): dev=00:03 old_netns=7 netns=8 res=1
While deleting a namespace would result in:
type=AUDIT_NS_DEL_MNT msg=audit(1431116003.205:534): dev=00:03 mntns=8 res=1
7/10 accepts a PID from userspace and requests logging an AUDIT_NS_INFO record type (CAP_AUDIT_CONTROL required).
8/10 adds auditing on creation of namespace(s) in fork for unshare(2) and clone(2), adding the CLONE_NEW_*ALL macro.
9/10 adds auditing a change of namespace on setns(2).
type=AUDIT_NS_SET_NET msg=audit(1408577535.306:81): dev=00:03 old_netns=7 netns=8 res=1
10/10 attaches a AUDIT_NS_INFO record to AUDIT_VIRT_CONTROL records (CAP_AUDIT_WRITE required).
v6 -> v7:
Added sys_unshare to the sys_clone patch.
Combined the CLONE_NEW_*_ALL macro and audit clone and unshare patches. Rebased on Al Viro's NSFS from v3.19-rc1 adding nsfs device ID to ns_common. Create and switch to an nsfs inode db.
Switch AUDIT_NS_{INIT,DEL,SET}_* to auxiliary records.
Fix NULL dereference bug in AUDIT_NS_INFO call from AUDIT_VIRT_CONTROL type. Remove call for audit_log_common_recv_msg.
Only emit info, init, del, set messages on audit_enabled.
v5 -> v6:
Switch to using namespace ID based on namespace proc inode minus base offset Added proc device ID to qualify proc inode reference
Eliminate exposed /proc interface
v4 -> v5:
Clean up prototypes for dependencies on CONFIG_NAMESPACES. Add AUDIT_NS_INFO record type to AUDIT_VIRT_CONTROL record. Log AUDIT_NS_INFO with PID.
Move /proc/<pid>/ns_* patches to end of patchset to deprecate them. Log on changing ns (setns).
Log on creating new namespaces when forking.
Added a macro for CLONE_NEW*.
v3 -> v4:
Seperate out the NS_INFO message from the SYSCALL message. Moved audit_log_namespace_info() out of audit_log_task_info(). Use a seperate message type per namespace type for each of INIT/DEL. Make ns= easier to search across NS_INFO and NS_INIT/DEL_XXX msg types. Add /proc/<pid>/ns/ documentation.
Fix dynamic initial ns logging.
v2 -> v3:
Use atomic64_t in ns_serial to simplify it.
Avoid funciton duplication in proc, keying on dentry. Squash down audit patch to avoid rcu sleep issues. Add tracking for creation and deletion of namespace instances.
v1 -> v2:
Avoid rollover by switching from an int to a long long. Change rollover behaviour from simply avoiding zero to raising a BUG. Expose serial numbers in /proc/<pid>/ns/*_snum.
Expose ns_entries and use it in audit.
Notes:
As for CAP_AUDIT_READ, a patchset has been accepted upstream to check capabilities of userspace processes that try to join netlink broadcast groups.
This set does not try to solve the non-init namespace audit messages and auditd problem yet. That will come later, likely with additional auditd instances running in another namespace with a limited ability to influence the master auditd. I echo Eric B's idea that messages destined for different namespaces would have to be tailored for that namespace with references that make sense (such as the right pid number reported to that pid namespace, and not leaking info about parents or peers).
Questions:
Is there a way to link serial numbers of namespaces involved in migration of a container to another kernel? It sounds like what is needed is a part of a mangement application that is able to pull the audit records from constituent hosts to build an audit trail of a container.
Do any additional events need this information?
Does this present any problematic information leaks? Only CAP_AUDIT_CONTROL (and now CAP_AUDIT_READ) in init_user_ns can get to this information in the init namespace at the moment from audit.
Richard Guy Briggs (10):
namespaces: expose ns_entries
nsfs: switch to dedicated inode pool
nsfs: add nsfs device ID to ns_common
audit: log namespace ID numbers
audit: initialize at subsystem time rather than device time
audit: log creation and deletion of namespace instances
audit: dump namespace IDs for pid on receipt of AUDIT_NS_INFO
fork: audit on creation of new namespace(s) with clone and unshare
audit: log on switching namespace (setns)
audit: emit AUDIT_NS_INFO record with AUDIT_VIRT_CONTROL record
fs/namespace.c | 15 +++ fs/nsfs.c | 65 ++++++++++++++ fs/proc/internal.h | 2 + fs/proc/namespaces.c | 2 +- include/linux/audit.h | 27 ++++++ include/linux/ns_common.h | 1 + include/linux/proc_ns.h | 22 ++--- include/uapi/linux/audit.h | 21 +++++ include/uapi/linux/sched.h | 6 ++ init/version.c | 2 +- ipc/msgutil.c | 2 +- ipc/namespace.c | 13 +++ kernel/audit.c | 180 +++++++++++++++++++++++++++++++++++++- kernel/auditsc.c | 2 + kernel/fork.c | 13 ++- kernel/nsproxy.c | 2 + kernel/pid.c | 2 +- kernel/pid_namespace.c | 13 +++ kernel/user.c | 2 +- kernel/user_namespace.c | 13 +++ kernel/utsname.c | 12 +++ net/core/net_namespace.c | 13 +++ security/integrity/ima/ima_api.c | 2 + 23 files changed, 410 insertions(+), 22 deletions(-)
PATCH v7 1/10 namespaces: expose ns_entries
Expose ns_entries so subsystems other than proc can use this set of namespace operations.
--- fs/proc/namespaces.c | 2 +- include/linux/proc_ns.h | 1 + 2 files changed, 2 insertions(+), 1 deletions(-)
fs/proc/namespaces.c +1 -1
@@ -11,7 +11,7 @@#include "internal.h" -static const struct proc_ns_operations *ns_entries[] = { +const struct proc_ns_operations *ns_entries[] = { #ifdef CONFIG_NET_NS &netns_operations, #endif
include/linux/proc_ns.h +1 -0
@@ -24,6 +24,7 @@ extern const struct proc_ns_operations ipcns_operations;extern const struct proc_ns_operations pidns_operations;extern const struct proc_ns_operations userns_operations;extern const struct proc_ns_operations mntns_operations; +extern const struct proc_ns_operations *ns_entries[];/* * We always define these enumerators
Signature · 1 line
1.7.1
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH v7 1/10 namespaces: expose ns_entries
Expose ns_entries so subsystems other than proc can use this set of namespace operations.
--- fs/proc/namespaces.c | 2 +- include/linux/proc_ns.h | 1 + 2 files changed, 2 insertions(+), 1 deletions(-)
fs/proc/namespaces.c +1 -1
@@ -11,7 +11,7 @@#include "internal.h" -static const struct proc_ns_operations *ns_entries[] = { +const struct proc_ns_operations *ns_entries[] = { #ifdef CONFIG_NET_NS &netns_operations, #endif
include/linux/proc_ns.h +1 -0
@@ -24,6 +24,7 @@ extern const struct proc_ns_operations ipcns_operations;extern const struct proc_ns_operations pidns_operations;extern const struct proc_ns_operations userns_operations;extern const struct proc_ns_operations mntns_operations; +extern const struct proc_ns_operations *ns_entries[];/* * We always define these enumerators
Signature · 1 line
1.7.1
PATCH v7 2/10 nsfs: switch to dedicated inode pool
In reply to a message not in the archiveInstead of borrowing proc's inode pool and starting at a custom offset, give nsfs its own dedicated inode pool without an offset.
--- fs/nsfs.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ fs/proc/internal.h | 2 ++ include/linux/proc_ns.h | 20 ++++++++------------ init/version.c | 2 +- ipc/msgutil.c | 2 +- kernel/pid.c | 2 +- kernel/user.c | 2 +- 7 files changed, 58 insertions(+), 16 deletions(-)
fs/nsfs.c +44 -0
@@ -159,3 +159,47 @@ void __init nsfs_init(void)panic ("can't set nsfs up\n" ); nsfs_mnt->mnt_sb->s_flags &= ~MS_NOUSER ; } + +static DEFINE_IDA (ns_inum_ida); +static DEFINE_SPINLOCK (ns_inum_lock);/* protects the above */ + +/* +* Return an inode number between PROC_DYNAMIC_FIRST and +* 0xffffffff, or zero on failure. +*/ +int ns_alloc_inum (struct ns_common *ns) +{ +unsigned int i; +int error; + +atomic_long_set (&ns->stashed,0 ); +retry: +if (!ida_pre_get (&ns_inum_ida,GFP_KERNEL )) +return -ENOMEM ; + +spin_lock_irq (&ns_inum_lock); + error =ida_get_new (&ns_inum_ida, &i); +spin_unlock_irq (&ns_inum_lock); +if (error == -EAGAIN ) + goto retry; +else if (error) +return error; + +if (i >UINT_MAX ) { +spin_lock_irq (&ns_inum_lock); +ida_remove (&ns_inum_ida, i); +spin_unlock_irq (&ns_inum_lock); +return -ENOSPC ; + } + ns->inum =NS_DYNAMIC_FIRST + i; +return 0 ; +} + +void ns_free_inum (struct ns_common *ns) +{ +unsigned long flags; +spin_lock_irqsave (&ns_inum_lock, flags); +ida_remove (&ns_inum_ida, ns->inum -NS_DYNAMIC_FIRST ); +spin_unlock_irqrestore (&ns_inum_lock, flags); +} +
fs/proc/internal.h +2 -0
@@ -18,6 +18,8 @@struct ctl_table_header ;struct mempolicy ; +#define PROC_ROOT_INO 1 +/* * This is not completely implemented yet. The idea is to * create an in-memory tree (like the actual /proc filesystem
include/linux/proc_ns.h +8 -12
@@ -30,11 +30,12 @@ extern const struct proc_ns_operations *ns_entries[];* We always define these enumerators */ enum { -PROC_ROOT_INO =1 , -PROC_IPC_INIT_INO =0xEFFFFFFFU , -PROC_UTS_INIT_INO =0xEFFFFFFEU , -PROC_USER_INIT_INO =0xEFFFFFFDU , -PROC_PID_INIT_INO =0xEFFFFFFCU , +NS_NULL_INIT_INO , +NS_IPC_INIT_INO , +NS_UTS_INIT_INO , +NS_USER_INIT_INO , +NS_PID_INIT_INO , +NS_DYNAMIC_FIRST , };#ifdef CONFIG_PROC_FS
@@ -58,13 +59,8 @@ static inline void proc_free_inum(unsigned int inum) {}#endif /* CONFIG_PROC_FS */ -static inline int ns_alloc_inum (struct ns_common *ns) -{ -atomic_long_set (&ns->stashed,0 ); -return proc_alloc_inum (&ns->inum); -} - -#define ns_free_inum (ns) proc_free_inum((ns)->inum) +extern int ns_alloc_inum (struct ns_common *ns); +extern void ns_free_inum (struct ns_common *ns);extern struct file *proc_ns_fget (int fd);#define get_proc_ns (inode) ((struct ns_common *)(inode)->i_private)
init/version.c +1 -1
@@ -35,7 +35,7 @@ struct uts_namespace init_uts_ns = { .domainname = UTS_DOMAINNAME, }, .user_ns = &init_user_ns, - .ns.inum = PROC_UTS_INIT_INO, + .ns.inum = NS_UTS_INIT_INO,#ifdef CONFIG_UTS_NS .ns.ops = &utsns_operations,#endif
ipc/msgutil.c +1 -1
@@ -31,7 +31,7 @@ DEFINE_SPINLOCK(mq_lock);struct ipc_namespace init_ipc_ns = { .count =ATOMIC_INIT (1 ), .user_ns = &init_user_ns, - .ns.inum =PROC_IPC_INIT_INO , + .ns.inum =NS_IPC_INIT_INO , #ifdef CONFIG_IPC_NS .ns.ops = &ipcns_operations, #endif
kernel/pid.c +1 -1
@@ -79,7 +79,7 @@ struct pid_namespace init_pid_ns = { .level = 0, .child_reaper = &init_task, .user_ns = &init_user_ns, - .ns.inum = PROC_PID_INIT_INO, + .ns.inum = NS_PID_INIT_INO,#ifdef CONFIG_PID_NS .ns.ops = &pidns_operations,#endif
kernel/user.c +1 -1
@@ -50,7 +50,7 @@ struct user_namespace init_user_ns = { .count = ATOMIC_INIT(3), .owner = GLOBAL_ROOT_UID, .group = GLOBAL_ROOT_GID, - .ns.inum = PROC_USER_INIT_INO, + .ns.inum = NS_USER_INIT_INO,#ifdef CONFIG_USER_NS .ns.ops = &userns_operations,#endif
Signature · 1 line
1.7.1
PATCH v7 5/10 audit: initialize at subsystem time rather than device time
In reply to a message not in the archiveThe audit subsystem should be initialized a bit earlier so that it is in place in time for initial namespace ID number logging.
--- kernel/audit.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/audit.c +1 -1
@@ -1175,7 +1175,7 @@ static int __init audit_init(void)return 0 ; } -__initcall (audit_init); +subsys_initcall (audit_init);/* Process kernel command-line parameter at boot time. audit=0 or audit=1. */ static int __init audit_enable (char *str)
Signature · 1 line
1.7.1
PATCH v7 9/10 audit: log on switching namespace (setns)
In reply to a message not in the archiveAdded six new audit message types, AUDIT_NS_SET_* and function audit_log_ns_set() to log a switch of namespace.
--- include/linux/audit.h | 5 ++++ include/uapi/linux/audit.h | 6 +++++ kernel/audit.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ kernel/nsproxy.c | 2 + 4 files changed, 64 insertions(+), 0 deletions(-)
include/linux/audit.h +5 -0
@@ -490,6 +490,7 @@ extern void audit_log_ns_info(struct task_struct *tsk);extern void audit_log_ns_init (int type,struct ns_common *old_ns,struct ns_common *ns);extern void audit_log_ns_del (int type,struct ns_common *ns); +extern void audit_log_ns_set (struct ns_common *ns);#else static inline void audit_log_ns_info (struct task_struct *tsk) { }
@@ -498,6 +499,8 @@ static inline void audit_log_ns_init(int type, struct ns_common *old_ns, { }static inline void audit_log_ns_del (int type,struct ns_common *ns) { } +static inline void audit_log_ns_set (struct ns_common *ns) +{ }#endif extern int audit_update_lsm_rules (void );
@@ -562,6 +565,8 @@ static inline void audit_log_ns_init(int type, struct ns_common *old_ns, { }static inline void audit_log_ns_del (int type,struct ns_common *ns) { } +static inline void audit_log_ns_set (struct ns_common *ns) +{ }#define audit_enabled 0#endif /* CONFIG_AUDIT */ static inline void audit_log_string (struct audit_buffer *ab,const char *buf)
include/uapi/linux/audit.h +6 -0
@@ -123,6 +123,12 @@#define AUDIT_NS_DEL_USER 1339/* Record USER namespace instance deletion */ #define AUDIT_NS_DEL_PID 1340/* Record PID namespace instance deletion */ #define AUDIT_NS_DEL_NET 1341/* Record NET namespace instance deletion */ +#define AUDIT_NS_SET_MNT 1342/* Record mount namespace instance deletion */ +#define AUDIT_NS_SET_UTS 1343/* Record UTS namespace instance deletion */ +#define AUDIT_NS_SET_IPC 1344/* Record IPC namespace instance deletion */ +#define AUDIT_NS_SET_USER 1345/* Record USER namespace instance deletion */ +#define AUDIT_NS_SET_PID 1346/* Record PID namespace instance deletion */ +#define AUDIT_NS_SET_NET 1347/* Record NET namespace instance deletion */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */
kernel/audit.c +51 -0
57 lines not on this page · raw message
kernel/nsproxy.c +2 -0
@@ -25,6 +25,7 @@#include <linux/proc_ns.h> #include <linux/file.h> #include <linux/syscalls.h> +#include <linux/audit.h> static struct kmem_cache *nsproxy_cachep;
@@ -246,6 +247,7 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)free_nsproxy (new_nsproxy); goto out; } +audit_log_ns_set (ns);switch_task_namespaces (tsk, new_nsproxy); out:fput (file);
Signature · 1 line
1.7.1
PATCH v7 10/10 audit: emit AUDIT_NS_INFO record with AUDIT_VIRT_CONTROL record
In reply to a message not in the archive--- include/uapi/linux/audit.h | 2 ++ kernel/audit.c | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-)
include/uapi/linux/audit.h +2 -0
@@ -163,6 +163,8 @@#define AUDIT_KERNEL 2000/* Asynchronous audit record. NOT A REQUEST. */ +#define AUDIT_VIRT_CONTROL 2500/* Start, Pause, Stop VM */ +/* Rule flags */ #define AUDIT_FILTER_USER 0x00/* Apply rule to user-generated messages */ #define AUDIT_FILTER_TASK 0x01/* Apply rule at task creation (not syscall) */
kernel/audit.c +2 -0
@@ -930,6 +930,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) }audit_set_portid (ab,NETLINK_CB (skb).portid);audit_log_end (ab); +if (msg_type ==AUDIT_VIRT_CONTROL ) +audit_log_ns_info (current);mutex_lock (&audit_cmd_mutex); }break ;
Signature · 1 line
1.7.1
PATCH v7 2/10 nsfs: switch to dedicated inode pool
In reply to Richard Guy BriggsInstead of borrowing proc's inode pool and starting at a custom offset, give nsfs its own dedicated inode pool without an offset.
--- fs/nsfs.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ fs/proc/internal.h | 2 ++ include/linux/proc_ns.h | 20 ++++++++------------ init/version.c | 2 +- ipc/msgutil.c | 2 +- kernel/pid.c | 2 +- kernel/user.c | 2 +- 7 files changed, 58 insertions(+), 16 deletions(-)
fs/nsfs.c +44 -0
@@ -159,3 +159,47 @@ void __init nsfs_init(void)panic ("can't set nsfs up\n" ); nsfs_mnt->mnt_sb->s_flags &= ~MS_NOUSER ; } + +static DEFINE_IDA (ns_inum_ida); +static DEFINE_SPINLOCK (ns_inum_lock);/* protects the above */ + +/* +* Return an inode number between PROC_DYNAMIC_FIRST and +* 0xffffffff, or zero on failure. +*/ +int ns_alloc_inum (struct ns_common *ns) +{ +unsigned int i; +int error; + +atomic_long_set (&ns->stashed,0 ); +retry: +if (!ida_pre_get (&ns_inum_ida,GFP_KERNEL )) +return -ENOMEM ; + +spin_lock_irq (&ns_inum_lock); + error =ida_get_new (&ns_inum_ida, &i); +spin_unlock_irq (&ns_inum_lock); +if (error == -EAGAIN ) + goto retry; +else if (error) +return error; + +if (i >UINT_MAX ) { +spin_lock_irq (&ns_inum_lock); +ida_remove (&ns_inum_ida, i); +spin_unlock_irq (&ns_inum_lock); +return -ENOSPC ; + } + ns->inum =NS_DYNAMIC_FIRST + i; +return 0 ; +} + +void ns_free_inum (struct ns_common *ns) +{ +unsigned long flags; +spin_lock_irqsave (&ns_inum_lock, flags); +ida_remove (&ns_inum_ida, ns->inum -NS_DYNAMIC_FIRST ); +spin_unlock_irqrestore (&ns_inum_lock, flags); +} +
fs/proc/internal.h +2 -0
@@ -18,6 +18,8 @@struct ctl_table_header ;struct mempolicy ; +#define PROC_ROOT_INO 1 +/* * This is not completely implemented yet. The idea is to * create an in-memory tree (like the actual /proc filesystem
include/linux/proc_ns.h +8 -12
@@ -30,11 +30,12 @@ extern const struct proc_ns_operations *ns_entries[];* We always define these enumerators */ enum { -PROC_ROOT_INO =1 , -PROC_IPC_INIT_INO =0xEFFFFFFFU , -PROC_UTS_INIT_INO =0xEFFFFFFEU , -PROC_USER_INIT_INO =0xEFFFFFFDU , -PROC_PID_INIT_INO =0xEFFFFFFCU , +NS_NULL_INIT_INO , +NS_IPC_INIT_INO , +NS_UTS_INIT_INO , +NS_USER_INIT_INO , +NS_PID_INIT_INO , +NS_DYNAMIC_FIRST , };#ifdef CONFIG_PROC_FS
@@ -58,13 +59,8 @@ static inline void proc_free_inum(unsigned int inum) {}#endif /* CONFIG_PROC_FS */ -static inline int ns_alloc_inum (struct ns_common *ns) -{ -atomic_long_set (&ns->stashed,0 ); -return proc_alloc_inum (&ns->inum); -} - -#define ns_free_inum (ns) proc_free_inum((ns)->inum) +extern int ns_alloc_inum (struct ns_common *ns); +extern void ns_free_inum (struct ns_common *ns);extern struct file *proc_ns_fget (int fd);#define get_proc_ns (inode) ((struct ns_common *)(inode)->i_private)
init/version.c +1 -1
@@ -35,7 +35,7 @@ struct uts_namespace init_uts_ns = { .domainname = UTS_DOMAINNAME, }, .user_ns = &init_user_ns, - .ns.inum = PROC_UTS_INIT_INO, + .ns.inum = NS_UTS_INIT_INO,#ifdef CONFIG_UTS_NS .ns.ops = &utsns_operations,#endif
ipc/msgutil.c +1 -1
@@ -31,7 +31,7 @@ DEFINE_SPINLOCK(mq_lock);struct ipc_namespace init_ipc_ns = { .count =ATOMIC_INIT (1 ), .user_ns = &init_user_ns, - .ns.inum =PROC_IPC_INIT_INO , + .ns.inum =NS_IPC_INIT_INO , #ifdef CONFIG_IPC_NS .ns.ops = &ipcns_operations, #endif
kernel/pid.c +1 -1
@@ -79,7 +79,7 @@ struct pid_namespace init_pid_ns = { .level = 0, .child_reaper = &init_task, .user_ns = &init_user_ns, - .ns.inum = PROC_PID_INIT_INO, + .ns.inum = NS_PID_INIT_INO,#ifdef CONFIG_PID_NS .ns.ops = &pidns_operations,#endif
kernel/user.c +1 -1
@@ -50,7 +50,7 @@ struct user_namespace init_user_ns = { .count = ATOMIC_INIT(3), .owner = GLOBAL_ROOT_UID, .group = GLOBAL_ROOT_GID, - .ns.inum = PROC_USER_INIT_INO, + .ns.inum = NS_USER_INIT_INO,#ifdef CONFIG_USER_NS .ns.ops = &userns_operations,#endif
Signature · 1 line
1.7.1
PATCH v7 3/10 nsfs: add nsfs device ID to ns_common
In reply to Richard Guy BriggsFor speed and convenience of look-up, the nsfs device ID is looked up for the first instance of a type of namespace, then copied to others of the same type as they are spawned.
--- fs/namespace.c | 2 ++ fs/nsfs.c | 21 +++++++++++++++++++++ include/linux/ns_common.h | 1 + include/linux/proc_ns.h | 1 + ipc/namespace.c | 1 + kernel/pid_namespace.c | 1 + kernel/user_namespace.c | 1 + kernel/utsname.c | 1 + net/core/net_namespace.c | 2 ++ 9 files changed, 31 insertions(+), 0 deletions(-)
fs/namespace.c +2 -0
@@ -2698,6 +2698,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, old = ns->root; new_ns =alloc_mnt_ns (user_ns); + new_ns->ns.dev = ns->ns.dev;if (IS_ERR (new_ns))return new_ns;
@@ -2762,6 +2763,7 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)struct mount *mnt =real_mount (m); mnt->mnt_ns = new_ns; new_ns->root = mnt; + new_ns->ns.dev =nsfs_dev ();list_add (&mnt->mnt_list, &new_ns->list); }else {mntput (m);
fs/nsfs.c +21 -0
@@ -4,6 +4,10 @@#include <linux/proc_ns.h> #include <linux/magic.h> #include <linux/ktime.h> +#include <linux/init_task.h> +#include <linux/utsname.h> +#include <linux/pid_namespace.h> +#include <linux/ipc_namespace.h> static struct vfsmount *nsfs_mnt;
@@ -158,6 +162,23 @@ void __init nsfs_init(void)if (IS_ERR (nsfs_mnt))panic ("can't set nsfs up\n" ); nsfs_mnt->mnt_sb->s_flags &= ~MS_NOUSER ; + init_ipc_ns.ns.dev = init_uts_ns.ns.dev = init_pid_ns.ns.dev + = init_user_ns.ns.dev =nsfs_dev (); +} + +dev_t nsfs_dev (void ) +{ +dev_t dev; + +void nssb_to_dev (struct super_block *sb,void *arg){ +dev_t *dev = arg; + +if (sb->s_magic ==NSFS_MAGIC ) + *dev = sb->s_dev; + } + +iterate_supers (nssb_to_dev, (void *)&dev); +return dev; }static DEFINE_IDA (ns_inum_ida);
include/linux/ns_common.h +1 -0
@@ -7,6 +7,7 @@ struct ns_common {atomic_long_t stashed;const struct proc_ns_operations *ops;unsigned int inum; + dev_t dev; };#endif
include/linux/proc_ns.h +1 -0
@@ -71,4 +71,5 @@ extern int ns_get_name(char *buf, size_t size, struct task_struct *task, const struct proc_ns_operations *ns_ops);extern void nsfs_init (void ); +extern dev_t nsfs_dev (void );#endif /* _LINUX_PROC_NS_H */
ipc/namespace.c +1 -0
@@ -31,6 +31,7 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,kfree (ns);return ERR_PTR (err); } + ns->ns.dev = old_ns->ns.dev; ns->ns.ops = &ipcns_operations;atomic_set (&ns->count,1 );
kernel/pid_namespace.c +1 -0
@@ -108,6 +108,7 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns err =ns_alloc_inum (&ns->ns);if (err) goto out_free_map; + ns->ns.dev = parent_pid_ns->ns.dev; ns->ns.ops = &pidns_operations;kref_init (&ns->kref);
kernel/user_namespace.c +1 -0
@@ -92,6 +92,7 @@ int create_user_ns(struct cred *new)kmem_cache_free (user_ns_cachep, ns);return ret; } + ns->ns.dev = parent_ns->ns.dev; ns->ns.ops = &userns_operations;atomic_set (&ns->count,1 );
kernel/utsname.c +1 -0
@@ -48,6 +48,7 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,return ERR_PTR (err); } + ns->ns.dev = old_ns->ns.dev; ns->ns.ops = &utsns_operations;down_read (&uts_sem);
net/core/net_namespace.c +2 -0
@@ -332,6 +332,7 @@ struct net *copy_net_ns(unsigned long flags,mutex_lock (&net_mutex); rv =setup_net (net, user_ns);if (rv ==0 ) { + net->ns.dev = old_net->ns.dev;rtnl_lock ();list_add_tail_rcu (&net->list, &net_namespace_list);rtnl_unlock ();
@@ -639,6 +640,7 @@ static int __init net_ns_init(void)if (setup_net (&init_net, &init_user_ns))panic ("Could not setup the initial network namespace" ); + init_net.ns.dev =nsfs_dev ();rtnl_lock ();list_add_tail_rcu (&init_net.list, &net_namespace_list);rtnl_unlock ();
Signature · 1 line
1.7.1
PATCH v7 4/10 audit: log namespace ID numbers
In reply to Richard Guy BriggsLog the namespace identifiers (nsfs device ID and inode) of a task in a new record type (1329) (usually accompanies audit_log_task_info() type=SYSCALL record) which is used by syscall audits, among others..
Idea first presented:
https://www.redhat.com/archives/linux-audit/2013-March/msg00020.html
Typical output format would look something like:
type=NS_INFO msg=audit(1408577535.306:82): pid=374 dev=00:03 netns=7 utsns=2 ipcns=1 pidns=4 userns=3 mntns=5
--- include/linux/audit.h | 8 ++++++++ include/uapi/linux/audit.h | 1 + kernel/audit.c | 35 +++++++++++++++++++++++++++++++++++ kernel/auditsc.c | 2 ++ security/integrity/ima/ima_api.c | 2 ++ 5 files changed, 48 insertions(+), 0 deletions(-)
include/linux/audit.h +8 -0
@@ -484,6 +484,12 @@ static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid)extern int audit_log_task_context (struct audit_buffer *ab);extern void audit_log_task_info (struct audit_buffer *ab,struct task_struct *tsk); +#ifdef CONFIG_NAMESPACES +extern void audit_log_ns_info (struct task_struct *tsk); +#else +static inline void audit_log_ns_info (struct task_struct *tsk) +{ } +#endif extern int audit_update_lsm_rules (void );
@@ -540,6 +546,8 @@ static inline int audit_log_task_context(struct audit_buffer *ab)static inline void audit_log_task_info (struct audit_buffer *ab,struct task_struct *tsk) { } +static inline void audit_log_ns_info (struct task_struct *tsk) +{ }#define audit_enabled 0#endif /* CONFIG_AUDIT */ static inline void audit_log_string (struct audit_buffer *ab,const char *buf)
include/uapi/linux/audit.h +1 -0
@@ -110,6 +110,7 @@#define AUDIT_SECCOMP 1326/* Secure Computing event */ #define AUDIT_PROCTITLE 1327/* Proctitle emit event */ #define AUDIT_FEATURE_CHANGE 1328/* audit log listing feature changes */ +#define AUDIT_NS_INFO 1329/* Record process namespace IDs */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */
kernel/audit.c +35 -0
@@ -65,6 +65,7 @@#include <linux/freezer.h> #include <linux/tty.h> #include <linux/pid_namespace.h> +#include <linux/proc_ns.h> #include <net/netns/generic.h> #include "audit.h"
@@ -1642,6 +1643,38 @@ void audit_log_session_info(struct audit_buffer *ab)audit_log_format (ab," auid=%u ses=%u" , auid, sessionid); } +#ifdef CONFIG_NAMESPACES +void audit_log_ns_info (struct task_struct *tsk) +{ +const struct proc_ns_operations **entry; +bool end = false; +struct audit_buffer *ab; +int devprinted =0 ; + +if (!audit_enabled || !tsk) +return ; + ab =audit_log_start (current->audit_context,GFP_KERNEL , +AUDIT_NS_INFO ); +if (!ab) +return ; +audit_log_format (ab,"pid=%d" ,task_pid_nr (tsk)); +for (entry = ns_entries; !end; entry++) { +struct ns_common *ns = (*entry)->get (tsk); + +if (!devprinted) { +audit_log_format (ab," dev=%02x:%02x" ,MAJOR (ns->dev), +MINOR (ns->dev)); + devprinted =1 ; + } +audit_log_format (ab," %sns=%d" , (*entry)->name, + ns->inum); + (*entry)->put (ns); + end = (*entry)->type ==CLONE_NEWNS ; + } +audit_log_end (ab); +} +#endif /* CONFIG_NAMESPACES */ +void audit_log_key (struct audit_buffer *ab,char *key) {audit_log_format (ab," key=" );
@@ -1913,6 +1946,8 @@ void audit_log_link_denied(const char *operation, struct path *link)audit_log_format (ab," res=0" );audit_log_end (ab); +audit_log_ns_info (current); +/* Generate AUDIT_PATH record with object. */ name->type =AUDIT_TYPE_NORMAL ;audit_copy_inode (name, link->dentry, link->dentry->d_inode);
kernel/auditsc.c +2 -0
@@ -1355,6 +1355,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *tsaudit_log_key (ab, context->filterkey);audit_log_end (ab); +audit_log_ns_info (tsk); +for (aux = context->aux; aux; aux = aux->next) { ab =audit_log_start (context,GFP_KERNEL , aux->type);
security/integrity/ima/ima_api.c +2 -0
@@ -317,6 +317,8 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,audit_log_task_info (ab, current);audit_log_end (ab); +audit_log_ns_info (current); + iint->flags |=IMA_AUDITED ; }
Signature · 1 line
1.7.1
PATCH v7 5/10 audit: initialize at subsystem time rather than device time
In reply to Richard Guy BriggsThe audit subsystem should be initialized a bit earlier so that it is in place in time for initial namespace ID number logging.
--- kernel/audit.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/audit.c +1 -1
@@ -1175,7 +1175,7 @@ static int __init audit_init(void)return 0 ; } -__initcall (audit_init); +subsys_initcall (audit_init);/* Process kernel command-line parameter at boot time. audit=0 or audit=1. */ static int __init audit_enable (char *str)
Signature · 1 line
1.7.1
PATCH v7 6/10 audit: log creation and deletion of namespace instances
In reply to Richard Guy BriggsLog the creation and deletion of namespace instances in all 6 types of namespaces.
Twelve new audit message types have been introduced:
AUDIT_NS_INIT_MNT 1330 /* Record mount namespace instance creation */ AUDIT_NS_INIT_UTS 1331 /* Record UTS namespace instance creation */ AUDIT_NS_INIT_IPC 1332 /* Record IPC namespace instance creation */ AUDIT_NS_INIT_USER 1333 /* Record USER namespace instance creation */ AUDIT_NS_INIT_PID 1334 /* Record PID namespace instance creation */ AUDIT_NS_INIT_NET 1335 /* Record NET namespace instance creation */ AUDIT_NS_DEL_MNT 1336 /* Record mount namespace instance deletion */ AUDIT_NS_DEL_UTS 1337 /* Record UTS namespace instance deletion */ AUDIT_NS_DEL_IPC 1338 /* Record IPC namespace instance deletion */ AUDIT_NS_DEL_USER 1339 /* Record USER namespace instance deletion */ AUDIT_NS_DEL_PID 1340 /* Record PID namespace instance deletion */ AUDIT_NS_DEL_NET 1341 /* Record NET namespace instance deletion */
As suggested by Eric Paris, there are 12 message types, one for each of creation and deletion, one for each type of namespace so that text searches are easier in conjunction with the AUDIT_NS_INFO message type, being able to search for all records such as "netns=7 " and to avoid fields disappearing per message type to make ausearch more efficient.
A typical startup would look roughly like:
type=AUDIT_NS_INIT_UTS msg=audit(1408577534.868:5): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_utsns=(none) utsns=2 res=1 type=AUDIT_NS_INIT_USER msg=audit(1408577534.868:6): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_userns=(none) userns=3 res=1 type=AUDIT_NS_INIT_PID msg=audit(1408577534.868:7): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_pidns=(none) pidns=4 res=1 type=AUDIT_NS_INIT_MNT msg=audit(1408577534.868:8): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_mntns=(none) mntns=5 res=1 type=AUDIT_NS_INIT_IPC msg=audit(1408577534.868:9): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_ipcns=(none) ipcns=1 res=1 type=AUDIT_NS_INIT_NET msg=audit(1408577533.500:10): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_netns=(none) netns=7 res=1
And a CLONE action would result in:
type=type=AUDIT_NS_INIT_NET msg=audit(1408577535.306:81): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 dev=00:03 old_netns=7 netns=8 res=1
While deleting a namespace would result in:
type=type=AUDIT_NS_DEL_MNT msg=audit(1408577552.221:85): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 dev=00:03 mntns=5 res=1
If not "(none)", old_XXXns lists the namespace from which it was cloned.
--- fs/namespace.c | 13 ++++++++ include/linux/audit.h | 14 ++++++++ include/uapi/linux/audit.h | 12 +++++++ ipc/namespace.c | 12 +++++++ kernel/audit.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ kernel/pid_namespace.c | 12 +++++++ kernel/user_namespace.c | 12 +++++++ kernel/utsname.c | 11 ++++++ net/core/net_namespace.c | 11 ++++++ 9 files changed, 170 insertions(+), 0 deletions(-)
fs/namespace.c +13 -0
@@ -24,6 +24,7 @@#include <linux/magic.h> #include <linux/bootmem.h> #include <linux/task_work.h> +#include <linux/audit.h> #include "pnode.h" #include "internal.h"
@@ -2640,6 +2641,7 @@ dput_out:static void free_mnt_ns (struct mnt_namespace *ns) { +audit_log_ns_del (AUDIT_NS_DEL_MNT , &ns->ns);ns_free_inum (&ns->ns);put_user_ns (ns->user_ns);kfree (ns);
@@ -2701,6 +2703,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, new_ns->ns.dev = ns->ns.dev;if (IS_ERR (new_ns))return new_ns; +audit_log_ns_init (AUDIT_NS_INIT_MNT , &ns->ns, &new_ns->ns);namespace_lock ();/* First pass: copy the tree topology */
@@ -3013,6 +3016,16 @@ static void __init init_mount_tree(void)set_fs_root (current->fs, &root); } +/* log the ID of init mnt namespace after audit service starts */ +static int __init mnt_ns_init_log (void ) +{ +struct mnt_namespace *init_mnt_ns = init_task.nsproxy->mnt_ns; + +audit_log_ns_init (AUDIT_NS_INIT_MNT ,0 , &init_mnt_ns->ns); +return 0 ; +} +late_initcall (mnt_ns_init_log); +void __init mnt_init (void ) {unsigned u;
include/linux/audit.h +14 -0
@@ -26,6 +26,7 @@#include <linux/sched.h> #include <linux/ptrace.h> #include <uapi/linux/audit.h> +#include <linux/proc_ns.h> struct audit_sig_info {uid_t uid;
@@ -486,9 +487,17 @@ extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk);#ifdef CONFIG_NAMESPACES extern void audit_log_ns_info (struct task_struct *tsk); +extern void audit_log_ns_init (int type,struct ns_common *old_ns, +struct ns_common *ns); +extern void audit_log_ns_del (int type,struct ns_common *ns);#else static inline void audit_log_ns_info (struct task_struct *tsk) { } +static inline void audit_log_ns_init (int type,struct ns_common *old_ns, +struct ns_common *ns) +{ } +static inline void audit_log_ns_del (int type,struct ns_common *ns) +{ }#endif extern int audit_update_lsm_rules (void );
@@ -548,6 +557,11 @@ static inline void audit_log_task_info(struct audit_buffer *ab, { }static inline void audit_log_ns_info (struct task_struct *tsk) { } +static inline void audit_log_ns_init (int type,struct ns_common *old_ns, +struct ns_common *ns) +{ } +static inline void audit_log_ns_del (int type,struct ns_common *ns) +{ }#define audit_enabled 0#endif /* CONFIG_AUDIT */ static inline void audit_log_string (struct audit_buffer *ab,const char *buf)
include/uapi/linux/audit.h +12 -0
@@ -111,6 +111,18 @@#define AUDIT_PROCTITLE 1327/* Proctitle emit event */ #define AUDIT_FEATURE_CHANGE 1328/* audit log listing feature changes */ #define AUDIT_NS_INFO 1329/* Record process namespace IDs */ +#define AUDIT_NS_INIT_MNT 1330/* Record mount namespace instance creation */ +#define AUDIT_NS_INIT_UTS 1331/* Record UTS namespace instance creation */ +#define AUDIT_NS_INIT_IPC 1332/* Record IPC namespace instance creation */ +#define AUDIT_NS_INIT_USER 1333/* Record USER namespace instance creation */ +#define AUDIT_NS_INIT_PID 1334/* Record PID namespace instance creation */ +#define AUDIT_NS_INIT_NET 1335/* Record NET namespace instance creation */ +#define AUDIT_NS_DEL_MNT 1336/* Record mount namespace instance deletion */ +#define AUDIT_NS_DEL_UTS 1337/* Record UTS namespace instance deletion */ +#define AUDIT_NS_DEL_IPC 1338/* Record IPC namespace instance deletion */ +#define AUDIT_NS_DEL_USER 1339/* Record USER namespace instance deletion */ +#define AUDIT_NS_DEL_PID 1340/* Record PID namespace instance deletion */ +#define AUDIT_NS_DEL_NET 1341/* Record NET namespace instance deletion */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */
ipc/namespace.c +12 -0
@@ -13,6 +13,7 @@#include <linux/mount.h> #include <linux/user_namespace.h> #include <linux/proc_ns.h> +#include <linux/audit.h> #include "util.h"
@@ -43,6 +44,8 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns, }atomic_inc (&nr_ipc_ns); +audit_log_ns_init (AUDIT_NS_INIT_IPC , &old_ns->ns, &ns->ns); +sem_init_ns (ns);msg_init_ns (ns);shm_init_ns (ns);
@@ -99,6 +102,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)atomic_dec (&nr_ipc_ns);put_user_ns (ns->user_ns); +audit_log_ns_del (AUDIT_NS_DEL_IPC , &ns->ns);ns_free_inum (&ns->ns);kfree (ns); }
@@ -174,3 +178,11 @@ const struct proc_ns_operations ipcns_operations = { .put = ipcns_put, .install = ipcns_install, }; + +/* log the ID of init IPC namespace after audit service starts */ +static int __init ipc_namespaces_init (void ) +{ +audit_log_ns_init (AUDIT_NS_INIT_IPC ,0 , &init_ipc_ns.ns); +return 0 ; +} +late_initcall (ipc_namespaces_init);
kernel/audit.c +73 -0
79 lines not on this page · raw message
kernel/pid_namespace.c +12 -0
@@ -18,6 +18,7 @@#include <linux/proc_ns.h> #include <linux/reboot.h> #include <linux/export.h> +#include <linux/audit.h> struct pid_cache {int nr_ids;
@@ -111,6 +112,8 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns ns->ns.dev = parent_pid_ns->ns.dev; ns->ns.ops = &pidns_operations; +audit_log_ns_init (AUDIT_NS_INIT_PID , &parent_pid_ns->ns, &ns->ns); +kref_init (&ns->kref); ns->level = level; ns->parent =get_pid_ns (parent_pid_ns);
@@ -144,6 +147,7 @@ static void destroy_pid_namespace(struct pid_namespace *ns) {int i; +audit_log_ns_del (AUDIT_NS_DEL_PID , &ns->ns);ns_free_inum (&ns->ns);for (i =0 ; i <PIDMAP_ENTRIES ; i++)kfree (ns->pidmap[i].page);
@@ -408,3 +412,11 @@ static __init int pid_namespaces_init(void) }__initcall (pid_namespaces_init); + +/* log the ID of init PID namespace after audit service starts */ +static __init int pid_namespaces_late_init (void ) +{ +audit_log_ns_init (AUDIT_NS_INIT_PID ,0 , &init_pid_ns.ns); +return 0 ; +} +late_initcall (pid_namespaces_late_init);
kernel/user_namespace.c +12 -0
@@ -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 ;static DEFINE_MUTEX (userns_state_mutex);
@@ -95,6 +96,8 @@ int create_user_ns(struct cred *new) ns->ns.dev = parent_ns->ns.dev; ns->ns.ops = &userns_operations; +audit_log_ns_init (AUDIT_NS_INIT_USER , &parent_ns->ns, &ns->ns); +atomic_set (&ns->count,1 );/* Leave the new->user_ns reference with the new user namespace. */ ns->parent = parent_ns;
@@ -144,6 +147,7 @@ void free_user_ns(struct user_namespace *ns)#ifdef CONFIG_PERSISTENT_KEYRINGS key_put (ns->persistent_keyring_register);#endif +audit_log_ns_del (AUDIT_NS_DEL_USER , &ns->ns);ns_free_inum (&ns->ns);kmem_cache_free (user_ns_cachep, ns); ns = parent;
@@ -1011,3 +1015,11 @@ static __init int user_namespaces_init(void)return 0 ; }subsys_initcall (user_namespaces_init); + +/* log the ID of init user namespace after audit service starts */ +static __init int user_namespaces_late_init (void ) +{ +audit_log_ns_init (AUDIT_NS_INIT_USER ,0 , &init_user_ns.ns); +return 0 ; +} +late_initcall (user_namespaces_late_init);
kernel/utsname.c +11 -0
@@ -16,6 +16,7 @@#include <linux/slab.h> #include <linux/user_namespace.h> #include <linux/proc_ns.h> +#include <linux/audit.h> static struct uts_namespace *create_uts_ns (void ) {
@@ -50,6 +51,7 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns, ns->ns.dev = old_ns->ns.dev; ns->ns.ops = &utsns_operations; +audit_log_ns_init (AUDIT_NS_INIT_UTS , &old_ns->ns, &ns->ns);down_read (&uts_sem);memcpy (&ns->name, &old_ns->name,sizeof (ns->name));
@@ -87,6 +89,7 @@ void free_uts_ns(struct kref *kref) ns = container_of(kref, struct uts_namespace, kref);put_user_ns (ns->user_ns); +audit_log_ns_del (AUDIT_NS_DEL_UTS , &ns->ns);ns_free_inum (&ns->ns);kfree (ns); }
@@ -138,3 +141,11 @@ const struct proc_ns_operations utsns_operations = { .put = utsns_put, .install = utsns_install, }; + +/* log the ID of init UTS namespace after audit service starts */ +static int __init uts_namespaces_init (void ) +{ +audit_log_ns_init (AUDIT_NS_INIT_UTS ,0 , &init_uts_ns.ns); +return 0 ; +} +late_initcall (uts_namespaces_init);
net/core/net_namespace.c +11 -0
@@ -21,6 +21,7 @@#include <net/netlink.h> #include <net/net_namespace.h> #include <net/netns/generic.h> +#include <linux/audit.h> /* * Our network namespace constructor/destructor lists
@@ -333,6 +334,7 @@ struct net *copy_net_ns(unsigned long flags, rv =setup_net (net, user_ns);if (rv ==0 ) { net->ns.dev = old_net->ns.dev; +audit_log_ns_init (AUDIT_NS_INIT_NET , &old_net->ns, &net->ns);rtnl_lock ();list_add_tail_rcu (&net->list, &net_namespace_list);rtnl_unlock ();
@@ -483,6 +485,7 @@ static __net_init int net_ns_net_init(struct net *net) static __net_exit void net_ns_net_exit(struct net *net) { +audit_log_ns_del (AUDIT_NS_DEL_NET , &net->ns);ns_free_inum (&net->ns); }
@@ -657,6 +660,14 @@ static int __init net_ns_init(void)pure_initcall (net_ns_init); +/* log the ID of init_net namespace after audit service starts */ +static int __init net_ns_init_log (void ) +{ +audit_log_ns_init (AUDIT_NS_INIT_NET ,0 , &init_net.ns); +return 0 ; +} +late_initcall (net_ns_init_log); +#ifdef CONFIG_NET_NS static int __register_pernet_operations (struct list_head *list,struct pernet_operations *ops)
Signature · 1 line
1.7.1
PATCH v7 7/10 audit: dump namespace IDs for pid on receipt of AUDIT_NS_INFO
In reply to Richard Guy BriggsWhen a task with CAP_AUDIT_CONTROL sends a NETLINK_AUDIT message of type UDIT_NS_INFO with a PID of interest formatted as pid_t as the first and only data, dump the namespace IDs of that task to the audit log.
--- kernel/audit.c | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-)
kernel/audit.c +17 -0
@@ -662,6 +662,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)case AUDIT_TTY_SET :case AUDIT_TRIM :case AUDIT_MAKE_EQUIV : +case AUDIT_NS_INFO :/* Only support auditd and auditctl in initial pid namespace * for now. */ if ((task_active_pid_ns (current) != &init_pid_ns))
@@ -1057,6 +1058,22 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)audit_log_end (ab);break ; } +case AUDIT_NS_INFO : +#ifdef CONFIG_NAMESPACES + { +struct task_struct *tsk; + +rcu_read_lock (); + tsk =find_task_by_vpid (*(pid_t *)data); +rcu_read_unlock (); +if (tsk) +audit_log_ns_info (tsk); +else + err = -EINVAL ; + } +#else /* CONFIG_NAMESPACES */ + err = -EOPNOTSUPP ; +#endif /* CONFIG_NAMESPACES */ default : err = -EINVAL ;break ;
Signature · 1 line
1.7.1
PATCH v7 8/10 fork: audit on creation of new namespace(s) with clone and unshare
In reply to Richard Guy BriggsWhen clone(2) is called to fork a new process or unshare(2) creating one or more namespaces, audit the event to tie the new pid with the namespace IDs.
Added the macro CLONE_NEW_MASK_ALL to refer to all CLONE_NEW* flags.
Cleaned up check_unshare_flags() to make it more readable using this new macro.
--- include/uapi/linux/sched.h | 6 ++++++ kernel/fork.c | 13 +++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-)
include/uapi/linux/sched.h +6 -0
@@ -28,6 +28,12 @@#define CLONE_NEWUSER 0x10000000/* New user namespace */ #define CLONE_NEWPID 0x20000000/* New pid namespace */ #define CLONE_NEWNET 0x40000000/* New network namespace */ +#define CLONE_NEW_MASK_ALL (CLONE_NEWNS \ + | CLONE_NEWUTS \ + | CLONE_NEWIPC \ + | CLONE_NEWUSER \ + | CLONE_NEWPID \ + | CLONE_NEWNET)/* mask of all namespace type flags */ #define CLONE_IO 0x80000000/* Clone io context */ /*
kernel/fork.c +9 -4
@@ -1680,6 +1680,9 @@ long do_fork(unsigned long clone_flags,get_task_struct (p); } +if (unlikely (clone_flags &CLONE_NEW_MASK_ALL )) +audit_log_ns_info (p); +wake_up_new_task (p);/* forking complete and child started to run, tell ptracer */
@@ -1802,10 +1805,9 @@ void __init proc_caches_init(void)*/ static int check_unshare_flags (unsigned long unshare_flags) { -if (unshare_flags & ~(CLONE_THREAD |CLONE_FS |CLONE_NEWNS |CLONE_SIGHAND | -CLONE_VM |CLONE_FILES |CLONE_SYSVSEM | -CLONE_NEWUTS |CLONE_NEWIPC |CLONE_NEWNET | -CLONE_NEWUSER |CLONE_NEWPID )) +if (unshare_flags & ~(CLONE_THREAD |CLONE_FS |CLONE_SIGHAND | +CLONE_VM |CLONE_FILES |CLONE_SYSVSEM | +CLONE_NEW_MASK_ALL ))return -EINVAL ;/* * Not implemented, but pretend it works if there is nothing to
@@ -1964,6 +1966,9 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)commit_creds (new_cred); new_cred =NULL ; } + +if (unshare_flags &CLONE_NEW_MASK_ALL ) +audit_log_ns_info (current); } bad_unshare_cleanup_cred:
Signature · 1 line
1.7.1
PATCH v7 9/10 audit: log on switching namespace (setns)
In reply to Richard Guy BriggsAdded six new audit message types, AUDIT_NS_SET_* and function audit_log_ns_set() to log a switch of namespace.
--- include/linux/audit.h | 5 ++++ include/uapi/linux/audit.h | 6 +++++ kernel/audit.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ kernel/nsproxy.c | 2 + 4 files changed, 64 insertions(+), 0 deletions(-)
include/linux/audit.h +5 -0
@@ -490,6 +490,7 @@ extern void audit_log_ns_info(struct task_struct *tsk);extern void audit_log_ns_init (int type,struct ns_common *old_ns,struct ns_common *ns);extern void audit_log_ns_del (int type,struct ns_common *ns); +extern void audit_log_ns_set (struct ns_common *ns);#else static inline void audit_log_ns_info (struct task_struct *tsk) { }
@@ -498,6 +499,8 @@ static inline void audit_log_ns_init(int type, struct ns_common *old_ns, { }static inline void audit_log_ns_del (int type,struct ns_common *ns) { } +static inline void audit_log_ns_set (struct ns_common *ns) +{ }#endif extern int audit_update_lsm_rules (void );
@@ -562,6 +565,8 @@ static inline void audit_log_ns_init(int type, struct ns_common *old_ns, { }static inline void audit_log_ns_del (int type,struct ns_common *ns) { } +static inline void audit_log_ns_set (struct ns_common *ns) +{ }#define audit_enabled 0#endif /* CONFIG_AUDIT */ static inline void audit_log_string (struct audit_buffer *ab,const char *buf)
include/uapi/linux/audit.h +6 -0
@@ -123,6 +123,12 @@#define AUDIT_NS_DEL_USER 1339/* Record USER namespace instance deletion */ #define AUDIT_NS_DEL_PID 1340/* Record PID namespace instance deletion */ #define AUDIT_NS_DEL_NET 1341/* Record NET namespace instance deletion */ +#define AUDIT_NS_SET_MNT 1342/* Record mount namespace instance deletion */ +#define AUDIT_NS_SET_UTS 1343/* Record UTS namespace instance deletion */ +#define AUDIT_NS_SET_IPC 1344/* Record IPC namespace instance deletion */ +#define AUDIT_NS_SET_USER 1345/* Record USER namespace instance deletion */ +#define AUDIT_NS_SET_PID 1346/* Record PID namespace instance deletion */ +#define AUDIT_NS_SET_NET 1347/* Record NET namespace instance deletion */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */
kernel/audit.c +51 -0
57 lines not on this page · raw message
kernel/nsproxy.c +2 -0
@@ -25,6 +25,7 @@#include <linux/proc_ns.h> #include <linux/file.h> #include <linux/syscalls.h> +#include <linux/audit.h> static struct kmem_cache *nsproxy_cachep;
@@ -246,6 +247,7 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)free_nsproxy (new_nsproxy); goto out; } +audit_log_ns_set (ns);switch_task_namespaces (tsk, new_nsproxy); out:fput (file);
Signature · 1 line
1.7.1
PATCH v7 10/10 audit: emit AUDIT_NS_INFO record with AUDIT_VIRT_CONTROL record
In reply to Richard Guy Briggs--- include/uapi/linux/audit.h | 2 ++ kernel/audit.c | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-)
include/uapi/linux/audit.h +2 -0
@@ -163,6 +163,8 @@#define AUDIT_KERNEL 2000/* Asynchronous audit record. NOT A REQUEST. */ +#define AUDIT_VIRT_CONTROL 2500/* Start, Pause, Stop VM */ +/* Rule flags */ #define AUDIT_FILTER_USER 0x00/* Apply rule to user-generated messages */ #define AUDIT_FILTER_TASK 0x01/* Apply rule at task creation (not syscall) */
kernel/audit.c +2 -0
@@ -930,6 +930,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) }audit_set_portid (ab,NETLINK_CB (skb).portid);audit_log_end (ab); +if (msg_type ==AUDIT_VIRT_CONTROL ) +audit_log_ns_info (current);mutex_lock (&audit_cmd_mutex); }break ;
Signature · 1 line
1.7.1