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
This commit is contained in:
@@ -136,6 +136,11 @@ u32 audit_sig_sid = 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 */
|
||||
struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
|
||||
|
||||
@@ -1201,17 +1206,18 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
case AUDIT_GET: {
|
||||
struct audit_status s;
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.enabled = audit_enabled;
|
||||
s.failure = audit_failure;
|
||||
s.enabled = audit_enabled;
|
||||
s.failure = audit_failure;
|
||||
/* NOTE: use pid_vnr() so the PID is relative to the current
|
||||
* namespace */
|
||||
s.pid = auditd_pid_vnr();
|
||||
s.rate_limit = audit_rate_limit;
|
||||
s.backlog_limit = audit_backlog_limit;
|
||||
s.lost = atomic_read(&audit_lost);
|
||||
s.backlog = skb_queue_len(&audit_queue);
|
||||
s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL;
|
||||
s.backlog_wait_time = audit_backlog_wait_time;
|
||||
s.pid = auditd_pid_vnr();
|
||||
s.rate_limit = audit_rate_limit;
|
||||
s.backlog_limit = audit_backlog_limit;
|
||||
s.lost = atomic_read(&audit_lost);
|
||||
s.backlog = skb_queue_len(&audit_queue);
|
||||
s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL;
|
||||
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));
|
||||
break;
|
||||
}
|
||||
@@ -1315,6 +1321,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
audit_log_config_change("lost", 0, lost, 1);
|
||||
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;
|
||||
}
|
||||
case AUDIT_GET_FEATURE:
|
||||
@@ -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
|
||||
* backlog wait limit */
|
||||
if (gfpflags_allow_blocking(gfp_mask) && (stime > 0)) {
|
||||
long rtime = stime;
|
||||
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
add_wait_queue_exclusive(&audit_backlog_wait,
|
||||
&wait);
|
||||
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);
|
||||
} else {
|
||||
if (audit_rate_check() && printk_ratelimit())
|
||||
@@ -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 */
|
||||
pathname = kmalloc(PATH_MAX+11, ab->gfp_mask);
|
||||
if (!pathname) {
|
||||
audit_log_string(ab, "<no_memory>");
|
||||
audit_log_format(ab, "\"<no_memory>\"");
|
||||
return;
|
||||
}
|
||||
p = d_path(path, pathname, PATH_MAX+11);
|
||||
if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */
|
||||
/* FIXME: can we save some information here? */
|
||||
audit_log_string(ab, "<too_long>");
|
||||
audit_log_format(ab, "\"<too_long>\"");
|
||||
} else
|
||||
audit_log_untrustedstring(ab, p);
|
||||
kfree(pathname);
|
||||
|
@@ -188,11 +188,9 @@ static struct fsnotify_mark *alloc_mark(void)
|
||||
static struct audit_chunk *alloc_chunk(int count)
|
||||
{
|
||||
struct audit_chunk *chunk;
|
||||
size_t size;
|
||||
int i;
|
||||
|
||||
size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node);
|
||||
chunk = kzalloc(size, GFP_KERNEL);
|
||||
chunk = kzalloc(struct_size(chunk, owners, count), GFP_KERNEL);
|
||||
if (!chunk)
|
||||
return NULL;
|
||||
|
||||
|
@@ -75,6 +75,7 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/fsnotify_backend.h>
|
||||
#include <uapi/linux/limits.h>
|
||||
#include <uapi/linux/netfilter/nf_tables.h>
|
||||
|
||||
#include "audit.h"
|
||||
|
||||
@@ -136,9 +137,26 @@ struct audit_nfcfgop_tab {
|
||||
};
|
||||
|
||||
static const struct audit_nfcfgop_tab audit_nfcfgs[] = {
|
||||
{ AUDIT_XT_OP_REGISTER, "register" },
|
||||
{ AUDIT_XT_OP_REPLACE, "replace" },
|
||||
{ AUDIT_XT_OP_UNREGISTER, "unregister" },
|
||||
{ AUDIT_XT_OP_REGISTER, "xt_register" },
|
||||
{ AUDIT_XT_OP_REPLACE, "xt_replace" },
|
||||
{ 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)
|
||||
@@ -1876,6 +1894,20 @@ __audit_reusename(const __user char *uptr)
|
||||
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
|
||||
* @name: name to add
|
||||
@@ -1900,8 +1932,7 @@ void __audit_getname(struct filename *name)
|
||||
name->aname = n;
|
||||
name->refcnt++;
|
||||
|
||||
if (!context->pwd.dentry)
|
||||
get_fs_pwd(current->fs, &context->pwd);
|
||||
_audit_getcwd(context);
|
||||
}
|
||||
|
||||
static inline int audit_copy_fcaps(struct audit_names *name,
|
||||
@@ -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,
|
||||
enum audit_nfcfgop op)
|
||||
enum audit_nfcfgop op, gfp_t gfp)
|
||||
{
|
||||
struct audit_buffer *ab;
|
||||
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)
|
||||
return;
|
||||
audit_log_format(ab, "table=%s family=%u entries=%u op=%s",
|
||||
|
Reference in New Issue
Block a user