Commit 7391786a authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'stable-4.13' of git://git.infradead.org/users/pcmoore/audit

Pull audit updates from Paul Moore:
 "Things are relatively quiet on the audit front for v4.13, just five
  patches for a total diffstat of 102 lines.

  There are two patches from Richard to consistently record the POSIX
  capabilities and add the ambient capability information as well.

  I also chipped in two patches to fix a race condition with the auditd
  tracking code and ensure we don't skip sending any records to the
  audit multicast group.

  Finally a single style fix that I accepted because I must have been in
  a good mood that day.

  Everything passes our test suite, and should be relatively harmless,
  please merge for v4.13"

* 'stable-4.13' of git://git.infradead.org/users/pcmoore/audit:
  audit: make sure we never skip the multicast broadcast
  audit: fix a race condition with the auditd tracking code
  audit: style fix
  audit: add ambient capabilities to CAPSET and BPRM_FCAPS records
  audit: unswing cap_* fields in PATH records
parents eed1fc87 cd33f5f2
...@@ -575,12 +575,16 @@ static void kauditd_retry_skb(struct sk_buff *skb) ...@@ -575,12 +575,16 @@ static void kauditd_retry_skb(struct sk_buff *skb)
/** /**
* auditd_reset - Disconnect the auditd connection * auditd_reset - Disconnect the auditd connection
* @ac: auditd connection state
* *
* Description: * Description:
* Break the auditd/kauditd connection and move all the queued records into the * Break the auditd/kauditd connection and move all the queued records into the
* hold queue in case auditd reconnects. * hold queue in case auditd reconnects. It is important to note that the @ac
* pointer should never be dereferenced inside this function as it may be NULL
* or invalid, you can only compare the memory address! If @ac is NULL then
* the connection will always be reset.
*/ */
static void auditd_reset(void) static void auditd_reset(const struct auditd_connection *ac)
{ {
unsigned long flags; unsigned long flags;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -590,17 +594,21 @@ static void auditd_reset(void) ...@@ -590,17 +594,21 @@ static void auditd_reset(void)
spin_lock_irqsave(&auditd_conn_lock, flags); spin_lock_irqsave(&auditd_conn_lock, flags);
ac_old = rcu_dereference_protected(auditd_conn, ac_old = rcu_dereference_protected(auditd_conn,
lockdep_is_held(&auditd_conn_lock)); lockdep_is_held(&auditd_conn_lock));
if (ac && ac != ac_old) {
/* someone already registered a new auditd connection */
spin_unlock_irqrestore(&auditd_conn_lock, flags);
return;
}
rcu_assign_pointer(auditd_conn, NULL); rcu_assign_pointer(auditd_conn, NULL);
spin_unlock_irqrestore(&auditd_conn_lock, flags); spin_unlock_irqrestore(&auditd_conn_lock, flags);
if (ac_old) if (ac_old)
call_rcu(&ac_old->rcu, auditd_conn_free); call_rcu(&ac_old->rcu, auditd_conn_free);
/* flush all of the main and retry queues to the hold queue */ /* flush the retry queue to the hold queue, but don't touch the main
* queue since we need to process that normally for multicast */
while ((skb = skb_dequeue(&audit_retry_queue))) while ((skb = skb_dequeue(&audit_retry_queue)))
kauditd_hold_skb(skb); kauditd_hold_skb(skb);
while ((skb = skb_dequeue(&audit_queue)))
kauditd_hold_skb(skb);
} }
/** /**
...@@ -649,8 +657,8 @@ static int auditd_send_unicast_skb(struct sk_buff *skb) ...@@ -649,8 +657,8 @@ static int auditd_send_unicast_skb(struct sk_buff *skb)
return rc; return rc;
err: err:
if (rc == -ECONNREFUSED) if (ac && rc == -ECONNREFUSED)
auditd_reset(); auditd_reset(ac);
return rc; return rc;
} }
...@@ -795,9 +803,9 @@ static int kauditd_thread(void *dummy) ...@@ -795,9 +803,9 @@ static int kauditd_thread(void *dummy)
rc = kauditd_send_queue(sk, portid, rc = kauditd_send_queue(sk, portid,
&audit_hold_queue, UNICAST_RETRIES, &audit_hold_queue, UNICAST_RETRIES,
NULL, kauditd_rehold_skb); NULL, kauditd_rehold_skb);
if (rc < 0) { if (ac && rc < 0) {
sk = NULL; sk = NULL;
auditd_reset(); auditd_reset(ac);
goto main_queue; goto main_queue;
} }
...@@ -805,9 +813,9 @@ static int kauditd_thread(void *dummy) ...@@ -805,9 +813,9 @@ static int kauditd_thread(void *dummy)
rc = kauditd_send_queue(sk, portid, rc = kauditd_send_queue(sk, portid,
&audit_retry_queue, UNICAST_RETRIES, &audit_retry_queue, UNICAST_RETRIES,
NULL, kauditd_hold_skb); NULL, kauditd_hold_skb);
if (rc < 0) { if (ac && rc < 0) {
sk = NULL; sk = NULL;
auditd_reset(); auditd_reset(ac);
goto main_queue; goto main_queue;
} }
...@@ -815,12 +823,13 @@ static int kauditd_thread(void *dummy) ...@@ -815,12 +823,13 @@ static int kauditd_thread(void *dummy)
/* process the main queue - do the multicast send and attempt /* process the main queue - do the multicast send and attempt
* unicast, dump failed record sends to the retry queue; if * unicast, dump failed record sends to the retry queue; if
* sk == NULL due to previous failures we will just do the * sk == NULL due to previous failures we will just do the
* multicast send and move the record to the retry queue */ * multicast send and move the record to the hold queue */
rc = kauditd_send_queue(sk, portid, &audit_queue, 1, rc = kauditd_send_queue(sk, portid, &audit_queue, 1,
kauditd_send_multicast_skb, kauditd_send_multicast_skb,
kauditd_retry_skb); (sk ?
if (sk == NULL || rc < 0) kauditd_retry_skb : kauditd_hold_skb));
auditd_reset(); if (ac && rc < 0)
auditd_reset(ac);
sk = NULL; sk = NULL;
/* drop our netns reference, no auditd sends past this line */ /* drop our netns reference, no auditd sends past this line */
...@@ -1230,7 +1239,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -1230,7 +1239,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
auditd_pid, 1); auditd_pid, 1);
/* unregister the auditd connection */ /* unregister the auditd connection */
auditd_reset(); auditd_reset(NULL);
} }
} }
if (s.mask & AUDIT_STATUS_RATE_LIMIT) { if (s.mask & AUDIT_STATUS_RATE_LIMIT) {
...@@ -1999,20 +2008,8 @@ void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) ...@@ -1999,20 +2008,8 @@ void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap)
static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
{ {
kernel_cap_t *perm = &name->fcap.permitted; audit_log_cap(ab, "cap_fp", &name->fcap.permitted);
kernel_cap_t *inh = &name->fcap.inheritable; audit_log_cap(ab, "cap_fi", &name->fcap.inheritable);
int log = 0;
if (!cap_isclear(*perm)) {
audit_log_cap(ab, "cap_fp", perm);
log = 1;
}
if (!cap_isclear(*inh)) {
audit_log_cap(ab, "cap_fi", inh);
log = 1;
}
if (log)
audit_log_format(ab, " cap_fe=%d cap_fver=%x", audit_log_format(ab, " cap_fe=%d cap_fver=%x",
name->fcap.fE, name->fcap_ver); name->fcap.fE, name->fcap_ver);
} }
......
...@@ -68,6 +68,7 @@ struct audit_cap_data { ...@@ -68,6 +68,7 @@ struct audit_cap_data {
unsigned int fE; /* effective bit of file cap */ unsigned int fE; /* effective bit of file cap */
kernel_cap_t effective; /* effective set of process */ kernel_cap_t effective; /* effective set of process */
}; };
kernel_cap_t ambient;
}; };
/* When fs/namei.c:getname() is called, we store the pointer in name and bump /* When fs/namei.c:getname() is called, we store the pointer in name and bump
...@@ -247,13 +248,13 @@ struct audit_netlink_list { ...@@ -247,13 +248,13 @@ struct audit_netlink_list {
struct sk_buff_head q; struct sk_buff_head q;
}; };
int audit_send_list(void *); int audit_send_list(void *_dest);
extern int selinux_audit_rule_update(void); extern int selinux_audit_rule_update(void);
extern struct mutex audit_filter_mutex; extern struct mutex audit_filter_mutex;
extern int audit_del_rule(struct audit_entry *); extern int audit_del_rule(struct audit_entry *entry);
extern void audit_free_rule_rcu(struct rcu_head *); extern void audit_free_rule_rcu(struct rcu_head *head);
extern struct list_head audit_filter_list[]; extern struct list_head audit_filter_list[];
extern struct audit_entry *audit_dupe_rule(struct audit_krule *old); extern struct audit_entry *audit_dupe_rule(struct audit_krule *old);
...@@ -301,17 +302,17 @@ extern int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark ...@@ -301,17 +302,17 @@ extern int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark
#endif /* CONFIG_AUDIT_WATCH */ #endif /* CONFIG_AUDIT_WATCH */
#ifdef CONFIG_AUDIT_TREE #ifdef CONFIG_AUDIT_TREE
extern struct audit_chunk *audit_tree_lookup(const struct inode *); extern struct audit_chunk *audit_tree_lookup(const struct inode *inode);
extern void audit_put_chunk(struct audit_chunk *); extern void audit_put_chunk(struct audit_chunk *chunk);
extern bool audit_tree_match(struct audit_chunk *, struct audit_tree *); extern bool audit_tree_match(struct audit_chunk *chunk, struct audit_tree *tree);
extern int audit_make_tree(struct audit_krule *, char *, u32); extern int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op);
extern int audit_add_tree_rule(struct audit_krule *); extern int audit_add_tree_rule(struct audit_krule *rule);
extern int audit_remove_tree_rule(struct audit_krule *); extern int audit_remove_tree_rule(struct audit_krule *rule);
extern void audit_trim_trees(void); extern void audit_trim_trees(void);
extern int audit_tag_tree(char *old, char *new); extern int audit_tag_tree(char *old, char *new);
extern const char *audit_tree_path(struct audit_tree *); extern const char *audit_tree_path(struct audit_tree *tree);
extern void audit_put_tree(struct audit_tree *); extern void audit_put_tree(struct audit_tree *tree);
extern void audit_kill_trees(struct list_head *); extern void audit_kill_trees(struct list_head *list);
#else #else
#define audit_remove_tree_rule(rule) BUG() #define audit_remove_tree_rule(rule) BUG()
#define audit_add_tree_rule(rule) -EINVAL #define audit_add_tree_rule(rule) -EINVAL
...@@ -323,7 +324,7 @@ extern void audit_kill_trees(struct list_head *); ...@@ -323,7 +324,7 @@ extern void audit_kill_trees(struct list_head *);
#define audit_kill_trees(list) BUG() #define audit_kill_trees(list) BUG()
#endif #endif
extern char *audit_unpack_string(void **, size_t *, size_t); extern char *audit_unpack_string(void **bufp, size_t *remain, size_t len);
extern pid_t audit_sig_pid; extern pid_t audit_sig_pid;
extern kuid_t audit_sig_uid; extern kuid_t audit_sig_uid;
...@@ -333,7 +334,7 @@ extern int audit_filter(int msgtype, unsigned int listtype); ...@@ -333,7 +334,7 @@ extern int audit_filter(int msgtype, unsigned int listtype);
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
extern int audit_signal_info(int sig, struct task_struct *t); extern int audit_signal_info(int sig, struct task_struct *t);
extern void audit_filter_inodes(struct task_struct *, struct audit_context *); extern void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx);
extern struct list_head *audit_killed_trees(void); extern struct list_head *audit_killed_trees(void);
#else #else
#define audit_signal_info(s,t) AUDIT_DISABLED #define audit_signal_info(s,t) AUDIT_DISABLED
......
...@@ -1261,6 +1261,7 @@ static void show_special(struct audit_context *context, int *call_panic) ...@@ -1261,6 +1261,7 @@ static void show_special(struct audit_context *context, int *call_panic)
audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable); audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable);
audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted); audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted);
audit_log_cap(ab, "cap_pe", &context->capset.cap.effective); audit_log_cap(ab, "cap_pe", &context->capset.cap.effective);
audit_log_cap(ab, "cap_pa", &context->capset.cap.ambient);
break; break;
case AUDIT_MMAP: case AUDIT_MMAP:
audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd, audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd,
...@@ -1382,9 +1383,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts ...@@ -1382,9 +1383,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
audit_log_cap(ab, "old_pp", &axs->old_pcap.permitted); audit_log_cap(ab, "old_pp", &axs->old_pcap.permitted);
audit_log_cap(ab, "old_pi", &axs->old_pcap.inheritable); audit_log_cap(ab, "old_pi", &axs->old_pcap.inheritable);
audit_log_cap(ab, "old_pe", &axs->old_pcap.effective); audit_log_cap(ab, "old_pe", &axs->old_pcap.effective);
audit_log_cap(ab, "new_pp", &axs->new_pcap.permitted); audit_log_cap(ab, "old_pa", &axs->old_pcap.ambient);
audit_log_cap(ab, "new_pi", &axs->new_pcap.inheritable); audit_log_cap(ab, "pp", &axs->new_pcap.permitted);
audit_log_cap(ab, "new_pe", &axs->new_pcap.effective); audit_log_cap(ab, "pi", &axs->new_pcap.inheritable);
audit_log_cap(ab, "pe", &axs->new_pcap.effective);
audit_log_cap(ab, "pa", &axs->new_pcap.ambient);
break; } break; }
} }
...@@ -2342,10 +2345,12 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm, ...@@ -2342,10 +2345,12 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
ax->old_pcap.permitted = old->cap_permitted; ax->old_pcap.permitted = old->cap_permitted;
ax->old_pcap.inheritable = old->cap_inheritable; ax->old_pcap.inheritable = old->cap_inheritable;
ax->old_pcap.effective = old->cap_effective; ax->old_pcap.effective = old->cap_effective;
ax->old_pcap.ambient = old->cap_ambient;
ax->new_pcap.permitted = new->cap_permitted; ax->new_pcap.permitted = new->cap_permitted;
ax->new_pcap.inheritable = new->cap_inheritable; ax->new_pcap.inheritable = new->cap_inheritable;
ax->new_pcap.effective = new->cap_effective; ax->new_pcap.effective = new->cap_effective;
ax->new_pcap.ambient = new->cap_ambient;
return 0; return 0;
} }
...@@ -2364,6 +2369,7 @@ void __audit_log_capset(const struct cred *new, const struct cred *old) ...@@ -2364,6 +2369,7 @@ void __audit_log_capset(const struct cred *new, const struct cred *old)
context->capset.cap.effective = new->cap_effective; context->capset.cap.effective = new->cap_effective;
context->capset.cap.inheritable = new->cap_effective; context->capset.cap.inheritable = new->cap_effective;
context->capset.cap.permitted = new->cap_permitted; context->capset.cap.permitted = new->cap_permitted;
context->capset.cap.ambient = new->cap_ambient;
context->type = AUDIT_CAPSET; context->type = AUDIT_CAPSET;
} }
......
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