Commit 5d7e5223 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull audit updates from Paul Moore:
 "Four audit patches for v5.17:

   - Harden the code through additional use of the struct_size() macro
     and zero-length arrays to flexible-array conversions.

   - Ensure that processes which generate userspace audit records are
     not exempt from the kernel's audit throttling when the audit queues
     are being overrun"

* tag 'audit-pr-20220110' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit:
  audit: replace zero-length array with flexible-array member
  audit: use struct_size() helper in audit_[send|make]_reply()
  audit: ensure userspace is penalized the same as the kernel when under pressure
  audit: use struct_size() helper in kmalloc()
parents a135ce44 ed98ea21
...@@ -514,7 +514,7 @@ struct audit_rule_data { ...@@ -514,7 +514,7 @@ struct audit_rule_data {
__u32 values[AUDIT_MAX_FIELDS]; __u32 values[AUDIT_MAX_FIELDS];
__u32 fieldflags[AUDIT_MAX_FIELDS]; __u32 fieldflags[AUDIT_MAX_FIELDS];
__u32 buflen; /* total length of string fields */ __u32 buflen; /* total length of string fields */
char buf[0]; /* string fields buffer */ char buf[]; /* string fields buffer */
}; };
#endif /* _UAPI_LINUX_AUDIT_H_ */ #endif /* _UAPI_LINUX_AUDIT_H_ */
...@@ -1444,7 +1444,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -1444,7 +1444,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (err) if (err)
return err; return err;
} }
sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL); sig_data = kmalloc(struct_size(sig_data, ctx, len), GFP_KERNEL);
if (!sig_data) { if (!sig_data) {
if (audit_sig_sid) if (audit_sig_sid)
security_release_secctx(ctx, len); security_release_secctx(ctx, len);
...@@ -1457,7 +1457,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -1457,7 +1457,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
security_release_secctx(ctx, len); security_release_secctx(ctx, len);
} }
audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0, audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
sig_data, sizeof(*sig_data) + len); sig_data, struct_size(sig_data, ctx, len));
kfree(sig_data); kfree(sig_data);
break; break;
case AUDIT_TTY_GET: { case AUDIT_TTY_GET: {
...@@ -1540,6 +1540,20 @@ static void audit_receive(struct sk_buff *skb) ...@@ -1540,6 +1540,20 @@ static void audit_receive(struct sk_buff *skb)
nlh = nlmsg_next(nlh, &len); nlh = nlmsg_next(nlh, &len);
} }
audit_ctl_unlock(); audit_ctl_unlock();
/* can't block with the ctrl lock, so penalize the sender now */
if (audit_backlog_limit &&
(skb_queue_len(&audit_queue) > audit_backlog_limit)) {
DECLARE_WAITQUEUE(wait, current);
/* wake kauditd to try and flush the queue */
wake_up_interruptible(&kauditd_wait);
add_wait_queue_exclusive(&audit_backlog_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(audit_backlog_wait_time);
remove_wait_queue(&audit_backlog_wait, &wait);
}
} }
/* Log information about who is connecting to the audit multicast socket */ /* Log information about who is connecting to the audit multicast socket */
...@@ -1824,7 +1838,9 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, ...@@ -1824,7 +1838,9 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
* task_tgid_vnr() since auditd_pid is set in audit_receive_msg() * task_tgid_vnr() since auditd_pid is set in audit_receive_msg()
* using a PID anchored in the caller's namespace * using a PID anchored in the caller's namespace
* 2. generator holding the audit_cmd_mutex - we don't want to block * 2. generator holding the audit_cmd_mutex - we don't want to block
* while holding the mutex */ * while holding the mutex, although we do penalize the sender
* later in audit_receive() when it is safe to block
*/
if (!(auditd_test_task(current) || audit_ctl_owner_current())) { if (!(auditd_test_task(current) || audit_ctl_owner_current())) {
long stime = audit_backlog_wait_time; long stime = audit_backlog_wait_time;
......
...@@ -94,7 +94,7 @@ static struct audit_tree *alloc_tree(const char *s) ...@@ -94,7 +94,7 @@ static struct audit_tree *alloc_tree(const char *s)
{ {
struct audit_tree *tree; struct audit_tree *tree;
tree = kmalloc(sizeof(struct audit_tree) + strlen(s) + 1, GFP_KERNEL); tree = kmalloc(struct_size(tree, pathname, strlen(s) + 1), GFP_KERNEL);
if (tree) { if (tree) {
refcount_set(&tree->count, 1); refcount_set(&tree->count, 1);
tree->goner = 0; tree->goner = 0;
......
...@@ -637,7 +637,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) ...@@ -637,7 +637,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
void *bufp; void *bufp;
int i; int i;
data = kmalloc(sizeof(*data) + krule->buflen, GFP_KERNEL); data = kmalloc(struct_size(data, buf, krule->buflen), GFP_KERNEL);
if (unlikely(!data)) if (unlikely(!data))
return NULL; return NULL;
memset(data, 0, sizeof(*data)); memset(data, 0, sizeof(*data));
...@@ -1092,7 +1092,7 @@ static void audit_list_rules(int seq, struct sk_buff_head *q) ...@@ -1092,7 +1092,7 @@ static void audit_list_rules(int seq, struct sk_buff_head *q)
break; break;
skb = audit_make_reply(seq, AUDIT_LIST_RULES, 0, 1, skb = audit_make_reply(seq, AUDIT_LIST_RULES, 0, 1,
data, data,
sizeof(*data) + data->buflen); struct_size(data, buf, data->buflen));
if (skb) if (skb)
skb_queue_tail(q, skb); skb_queue_tail(q, skb);
kfree(data); kfree(data);
......
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