Skip to content

Commit b43870c

Browse files
maxenglanderpcmoore
authored andcommitted
audit: report audit wait metric in audit status reply
In environments where the preservation of audit events and predictable usage of system memory are prioritized, admins may use a combination of --backlog_wait_time and -b options at the risk of degraded performance resulting from backlog waiting. In some cases, this risk may be preferred to lost events or unbounded memory usage. Ideally, this risk can be mitigated by making adjustments when backlog waiting is detected. However, detection can be difficult using the currently available metrics. For example, an admin attempting to debug degraded performance may falsely believe a full backlog indicates backlog waiting. It may turn out the backlog frequently fills up but drains quickly. To make it easier to reliably track degraded performance to backlog waiting, this patch makes the following changes: Add a new field backlog_wait_time_total to the audit status reply. Initialize this field to zero. Add to this field the total time spent by the current task on scheduled timeouts while the backlog limit is exceeded. Reset field to zero upon request via AUDIT_SET. Tested on Ubuntu 18.04 using complementary changes to the audit-userspace and audit-testsuite: - linux-audit/audit-userspace#134 - linux-audit/audit-testsuite#97 Signed-off-by: Max Englander <[email protected]> Signed-off-by: Paul Moore <[email protected]>
1 parent f1d9b23 commit b43870c

File tree

2 files changed

+36
-17
lines changed

2 files changed

+36
-17
lines changed

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: 25 additions & 10 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())

0 commit comments

Comments
 (0)