Commit fd76a74d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'audit-pr-20200803' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit

Pull audit updates from Paul Moore:
 "Aside from some smaller bug fixes, here are the highlights:

   - add a new backlog wait metric to the audit status message, this is
     intended to help admins determine how long processes have been
     waiting for the audit backlog queue to clear

   - generate audit records for nftables configuration changes

   - generate CWD audit records for for the relevant LSM audit records"

* tag 'audit-pr-20200803' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit:
  audit: report audit wait metric in audit status reply
  audit: purge audit_log_string from the intra-kernel audit API
  audit: issue CWD record to accompany LSM_AUDIT_DATA_* records
  audit: use the proper gfp flags in the audit_log_nfcfg() calls
  audit: remove unused !CONFIG_AUDITSYSCALL __audit_inode* stubs
  audit: add gfp parameter to audit_log_nfcfg
  audit: log nftables configuration change events
  audit: Use struct_size() helper in alloc_chunk
parents 49e917de b43870c7
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <uapi/linux/audit.h> #include <uapi/linux/audit.h>
#include <uapi/linux/netfilter/nf_tables.h>
#define AUDIT_INO_UNSET ((unsigned long)-1) #define AUDIT_INO_UNSET ((unsigned long)-1)
#define AUDIT_DEV_UNSET ((dev_t)-1) #define AUDIT_DEV_UNSET ((dev_t)-1)
...@@ -98,6 +99,23 @@ enum audit_nfcfgop { ...@@ -98,6 +99,23 @@ enum audit_nfcfgop {
AUDIT_XT_OP_REGISTER, AUDIT_XT_OP_REGISTER,
AUDIT_XT_OP_REPLACE, AUDIT_XT_OP_REPLACE,
AUDIT_XT_OP_UNREGISTER, AUDIT_XT_OP_UNREGISTER,
AUDIT_NFT_OP_TABLE_REGISTER,
AUDIT_NFT_OP_TABLE_UNREGISTER,
AUDIT_NFT_OP_CHAIN_REGISTER,
AUDIT_NFT_OP_CHAIN_UNREGISTER,
AUDIT_NFT_OP_RULE_REGISTER,
AUDIT_NFT_OP_RULE_UNREGISTER,
AUDIT_NFT_OP_SET_REGISTER,
AUDIT_NFT_OP_SET_UNREGISTER,
AUDIT_NFT_OP_SETELEM_REGISTER,
AUDIT_NFT_OP_SETELEM_UNREGISTER,
AUDIT_NFT_OP_GEN_REGISTER,
AUDIT_NFT_OP_OBJ_REGISTER,
AUDIT_NFT_OP_OBJ_UNREGISTER,
AUDIT_NFT_OP_OBJ_RESET,
AUDIT_NFT_OP_FLOWTABLE_REGISTER,
AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
AUDIT_NFT_OP_INVALID,
}; };
extern int is_audit_feature_set(int which); extern int is_audit_feature_set(int which);
...@@ -274,7 +292,7 @@ extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1, ...@@ -274,7 +292,7 @@ extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
extern void __audit_syscall_exit(int ret_success, long ret_value); extern void __audit_syscall_exit(int ret_success, long ret_value);
extern struct filename *__audit_reusename(const __user char *uptr); extern struct filename *__audit_reusename(const __user char *uptr);
extern void __audit_getname(struct filename *name); extern void __audit_getname(struct filename *name);
extern void __audit_getcwd(void);
extern void __audit_inode(struct filename *name, const struct dentry *dentry, extern void __audit_inode(struct filename *name, const struct dentry *dentry,
unsigned int flags); unsigned int flags);
extern void __audit_file(const struct file *); extern void __audit_file(const struct file *);
...@@ -333,6 +351,11 @@ static inline void audit_getname(struct filename *name) ...@@ -333,6 +351,11 @@ static inline void audit_getname(struct filename *name)
if (unlikely(!audit_dummy_context())) if (unlikely(!audit_dummy_context()))
__audit_getname(name); __audit_getname(name);
} }
static inline void audit_getcwd(void)
{
if (unlikely(audit_context()))
__audit_getcwd();
}
static inline void audit_inode(struct filename *name, static inline void audit_inode(struct filename *name,
const struct dentry *dentry, const struct dentry *dentry,
unsigned int aflags) { unsigned int aflags) {
...@@ -386,7 +409,7 @@ extern void __audit_fanotify(unsigned int response); ...@@ -386,7 +409,7 @@ extern void __audit_fanotify(unsigned int response);
extern void __audit_tk_injoffset(struct timespec64 offset); extern void __audit_tk_injoffset(struct timespec64 offset);
extern void __audit_ntp_log(const struct audit_ntp_data *ad); extern void __audit_ntp_log(const struct audit_ntp_data *ad);
extern void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries, extern void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
enum audit_nfcfgop op); enum audit_nfcfgop op, gfp_t gfp);
static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
{ {
...@@ -524,10 +547,10 @@ static inline void audit_ntp_log(const struct audit_ntp_data *ad) ...@@ -524,10 +547,10 @@ static inline void audit_ntp_log(const struct audit_ntp_data *ad)
static inline void audit_log_nfcfg(const char *name, u8 af, static inline void audit_log_nfcfg(const char *name, u8 af,
unsigned int nentries, unsigned int nentries,
enum audit_nfcfgop op) enum audit_nfcfgop op, gfp_t gfp)
{ {
if (audit_enabled) if (audit_enabled)
__audit_log_nfcfg(name, af, nentries, op); __audit_log_nfcfg(name, af, nentries, op, gfp);
} }
extern int audit_n_rules; extern int audit_n_rules;
...@@ -561,13 +584,7 @@ static inline struct filename *audit_reusename(const __user char *name) ...@@ -561,13 +584,7 @@ static inline struct filename *audit_reusename(const __user char *name)
} }
static inline void audit_getname(struct filename *name) static inline void audit_getname(struct filename *name)
{ } { }
static inline void __audit_inode(struct filename *name, static inline void audit_getcwd(void)
const struct dentry *dentry,
unsigned int flags)
{ }
static inline void __audit_inode_child(struct inode *parent,
const struct dentry *dentry,
const unsigned char type)
{ } { }
static inline void audit_inode(struct filename *name, static inline void audit_inode(struct filename *name,
const struct dentry *dentry, const struct dentry *dentry,
...@@ -665,7 +682,7 @@ static inline void audit_ptrace(struct task_struct *t) ...@@ -665,7 +682,7 @@ static inline void audit_ptrace(struct task_struct *t)
static inline void audit_log_nfcfg(const char *name, u8 af, static inline void audit_log_nfcfg(const char *name, u8 af,
unsigned int nentries, unsigned int nentries,
enum audit_nfcfgop op) enum audit_nfcfgop op, gfp_t gfp)
{ } { }
#define audit_n_rules 0 #define audit_n_rules 0
...@@ -677,9 +694,4 @@ static inline bool audit_loginuid_set(struct task_struct *tsk) ...@@ -677,9 +694,4 @@ static inline bool audit_loginuid_set(struct task_struct *tsk)
return uid_valid(audit_get_loginuid(tsk)); return uid_valid(audit_get_loginuid(tsk));
} }
static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
{
audit_log_n_string(ab, buf, strlen(buf));
}
#endif #endif
...@@ -341,6 +341,7 @@ enum { ...@@ -341,6 +341,7 @@ enum {
#define AUDIT_STATUS_BACKLOG_LIMIT 0x0010 #define AUDIT_STATUS_BACKLOG_LIMIT 0x0010
#define AUDIT_STATUS_BACKLOG_WAIT_TIME 0x0020 #define AUDIT_STATUS_BACKLOG_WAIT_TIME 0x0020
#define AUDIT_STATUS_LOST 0x0040 #define AUDIT_STATUS_LOST 0x0040
#define AUDIT_STATUS_BACKLOG_WAIT_TIME_ACTUAL 0x0080
#define AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT 0x00000001 #define AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT 0x00000001
#define AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME 0x00000002 #define AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME 0x00000002
...@@ -467,6 +468,9 @@ struct audit_status { ...@@ -467,6 +468,9 @@ struct audit_status {
__u32 feature_bitmap; /* bitmap of kernel audit features */ __u32 feature_bitmap; /* bitmap of kernel audit features */
}; };
__u32 backlog_wait_time;/* message queue wait timeout */ __u32 backlog_wait_time;/* message queue wait timeout */
__u32 backlog_wait_time_actual;/* time spent waiting while
* message limit exceeded
*/
}; };
struct audit_features { struct audit_features {
......
...@@ -136,6 +136,11 @@ u32 audit_sig_sid = 0; ...@@ -136,6 +136,11 @@ u32 audit_sig_sid = 0;
*/ */
static atomic_t audit_lost = ATOMIC_INIT(0); static atomic_t audit_lost = ATOMIC_INIT(0);
/* Monotonically increasing sum of time the kernel has spent
* waiting while the backlog limit is exceeded.
*/
static atomic_t audit_backlog_wait_time_actual = ATOMIC_INIT(0);
/* Hash for inode-based rules */ /* Hash for inode-based rules */
struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
...@@ -1212,6 +1217,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -1212,6 +1217,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
s.backlog = skb_queue_len(&audit_queue); s.backlog = skb_queue_len(&audit_queue);
s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL; s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL;
s.backlog_wait_time = audit_backlog_wait_time; s.backlog_wait_time = audit_backlog_wait_time;
s.backlog_wait_time_actual = atomic_read(&audit_backlog_wait_time_actual);
audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s)); audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s));
break; break;
} }
...@@ -1315,6 +1321,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -1315,6 +1321,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
audit_log_config_change("lost", 0, lost, 1); audit_log_config_change("lost", 0, lost, 1);
return lost; return lost;
} }
if (s.mask == AUDIT_STATUS_BACKLOG_WAIT_TIME_ACTUAL) {
u32 actual = atomic_xchg(&audit_backlog_wait_time_actual, 0);
audit_log_config_change("backlog_wait_time_actual", 0, actual, 1);
return actual;
}
break; break;
} }
case AUDIT_GET_FEATURE: case AUDIT_GET_FEATURE:
...@@ -1826,12 +1838,15 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, ...@@ -1826,12 +1838,15 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
/* sleep if we are allowed and we haven't exhausted our /* sleep if we are allowed and we haven't exhausted our
* backlog wait limit */ * backlog wait limit */
if (gfpflags_allow_blocking(gfp_mask) && (stime > 0)) { if (gfpflags_allow_blocking(gfp_mask) && (stime > 0)) {
long rtime = stime;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
add_wait_queue_exclusive(&audit_backlog_wait, add_wait_queue_exclusive(&audit_backlog_wait,
&wait); &wait);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
stime = schedule_timeout(stime); stime = schedule_timeout(rtime);
atomic_add(rtime - stime, &audit_backlog_wait_time_actual);
remove_wait_queue(&audit_backlog_wait, &wait); remove_wait_queue(&audit_backlog_wait, &wait);
} else { } else {
if (audit_rate_check() && printk_ratelimit()) if (audit_rate_check() && printk_ratelimit())
...@@ -2079,13 +2094,13 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix, ...@@ -2079,13 +2094,13 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
/* We will allow 11 spaces for ' (deleted)' to be appended */ /* We will allow 11 spaces for ' (deleted)' to be appended */
pathname = kmalloc(PATH_MAX+11, ab->gfp_mask); pathname = kmalloc(PATH_MAX+11, ab->gfp_mask);
if (!pathname) { if (!pathname) {
audit_log_string(ab, "<no_memory>"); audit_log_format(ab, "\"<no_memory>\"");
return; return;
} }
p = d_path(path, pathname, PATH_MAX+11); p = d_path(path, pathname, PATH_MAX+11);
if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */ if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */
/* FIXME: can we save some information here? */ /* FIXME: can we save some information here? */
audit_log_string(ab, "<too_long>"); audit_log_format(ab, "\"<too_long>\"");
} else } else
audit_log_untrustedstring(ab, p); audit_log_untrustedstring(ab, p);
kfree(pathname); kfree(pathname);
......
...@@ -188,11 +188,9 @@ static struct fsnotify_mark *alloc_mark(void) ...@@ -188,11 +188,9 @@ static struct fsnotify_mark *alloc_mark(void)
static struct audit_chunk *alloc_chunk(int count) static struct audit_chunk *alloc_chunk(int count)
{ {
struct audit_chunk *chunk; struct audit_chunk *chunk;
size_t size;
int i; int i;
size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node); chunk = kzalloc(struct_size(chunk, owners, count), GFP_KERNEL);
chunk = kzalloc(size, GFP_KERNEL);
if (!chunk) if (!chunk)
return NULL; return NULL;
......
...@@ -75,6 +75,7 @@ ...@@ -75,6 +75,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/fsnotify_backend.h> #include <linux/fsnotify_backend.h>
#include <uapi/linux/limits.h> #include <uapi/linux/limits.h>
#include <uapi/linux/netfilter/nf_tables.h>
#include "audit.h" #include "audit.h"
...@@ -136,9 +137,26 @@ struct audit_nfcfgop_tab { ...@@ -136,9 +137,26 @@ struct audit_nfcfgop_tab {
}; };
static const struct audit_nfcfgop_tab audit_nfcfgs[] = { static const struct audit_nfcfgop_tab audit_nfcfgs[] = {
{ AUDIT_XT_OP_REGISTER, "register" }, { AUDIT_XT_OP_REGISTER, "xt_register" },
{ AUDIT_XT_OP_REPLACE, "replace" }, { AUDIT_XT_OP_REPLACE, "xt_replace" },
{ AUDIT_XT_OP_UNREGISTER, "unregister" }, { AUDIT_XT_OP_UNREGISTER, "xt_unregister" },
{ AUDIT_NFT_OP_TABLE_REGISTER, "nft_register_table" },
{ AUDIT_NFT_OP_TABLE_UNREGISTER, "nft_unregister_table" },
{ AUDIT_NFT_OP_CHAIN_REGISTER, "nft_register_chain" },
{ AUDIT_NFT_OP_CHAIN_UNREGISTER, "nft_unregister_chain" },
{ AUDIT_NFT_OP_RULE_REGISTER, "nft_register_rule" },
{ AUDIT_NFT_OP_RULE_UNREGISTER, "nft_unregister_rule" },
{ AUDIT_NFT_OP_SET_REGISTER, "nft_register_set" },
{ AUDIT_NFT_OP_SET_UNREGISTER, "nft_unregister_set" },
{ AUDIT_NFT_OP_SETELEM_REGISTER, "nft_register_setelem" },
{ AUDIT_NFT_OP_SETELEM_UNREGISTER, "nft_unregister_setelem" },
{ AUDIT_NFT_OP_GEN_REGISTER, "nft_register_gen" },
{ AUDIT_NFT_OP_OBJ_REGISTER, "nft_register_obj" },
{ AUDIT_NFT_OP_OBJ_UNREGISTER, "nft_unregister_obj" },
{ AUDIT_NFT_OP_OBJ_RESET, "nft_reset_obj" },
{ AUDIT_NFT_OP_FLOWTABLE_REGISTER, "nft_register_flowtable" },
{ AUDIT_NFT_OP_FLOWTABLE_UNREGISTER, "nft_unregister_flowtable" },
{ AUDIT_NFT_OP_INVALID, "nft_invalid" },
}; };
static int audit_match_perm(struct audit_context *ctx, int mask) static int audit_match_perm(struct audit_context *ctx, int mask)
...@@ -1876,6 +1894,20 @@ __audit_reusename(const __user char *uptr) ...@@ -1876,6 +1894,20 @@ __audit_reusename(const __user char *uptr)
return NULL; return NULL;
} }
inline void _audit_getcwd(struct audit_context *context)
{
if (!context->pwd.dentry)
get_fs_pwd(current->fs, &context->pwd);
}
void __audit_getcwd(void)
{
struct audit_context *context = audit_context();
if (context->in_syscall)
_audit_getcwd(context);
}
/** /**
* __audit_getname - add a name to the list * __audit_getname - add a name to the list
* @name: name to add * @name: name to add
...@@ -1900,8 +1932,7 @@ void __audit_getname(struct filename *name) ...@@ -1900,8 +1932,7 @@ void __audit_getname(struct filename *name)
name->aname = n; name->aname = n;
name->refcnt++; name->refcnt++;
if (!context->pwd.dentry) _audit_getcwd(context);
get_fs_pwd(current->fs, &context->pwd);
} }
static inline int audit_copy_fcaps(struct audit_names *name, static inline int audit_copy_fcaps(struct audit_names *name,
...@@ -2557,12 +2588,12 @@ void __audit_ntp_log(const struct audit_ntp_data *ad) ...@@ -2557,12 +2588,12 @@ void __audit_ntp_log(const struct audit_ntp_data *ad)
} }
void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries, void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
enum audit_nfcfgop op) enum audit_nfcfgop op, gfp_t gfp)
{ {
struct audit_buffer *ab; struct audit_buffer *ab;
char comm[sizeof(current->comm)]; char comm[sizeof(current->comm)];
ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_NETFILTER_CFG); ab = audit_log_start(audit_context(), gfp, AUDIT_NETFILTER_CFG);
if (!ab) if (!ab)
return; return;
audit_log_format(ab, "table=%s family=%u entries=%u op=%s", audit_log_format(ab, "table=%s family=%u entries=%u op=%s",
......
...@@ -1047,7 +1047,7 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl, ...@@ -1047,7 +1047,7 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,
vfree(counterstmp); vfree(counterstmp);
audit_log_nfcfg(repl->name, AF_BRIDGE, repl->nentries, audit_log_nfcfg(repl->name, AF_BRIDGE, repl->nentries,
AUDIT_XT_OP_REPLACE); AUDIT_XT_OP_REPLACE, GFP_KERNEL);
return ret; return ret;
free_unlock: free_unlock:
...@@ -1123,7 +1123,7 @@ static void __ebt_unregister_table(struct net *net, struct ebt_table *table) ...@@ -1123,7 +1123,7 @@ static void __ebt_unregister_table(struct net *net, struct ebt_table *table)
list_del(&table->list); list_del(&table->list);
mutex_unlock(&ebt_mutex); mutex_unlock(&ebt_mutex);
audit_log_nfcfg(table->name, AF_BRIDGE, table->private->nentries, audit_log_nfcfg(table->name, AF_BRIDGE, table->private->nentries,
AUDIT_XT_OP_UNREGISTER); AUDIT_XT_OP_UNREGISTER, GFP_KERNEL);
EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size, EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size,
ebt_cleanup_entry, net, NULL); ebt_cleanup_entry, net, NULL);
if (table->private->nentries) if (table->private->nentries)
...@@ -1218,7 +1218,7 @@ int ebt_register_table(struct net *net, const struct ebt_table *input_table, ...@@ -1218,7 +1218,7 @@ int ebt_register_table(struct net *net, const struct ebt_table *input_table,
} }
audit_log_nfcfg(repl->name, AF_BRIDGE, repl->nentries, audit_log_nfcfg(repl->name, AF_BRIDGE, repl->nentries,
AUDIT_XT_OP_REGISTER); AUDIT_XT_OP_REGISTER, GFP_KERNEL);
return ret; return ret;
free_unlock: free_unlock:
mutex_unlock(&ebt_mutex); mutex_unlock(&ebt_mutex);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/rhashtable.h> #include <linux/rhashtable.h>
#include <linux/audit.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nf_tables.h> #include <linux/netfilter/nf_tables.h>
...@@ -681,6 +682,17 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event) ...@@ -681,6 +682,17 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;?:0",
ctx->table->name, ctx->table->handle);
audit_log_nfcfg(buf,
ctx->family,
ctx->table->use,
event == NFT_MSG_NEWTABLE ?
AUDIT_NFT_OP_TABLE_REGISTER :
AUDIT_NFT_OP_TABLE_UNREGISTER,
GFP_KERNEL);
kfree(buf);
if (!ctx->report && if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
...@@ -1415,6 +1427,18 @@ static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event) ...@@ -1415,6 +1427,18 @@ static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
ctx->table->name, ctx->table->handle,
ctx->chain->name, ctx->chain->handle);
audit_log_nfcfg(buf,
ctx->family,
ctx->chain->use,
event == NFT_MSG_NEWCHAIN ?
AUDIT_NFT_OP_CHAIN_REGISTER :
AUDIT_NFT_OP_CHAIN_UNREGISTER,
GFP_KERNEL);
kfree(buf);
if (!ctx->report && if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
...@@ -2680,6 +2704,18 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx, ...@@ -2680,6 +2704,18 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
ctx->table->name, ctx->table->handle,
ctx->chain->name, ctx->chain->handle);
audit_log_nfcfg(buf,
ctx->family,
rule->handle,
event == NFT_MSG_NEWRULE ?
AUDIT_NFT_OP_RULE_REGISTER :
AUDIT_NFT_OP_RULE_UNREGISTER,
GFP_KERNEL);
kfree(buf);
if (!ctx->report && if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
...@@ -3682,6 +3718,18 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx, ...@@ -3682,6 +3718,18 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx,
struct sk_buff *skb; struct sk_buff *skb;
u32 portid = ctx->portid; u32 portid = ctx->portid;
int err; int err;
char *buf = kasprintf(gfp_flags, "%s:%llu;%s:%llu",
ctx->table->name, ctx->table->handle,
set->name, set->handle);
audit_log_nfcfg(buf,
ctx->family,
set->field_count,
event == NFT_MSG_NEWSET ?
AUDIT_NFT_OP_SET_REGISTER :
AUDIT_NFT_OP_SET_UNREGISTER,
gfp_flags);
kfree(buf);
if (!ctx->report && if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
...@@ -4798,6 +4846,18 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx, ...@@ -4798,6 +4846,18 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
u32 portid = ctx->portid; u32 portid = ctx->portid;
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
ctx->table->name, ctx->table->handle,
set->name, set->handle);
audit_log_nfcfg(buf,
ctx->family,
set->handle,
event == NFT_MSG_NEWSETELEM ?
AUDIT_NFT_OP_SETELEM_REGISTER :
AUDIT_NFT_OP_SETELEM_UNREGISTER,
GFP_KERNEL);
kfree(buf);
if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
return; return;
...@@ -5879,6 +5939,20 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -5879,6 +5939,20 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
obj->ops->type->type != filter->type) obj->ops->type->type != filter->type)
goto cont; goto cont;
if (reset) {
char *buf = kasprintf(GFP_ATOMIC,
"%s:%llu;?:0",
table->name,
table->handle);
audit_log_nfcfg(buf,
family,
obj->handle,
AUDIT_NFT_OP_OBJ_RESET,
GFP_ATOMIC);
kfree(buf);
}
if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid, if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
NFT_MSG_NEWOBJ, NFT_MSG_NEWOBJ,
...@@ -5989,6 +6063,18 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk, ...@@ -5989,6 +6063,18 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
if (NFNL_MSG_TYPE(nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET) if (NFNL_MSG_TYPE(nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
reset = true; reset = true;
if (reset) {
char *buf = kasprintf(GFP_ATOMIC, "%s:%llu;?:0",
table->name, table->handle);
audit_log_nfcfg(buf,
family,
obj->handle,
AUDIT_NFT_OP_OBJ_RESET,
GFP_ATOMIC);
kfree(buf);
}
err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid, err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid,
nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0, nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
family, table, obj, reset); family, table, obj, reset);
...@@ -6064,6 +6150,17 @@ void nft_obj_notify(struct net *net, const struct nft_table *table, ...@@ -6064,6 +6150,17 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
char *buf = kasprintf(gfp, "%s:%llu;?:0",
table->name, table->handle);
audit_log_nfcfg(buf,
family,
obj->handle,
event == NFT_MSG_NEWOBJ ?
AUDIT_NFT_OP_OBJ_REGISTER :
AUDIT_NFT_OP_OBJ_UNREGISTER,
gfp);
kfree(buf);
if (!report && if (!report &&
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
...@@ -6860,6 +6957,18 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx, ...@@ -6860,6 +6957,18 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
flowtable->table->name, flowtable->table->handle,
flowtable->name, flowtable->handle);
audit_log_nfcfg(buf,
ctx->family,
flowtable->hooknum,
event == NFT_MSG_NEWFLOWTABLE ?
AUDIT_NFT_OP_FLOWTABLE_REGISTER :
AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
GFP_KERNEL);
kfree(buf);
if (ctx->report && if (ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
...@@ -6981,6 +7090,9 @@ static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb, ...@@ -6981,6 +7090,9 @@ static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
struct sk_buff *skb2; struct sk_buff *skb2;
int err; int err;
audit_log_nfcfg("?:0;?:0", 0, net->nft.base_seq,
AUDIT_NFT_OP_GEN_REGISTER, GFP_KERNEL);
if (nlmsg_report(nlh) && if (nlmsg_report(nlh) &&
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
return; return;
......
...@@ -1410,7 +1410,8 @@ xt_replace_table(struct xt_table *table, ...@@ -1410,7 +1410,8 @@ xt_replace_table(struct xt_table *table,
audit_log_nfcfg(table->name, table->af, private->number, audit_log_nfcfg(table->name, table->af, private->number,
!private->number ? AUDIT_XT_OP_REGISTER : !private->number ? AUDIT_XT_OP_REGISTER :
AUDIT_XT_OP_REPLACE); AUDIT_XT_OP_REPLACE,
GFP_KERNEL);
return private; return private;
} }
EXPORT_SYMBOL_GPL(xt_replace_table); EXPORT_SYMBOL_GPL(xt_replace_table);
...@@ -1473,7 +1474,7 @@ void *xt_unregister_table(struct xt_table *table) ...@@ -1473,7 +1474,7 @@ void *xt_unregister_table(struct xt_table *table)
list_del(&table->list); list_del(&table->list);
mutex_unlock(&xt[table->af].mutex); mutex_unlock(&xt[table->af].mutex);
audit_log_nfcfg(table->name, table->af, private->number, audit_log_nfcfg(table->name, table->af, private->number,
AUDIT_XT_OP_UNREGISTER); AUDIT_XT_OP_UNREGISTER, GFP_KERNEL);
kfree(table); kfree(table);
return private; return private;
......
...@@ -57,18 +57,16 @@ static void audit_pre(struct audit_buffer *ab, void *ca) ...@@ -57,18 +57,16 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
struct common_audit_data *sa = ca; struct common_audit_data *sa = ca;
if (aa_g_audit_header) { if (aa_g_audit_header) {
audit_log_format(ab, "apparmor="); audit_log_format(ab, "apparmor=\"%s\"",
audit_log_string(ab, aa_audit_type[aad(sa)->type]); aa_audit_type[aad(sa)->type]);
} }
if (aad(sa)->op) { if (aad(sa)->op) {
audit_log_format(ab, " operation="); audit_log_format(ab, " operation=\"%s\"", aad(sa)->op);
audit_log_string(ab, aad(sa)->op);
} }
if (aad(sa)->info) { if (aad(sa)->info) {
audit_log_format(ab, " info="); audit_log_format(ab, " info=\"%s\"", aad(sa)->info);
audit_log_string(ab, aad(sa)->info);
if (aad(sa)->error) if (aad(sa)->error)
audit_log_format(ab, " error=%d", aad(sa)->error); audit_log_format(ab, " error=%d", aad(sa)->error);
} }
......
...@@ -34,20 +34,6 @@ static u32 map_mask_to_chr_mask(u32 mask) ...@@ -34,20 +34,6 @@ static u32 map_mask_to_chr_mask(u32 mask)
return m; return m;
} }
/**
* audit_file_mask - convert mask to permission string
* @buffer: buffer to write string to (NOT NULL)
* @mask: permission mask to convert
*/
static void audit_file_mask(struct audit_buffer *ab, u32 mask)
{
char str[10];
aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs,
map_mask_to_chr_mask(mask));
audit_log_string(ab, str);
}
/** /**
* file_audit_cb - call back for file specific audit fields * file_audit_cb - call back for file specific audit fields
* @ab: audit_buffer (NOT NULL) * @ab: audit_buffer (NOT NULL)
...@@ -57,14 +43,17 @@ static void file_audit_cb(struct audit_buffer *ab, void *va) ...@@ -57,14 +43,17 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
{ {
struct common_audit_data *sa = va; struct common_audit_data *sa = va;
kuid_t fsuid = current_fsuid(); kuid_t fsuid = current_fsuid();
char str[10];
if (aad(sa)->request & AA_AUDIT_FILE_MASK) { if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " requested_mask="); aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs,
audit_file_mask(ab, aad(sa)->request); map_mask_to_chr_mask(aad(sa)->request));
audit_log_format(ab, " requested_mask=\"%s\"", str);
} }
if (aad(sa)->denied & AA_AUDIT_FILE_MASK) { if (aad(sa)->denied & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " denied_mask="); aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs,
audit_file_mask(ab, aad(sa)->denied); map_mask_to_chr_mask(aad(sa)->denied));
audit_log_format(ab, " denied_mask=\"%s\"", str);
} }
if (aad(sa)->request & AA_AUDIT_FILE_MASK) { if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " fsuid=%d", audit_log_format(ab, " fsuid=%d",
......
...@@ -20,25 +20,23 @@ ...@@ -20,25 +20,23 @@
/** /**
* audit_ptrace_mask - convert mask to permission string * audit_ptrace_mask - convert mask to permission string
* @buffer: buffer to write string to (NOT NULL)
* @mask: permission mask to convert * @mask: permission mask to convert
*
* Returns: pointer to static string
*/ */
static void audit_ptrace_mask(struct audit_buffer *ab, u32 mask) static const char *audit_ptrace_mask(u32 mask)
{ {
switch (mask) { switch (mask) {
case MAY_READ: case MAY_READ:
audit_log_string(ab, "read"); return "read";
break;
case MAY_WRITE: case MAY_WRITE:
audit_log_string(ab, "trace"); return "trace";
break;
case AA_MAY_BE_READ: case AA_MAY_BE_READ:
audit_log_string(ab, "readby"); return "readby";
break;
case AA_MAY_BE_TRACED: case AA_MAY_BE_TRACED:
audit_log_string(ab, "tracedby"); return "tracedby";
break;
} }
return "";
} }
/* call back to audit ptrace fields */ /* call back to audit ptrace fields */
...@@ -47,12 +45,12 @@ static void audit_ptrace_cb(struct audit_buffer *ab, void *va) ...@@ -47,12 +45,12 @@ static void audit_ptrace_cb(struct audit_buffer *ab, void *va)
struct common_audit_data *sa = va; struct common_audit_data *sa = va;
if (aad(sa)->request & AA_PTRACE_PERM_MASK) { if (aad(sa)->request & AA_PTRACE_PERM_MASK) {
audit_log_format(ab, " requested_mask="); audit_log_format(ab, " requested_mask=\"%s\"",
audit_ptrace_mask(ab, aad(sa)->request); audit_ptrace_mask(aad(sa)->request));
if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { if (aad(sa)->denied & AA_PTRACE_PERM_MASK) {
audit_log_format(ab, " denied_mask="); audit_log_format(ab, " denied_mask=\"%s\"",
audit_ptrace_mask(ab, aad(sa)->denied); audit_ptrace_mask(aad(sa)->denied));
} }
} }
audit_log_format(ab, " peer="); audit_log_format(ab, " peer=");
...@@ -142,16 +140,18 @@ static inline int map_signal_num(int sig) ...@@ -142,16 +140,18 @@ static inline int map_signal_num(int sig)
} }
/** /**
* audit_file_mask - convert mask to permission string * audit_signal_mask - convert mask to permission string
* @buffer: buffer to write string to (NOT NULL)
* @mask: permission mask to convert * @mask: permission mask to convert
*
* Returns: pointer to static string
*/ */
static void audit_signal_mask(struct audit_buffer *ab, u32 mask) static const char *audit_signal_mask(u32 mask)
{ {
if (mask & MAY_READ) if (mask & MAY_READ)
audit_log_string(ab, "receive"); return "receive";
if (mask & MAY_WRITE) if (mask & MAY_WRITE)
audit_log_string(ab, "send"); return "send";
return "";
} }
/** /**
...@@ -164,11 +164,11 @@ static void audit_signal_cb(struct audit_buffer *ab, void *va) ...@@ -164,11 +164,11 @@ static void audit_signal_cb(struct audit_buffer *ab, void *va)
struct common_audit_data *sa = va; struct common_audit_data *sa = va;
if (aad(sa)->request & AA_SIGNAL_PERM_MASK) { if (aad(sa)->request & AA_SIGNAL_PERM_MASK) {
audit_log_format(ab, " requested_mask="); audit_log_format(ab, " requested_mask=\"%s\"",
audit_signal_mask(ab, aad(sa)->request); audit_signal_mask(aad(sa)->request));
if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) { if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) {
audit_log_format(ab, " denied_mask="); audit_log_format(ab, " denied_mask=\"%s\"",
audit_signal_mask(ab, aad(sa)->denied); audit_signal_mask(aad(sa)->denied));
} }
} }
if (aad(sa)->signal == SIGUNKNOWN) if (aad(sa)->signal == SIGUNKNOWN)
......
...@@ -72,16 +72,18 @@ void audit_net_cb(struct audit_buffer *ab, void *va) ...@@ -72,16 +72,18 @@ void audit_net_cb(struct audit_buffer *ab, void *va)
{ {
struct common_audit_data *sa = va; struct common_audit_data *sa = va;
audit_log_format(ab, " family=");
if (address_family_names[sa->u.net->family]) if (address_family_names[sa->u.net->family])
audit_log_string(ab, address_family_names[sa->u.net->family]); audit_log_format(ab, " family=\"%s\"",
address_family_names[sa->u.net->family]);
else else
audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family); audit_log_format(ab, " family=\"unknown(%d)\"",
audit_log_format(ab, " sock_type="); sa->u.net->family);
if (sock_type_names[aad(sa)->net.type]) if (sock_type_names[aad(sa)->net.type])
audit_log_string(ab, sock_type_names[aad(sa)->net.type]); audit_log_format(ab, " sock_type=\"%s\"",
sock_type_names[aad(sa)->net.type]);
else else
audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type); audit_log_format(ab, " sock_type=\"unknown(%d)\"",
aad(sa)->net.type);
audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol); audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
if (aad(sa)->request & NET_PERMS_MASK) { if (aad(sa)->request & NET_PERMS_MASK) {
......
...@@ -241,6 +241,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -241,6 +241,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_untrustedstring(ab, inode->i_sb->s_id);
audit_log_format(ab, " ino=%lu", inode->i_ino); audit_log_format(ab, " ino=%lu", inode->i_ino);
} }
audit_getcwd();
break; break;
} }
case LSM_AUDIT_DATA_FILE: { case LSM_AUDIT_DATA_FILE: {
...@@ -254,6 +255,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -254,6 +255,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_untrustedstring(ab, inode->i_sb->s_id);
audit_log_format(ab, " ino=%lu", inode->i_ino); audit_log_format(ab, " ino=%lu", inode->i_ino);
} }
audit_getcwd();
break; break;
} }
case LSM_AUDIT_DATA_IOCTL_OP: { case LSM_AUDIT_DATA_IOCTL_OP: {
...@@ -269,6 +271,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -269,6 +271,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
} }
audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd); audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd);
audit_getcwd();
break; break;
} }
case LSM_AUDIT_DATA_DENTRY: { case LSM_AUDIT_DATA_DENTRY: {
...@@ -283,6 +286,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -283,6 +286,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_untrustedstring(ab, inode->i_sb->s_id);
audit_log_format(ab, " ino=%lu", inode->i_ino); audit_log_format(ab, " ino=%lu", inode->i_ino);
} }
audit_getcwd();
break; break;
} }
case LSM_AUDIT_DATA_INODE: { case LSM_AUDIT_DATA_INODE: {
...@@ -300,6 +304,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -300,6 +304,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
audit_log_format(ab, " dev="); audit_log_format(ab, " dev=");
audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_untrustedstring(ab, inode->i_sb->s_id);
audit_log_format(ab, " ino=%lu", inode->i_ino); audit_log_format(ab, " ino=%lu", inode->i_ino);
audit_getcwd();
break; break;
} }
case LSM_AUDIT_DATA_TASK: { case LSM_AUDIT_DATA_TASK: {
...@@ -427,8 +432,8 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -427,8 +432,8 @@ static void dump_common_audit_data(struct audit_buffer *ab,
a->u.ibendport->port); a->u.ibendport->port);
break; break;
case LSM_AUDIT_DATA_LOCKDOWN: case LSM_AUDIT_DATA_LOCKDOWN:
audit_log_format(ab, " lockdown_reason="); audit_log_format(ab, " lockdown_reason=\"%s\"",
audit_log_string(ab, lockdown_reasons[a->u.reason]); lockdown_reasons[a->u.reason]);
break; break;
} /* switch (a->type) */ } /* switch (a->type) */
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment