Skip to content

Commit fd76a74

Browse files
committed
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
2 parents 49e917d + b43870c commit fd76a74

File tree

13 files changed

+273
-106
lines changed

13 files changed

+273
-106
lines changed

include/linux/audit.h

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/sched.h>
1313
#include <linux/ptrace.h>
1414
#include <uapi/linux/audit.h>
15+
#include <uapi/linux/netfilter/nf_tables.h>
1516

1617
#define AUDIT_INO_UNSET ((unsigned long)-1)
1718
#define AUDIT_DEV_UNSET ((dev_t)-1)
@@ -98,6 +99,23 @@ enum audit_nfcfgop {
9899
AUDIT_XT_OP_REGISTER,
99100
AUDIT_XT_OP_REPLACE,
100101
AUDIT_XT_OP_UNREGISTER,
102+
AUDIT_NFT_OP_TABLE_REGISTER,
103+
AUDIT_NFT_OP_TABLE_UNREGISTER,
104+
AUDIT_NFT_OP_CHAIN_REGISTER,
105+
AUDIT_NFT_OP_CHAIN_UNREGISTER,
106+
AUDIT_NFT_OP_RULE_REGISTER,
107+
AUDIT_NFT_OP_RULE_UNREGISTER,
108+
AUDIT_NFT_OP_SET_REGISTER,
109+
AUDIT_NFT_OP_SET_UNREGISTER,
110+
AUDIT_NFT_OP_SETELEM_REGISTER,
111+
AUDIT_NFT_OP_SETELEM_UNREGISTER,
112+
AUDIT_NFT_OP_GEN_REGISTER,
113+
AUDIT_NFT_OP_OBJ_REGISTER,
114+
AUDIT_NFT_OP_OBJ_UNREGISTER,
115+
AUDIT_NFT_OP_OBJ_RESET,
116+
AUDIT_NFT_OP_FLOWTABLE_REGISTER,
117+
AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
118+
AUDIT_NFT_OP_INVALID,
101119
};
102120

103121
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,
274292
extern void __audit_syscall_exit(int ret_success, long ret_value);
275293
extern struct filename *__audit_reusename(const __user char *uptr);
276294
extern void __audit_getname(struct filename *name);
277-
295+
extern void __audit_getcwd(void);
278296
extern void __audit_inode(struct filename *name, const struct dentry *dentry,
279297
unsigned int flags);
280298
extern void __audit_file(const struct file *);
@@ -333,6 +351,11 @@ static inline void audit_getname(struct filename *name)
333351
if (unlikely(!audit_dummy_context()))
334352
__audit_getname(name);
335353
}
354+
static inline void audit_getcwd(void)
355+
{
356+
if (unlikely(audit_context()))
357+
__audit_getcwd();
358+
}
336359
static inline void audit_inode(struct filename *name,
337360
const struct dentry *dentry,
338361
unsigned int aflags) {
@@ -386,7 +409,7 @@ extern void __audit_fanotify(unsigned int response);
386409
extern void __audit_tk_injoffset(struct timespec64 offset);
387410
extern void __audit_ntp_log(const struct audit_ntp_data *ad);
388411
extern void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
389-
enum audit_nfcfgop op);
412+
enum audit_nfcfgop op, gfp_t gfp);
390413

391414
static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
392415
{
@@ -524,10 +547,10 @@ static inline void audit_ntp_log(const struct audit_ntp_data *ad)
524547

525548
static inline void audit_log_nfcfg(const char *name, u8 af,
526549
unsigned int nentries,
527-
enum audit_nfcfgop op)
550+
enum audit_nfcfgop op, gfp_t gfp)
528551
{
529552
if (audit_enabled)
530-
__audit_log_nfcfg(name, af, nentries, op);
553+
__audit_log_nfcfg(name, af, nentries, op, gfp);
531554
}
532555

533556
extern int audit_n_rules;
@@ -561,13 +584,7 @@ static inline struct filename *audit_reusename(const __user char *name)
561584
}
562585
static inline void audit_getname(struct filename *name)
563586
{ }
564-
static inline void __audit_inode(struct filename *name,
565-
const struct dentry *dentry,
566-
unsigned int flags)
567-
{ }
568-
static inline void __audit_inode_child(struct inode *parent,
569-
const struct dentry *dentry,
570-
const unsigned char type)
587+
static inline void audit_getcwd(void)
571588
{ }
572589
static inline void audit_inode(struct filename *name,
573590
const struct dentry *dentry,
@@ -665,7 +682,7 @@ static inline void audit_ptrace(struct task_struct *t)
665682

666683
static inline void audit_log_nfcfg(const char *name, u8 af,
667684
unsigned int nentries,
668-
enum audit_nfcfgop op)
685+
enum audit_nfcfgop op, gfp_t gfp)
669686
{ }
670687

671688
#define audit_n_rules 0
@@ -677,9 +694,4 @@ static inline bool audit_loginuid_set(struct task_struct *tsk)
677694
return uid_valid(audit_get_loginuid(tsk));
678695
}
679696

680-
static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
681-
{
682-
audit_log_n_string(ab, buf, strlen(buf));
683-
}
684-
685697
#endif

include/uapi/linux/audit.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -333,14 +333,15 @@ enum {
333333
};
334334

335335
/* Status symbols */
336-
/* Mask values */
337-
#define AUDIT_STATUS_ENABLED 0x0001
338-
#define AUDIT_STATUS_FAILURE 0x0002
339-
#define AUDIT_STATUS_PID 0x0004
336+
/* Mask values */
337+
#define AUDIT_STATUS_ENABLED 0x0001
338+
#define AUDIT_STATUS_FAILURE 0x0002
339+
#define AUDIT_STATUS_PID 0x0004
340340
#define AUDIT_STATUS_RATE_LIMIT 0x0008
341-
#define AUDIT_STATUS_BACKLOG_LIMIT 0x0010
342-
#define AUDIT_STATUS_BACKLOG_WAIT_TIME 0x0020
343-
#define AUDIT_STATUS_LOST 0x0040
341+
#define AUDIT_STATUS_BACKLOG_LIMIT 0x0010
342+
#define AUDIT_STATUS_BACKLOG_WAIT_TIME 0x0020
343+
#define AUDIT_STATUS_LOST 0x0040
344+
#define AUDIT_STATUS_BACKLOG_WAIT_TIME_ACTUAL 0x0080
344345

345346
#define AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT 0x00000001
346347
#define AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME 0x00000002
@@ -467,6 +468,9 @@ struct audit_status {
467468
__u32 feature_bitmap; /* bitmap of kernel audit features */
468469
};
469470
__u32 backlog_wait_time;/* message queue wait timeout */
471+
__u32 backlog_wait_time_actual;/* time spent waiting while
472+
* message limit exceeded
473+
*/
470474
};
471475

472476
struct audit_features {

kernel/audit.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ u32 audit_sig_sid = 0;
136136
*/
137137
static atomic_t audit_lost = ATOMIC_INIT(0);
138138

139+
/* Monotonically increasing sum of time the kernel has spent
140+
* waiting while the backlog limit is exceeded.
141+
*/
142+
static atomic_t audit_backlog_wait_time_actual = ATOMIC_INIT(0);
143+
139144
/* Hash for inode-based rules */
140145
struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
141146

@@ -1201,17 +1206,18 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
12011206
case AUDIT_GET: {
12021207
struct audit_status s;
12031208
memset(&s, 0, sizeof(s));
1204-
s.enabled = audit_enabled;
1205-
s.failure = audit_failure;
1209+
s.enabled = audit_enabled;
1210+
s.failure = audit_failure;
12061211
/* NOTE: use pid_vnr() so the PID is relative to the current
12071212
* namespace */
1208-
s.pid = auditd_pid_vnr();
1209-
s.rate_limit = audit_rate_limit;
1210-
s.backlog_limit = audit_backlog_limit;
1211-
s.lost = atomic_read(&audit_lost);
1212-
s.backlog = skb_queue_len(&audit_queue);
1213-
s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL;
1214-
s.backlog_wait_time = audit_backlog_wait_time;
1213+
s.pid = auditd_pid_vnr();
1214+
s.rate_limit = audit_rate_limit;
1215+
s.backlog_limit = audit_backlog_limit;
1216+
s.lost = atomic_read(&audit_lost);
1217+
s.backlog = skb_queue_len(&audit_queue);
1218+
s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL;
1219+
s.backlog_wait_time = audit_backlog_wait_time;
1220+
s.backlog_wait_time_actual = atomic_read(&audit_backlog_wait_time_actual);
12151221
audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s));
12161222
break;
12171223
}
@@ -1315,6 +1321,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
13151321
audit_log_config_change("lost", 0, lost, 1);
13161322
return lost;
13171323
}
1324+
if (s.mask == AUDIT_STATUS_BACKLOG_WAIT_TIME_ACTUAL) {
1325+
u32 actual = atomic_xchg(&audit_backlog_wait_time_actual, 0);
1326+
1327+
audit_log_config_change("backlog_wait_time_actual", 0, actual, 1);
1328+
return actual;
1329+
}
13181330
break;
13191331
}
13201332
case AUDIT_GET_FEATURE:
@@ -1826,12 +1838,15 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
18261838
/* sleep if we are allowed and we haven't exhausted our
18271839
* backlog wait limit */
18281840
if (gfpflags_allow_blocking(gfp_mask) && (stime > 0)) {
1841+
long rtime = stime;
1842+
18291843
DECLARE_WAITQUEUE(wait, current);
18301844

18311845
add_wait_queue_exclusive(&audit_backlog_wait,
18321846
&wait);
18331847
set_current_state(TASK_UNINTERRUPTIBLE);
1834-
stime = schedule_timeout(stime);
1848+
stime = schedule_timeout(rtime);
1849+
atomic_add(rtime - stime, &audit_backlog_wait_time_actual);
18351850
remove_wait_queue(&audit_backlog_wait, &wait);
18361851
} else {
18371852
if (audit_rate_check() && printk_ratelimit())
@@ -2079,13 +2094,13 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
20792094
/* We will allow 11 spaces for ' (deleted)' to be appended */
20802095
pathname = kmalloc(PATH_MAX+11, ab->gfp_mask);
20812096
if (!pathname) {
2082-
audit_log_string(ab, "<no_memory>");
2097+
audit_log_format(ab, "\"<no_memory>\"");
20832098
return;
20842099
}
20852100
p = d_path(path, pathname, PATH_MAX+11);
20862101
if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */
20872102
/* FIXME: can we save some information here? */
2088-
audit_log_string(ab, "<too_long>");
2103+
audit_log_format(ab, "\"<too_long>\"");
20892104
} else
20902105
audit_log_untrustedstring(ab, p);
20912106
kfree(pathname);

kernel/audit_tree.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,9 @@ static struct fsnotify_mark *alloc_mark(void)
188188
static struct audit_chunk *alloc_chunk(int count)
189189
{
190190
struct audit_chunk *chunk;
191-
size_t size;
192191
int i;
193192

194-
size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node);
195-
chunk = kzalloc(size, GFP_KERNEL);
193+
chunk = kzalloc(struct_size(chunk, owners, count), GFP_KERNEL);
196194
if (!chunk)
197195
return NULL;
198196

kernel/auditsc.c

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
#include <linux/uaccess.h>
7676
#include <linux/fsnotify_backend.h>
7777
#include <uapi/linux/limits.h>
78+
#include <uapi/linux/netfilter/nf_tables.h>
7879

7980
#include "audit.h"
8081

@@ -136,9 +137,26 @@ struct audit_nfcfgop_tab {
136137
};
137138

138139
static const struct audit_nfcfgop_tab audit_nfcfgs[] = {
139-
{ AUDIT_XT_OP_REGISTER, "register" },
140-
{ AUDIT_XT_OP_REPLACE, "replace" },
141-
{ AUDIT_XT_OP_UNREGISTER, "unregister" },
140+
{ AUDIT_XT_OP_REGISTER, "xt_register" },
141+
{ AUDIT_XT_OP_REPLACE, "xt_replace" },
142+
{ AUDIT_XT_OP_UNREGISTER, "xt_unregister" },
143+
{ AUDIT_NFT_OP_TABLE_REGISTER, "nft_register_table" },
144+
{ AUDIT_NFT_OP_TABLE_UNREGISTER, "nft_unregister_table" },
145+
{ AUDIT_NFT_OP_CHAIN_REGISTER, "nft_register_chain" },
146+
{ AUDIT_NFT_OP_CHAIN_UNREGISTER, "nft_unregister_chain" },
147+
{ AUDIT_NFT_OP_RULE_REGISTER, "nft_register_rule" },
148+
{ AUDIT_NFT_OP_RULE_UNREGISTER, "nft_unregister_rule" },
149+
{ AUDIT_NFT_OP_SET_REGISTER, "nft_register_set" },
150+
{ AUDIT_NFT_OP_SET_UNREGISTER, "nft_unregister_set" },
151+
{ AUDIT_NFT_OP_SETELEM_REGISTER, "nft_register_setelem" },
152+
{ AUDIT_NFT_OP_SETELEM_UNREGISTER, "nft_unregister_setelem" },
153+
{ AUDIT_NFT_OP_GEN_REGISTER, "nft_register_gen" },
154+
{ AUDIT_NFT_OP_OBJ_REGISTER, "nft_register_obj" },
155+
{ AUDIT_NFT_OP_OBJ_UNREGISTER, "nft_unregister_obj" },
156+
{ AUDIT_NFT_OP_OBJ_RESET, "nft_reset_obj" },
157+
{ AUDIT_NFT_OP_FLOWTABLE_REGISTER, "nft_register_flowtable" },
158+
{ AUDIT_NFT_OP_FLOWTABLE_UNREGISTER, "nft_unregister_flowtable" },
159+
{ AUDIT_NFT_OP_INVALID, "nft_invalid" },
142160
};
143161

144162
static int audit_match_perm(struct audit_context *ctx, int mask)
@@ -1876,6 +1894,20 @@ __audit_reusename(const __user char *uptr)
18761894
return NULL;
18771895
}
18781896

1897+
inline void _audit_getcwd(struct audit_context *context)
1898+
{
1899+
if (!context->pwd.dentry)
1900+
get_fs_pwd(current->fs, &context->pwd);
1901+
}
1902+
1903+
void __audit_getcwd(void)
1904+
{
1905+
struct audit_context *context = audit_context();
1906+
1907+
if (context->in_syscall)
1908+
_audit_getcwd(context);
1909+
}
1910+
18791911
/**
18801912
* __audit_getname - add a name to the list
18811913
* @name: name to add
@@ -1900,8 +1932,7 @@ void __audit_getname(struct filename *name)
19001932
name->aname = n;
19011933
name->refcnt++;
19021934

1903-
if (!context->pwd.dentry)
1904-
get_fs_pwd(current->fs, &context->pwd);
1935+
_audit_getcwd(context);
19051936
}
19061937

19071938
static inline int audit_copy_fcaps(struct audit_names *name,
@@ -2557,12 +2588,12 @@ void __audit_ntp_log(const struct audit_ntp_data *ad)
25572588
}
25582589

25592590
void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
2560-
enum audit_nfcfgop op)
2591+
enum audit_nfcfgop op, gfp_t gfp)
25612592
{
25622593
struct audit_buffer *ab;
25632594
char comm[sizeof(current->comm)];
25642595

2565-
ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_NETFILTER_CFG);
2596+
ab = audit_log_start(audit_context(), gfp, AUDIT_NETFILTER_CFG);
25662597
if (!ab)
25672598
return;
25682599
audit_log_format(ab, "table=%s family=%u entries=%u op=%s",

net/bridge/netfilter/ebtables.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,7 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,
10471047
vfree(counterstmp);
10481048

10491049
audit_log_nfcfg(repl->name, AF_BRIDGE, repl->nentries,
1050-
AUDIT_XT_OP_REPLACE);
1050+
AUDIT_XT_OP_REPLACE, GFP_KERNEL);
10511051
return ret;
10521052

10531053
free_unlock:
@@ -1123,7 +1123,7 @@ static void __ebt_unregister_table(struct net *net, struct ebt_table *table)
11231123
list_del(&table->list);
11241124
mutex_unlock(&ebt_mutex);
11251125
audit_log_nfcfg(table->name, AF_BRIDGE, table->private->nentries,
1126-
AUDIT_XT_OP_UNREGISTER);
1126+
AUDIT_XT_OP_UNREGISTER, GFP_KERNEL);
11271127
EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size,
11281128
ebt_cleanup_entry, net, NULL);
11291129
if (table->private->nentries)
@@ -1218,7 +1218,7 @@ int ebt_register_table(struct net *net, const struct ebt_table *input_table,
12181218
}
12191219

12201220
audit_log_nfcfg(repl->name, AF_BRIDGE, repl->nentries,
1221-
AUDIT_XT_OP_REGISTER);
1221+
AUDIT_XT_OP_REGISTER, GFP_KERNEL);
12221222
return ret;
12231223
free_unlock:
12241224
mutex_unlock(&ebt_mutex);

0 commit comments

Comments
 (0)