You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'audit.b63' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current
* 'audit.b63' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current: Fix rule eviction order for AUDIT_DIR Audit: clean up all op= output to include string quoting Audit: move audit_get_nd completely into audit_watch audit: seperate audit inode watches into a subfile Audit: clean up audit_receive_skb Audit: cleanup netlink mesg handling Audit: unify the printk of an skb when auditd not around Audit: dereferencing krule as if it were an audit_watch Audit: better estimation of execve record length Audit: fix audit watch use after free
This commit is contained in:
@@ -599,6 +599,8 @@ extern void audit_log_untrustedstring(struct audit_buffer *ab,
|
||||
extern void audit_log_d_path(struct audit_buffer *ab,
|
||||
const char *prefix,
|
||||
struct path *path);
|
||||
extern void audit_log_key(struct audit_buffer *ab,
|
||||
char *key);
|
||||
extern void audit_log_lost(const char *message);
|
||||
extern int audit_update_lsm_rules(void);
|
||||
|
||||
@@ -621,6 +623,7 @@ extern int audit_enabled;
|
||||
#define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
|
||||
#define audit_log_untrustedstring(a,s) do { ; } while (0)
|
||||
#define audit_log_d_path(b, p, d) do { ; } while (0)
|
||||
#define audit_log_key(b, k) do { ; } while (0)
|
||||
#define audit_enabled 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o
|
||||
obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
|
||||
obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
|
||||
obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
|
||||
obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
|
||||
obj-$(CONFIG_AUDITSYSCALL) += auditsc.o audit_watch.o
|
||||
obj-$(CONFIG_GCOV_KERNEL) += gcov/
|
||||
obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o
|
||||
|
||||
+65
-81
@@ -115,9 +115,6 @@ static atomic_t audit_lost = ATOMIC_INIT(0);
|
||||
/* The netlink socket. */
|
||||
static struct sock *audit_sock;
|
||||
|
||||
/* Inotify handle. */
|
||||
struct inotify_handle *audit_ih;
|
||||
|
||||
/* Hash for inode-based rules */
|
||||
struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
|
||||
|
||||
@@ -136,7 +133,7 @@ static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
|
||||
static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
|
||||
|
||||
/* Serialize requests from userspace. */
|
||||
static DEFINE_MUTEX(audit_cmd_mutex);
|
||||
DEFINE_MUTEX(audit_cmd_mutex);
|
||||
|
||||
/* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting
|
||||
* audit records. Since printk uses a 1024 byte buffer, this buffer
|
||||
@@ -375,6 +372,25 @@ static void audit_hold_skb(struct sk_buff *skb)
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/*
|
||||
* For one reason or another this nlh isn't getting delivered to the userspace
|
||||
* audit daemon, just send it to printk.
|
||||
*/
|
||||
static void audit_printk_skb(struct sk_buff *skb)
|
||||
{
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(skb);
|
||||
char *data = NLMSG_DATA(nlh);
|
||||
|
||||
if (nlh->nlmsg_type != AUDIT_EOE) {
|
||||
if (printk_ratelimit())
|
||||
printk(KERN_NOTICE "type=%d %s\n", nlh->nlmsg_type, data);
|
||||
else
|
||||
audit_log_lost("printk limit exceeded\n");
|
||||
}
|
||||
|
||||
audit_hold_skb(skb);
|
||||
}
|
||||
|
||||
static void kauditd_send_skb(struct sk_buff *skb)
|
||||
{
|
||||
int err;
|
||||
@@ -427,14 +443,8 @@ static int kauditd_thread(void *dummy)
|
||||
if (skb) {
|
||||
if (audit_pid)
|
||||
kauditd_send_skb(skb);
|
||||
else {
|
||||
if (printk_ratelimit())
|
||||
printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0));
|
||||
else
|
||||
audit_log_lost("printk limit exceeded\n");
|
||||
|
||||
audit_hold_skb(skb);
|
||||
}
|
||||
else
|
||||
audit_printk_skb(skb);
|
||||
} else {
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
@@ -495,42 +505,25 @@ int audit_send_list(void *_dest)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AUDIT_TREE
|
||||
static int prune_tree_thread(void *unused)
|
||||
{
|
||||
mutex_lock(&audit_cmd_mutex);
|
||||
audit_prune_trees();
|
||||
mutex_unlock(&audit_cmd_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void audit_schedule_prune(void)
|
||||
{
|
||||
kthread_run(prune_tree_thread, NULL, "audit_prune_tree");
|
||||
}
|
||||
#endif
|
||||
|
||||
struct sk_buff *audit_make_reply(int pid, int seq, int type, int done,
|
||||
int multi, void *payload, int size)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct nlmsghdr *nlh;
|
||||
int len = NLMSG_SPACE(size);
|
||||
void *data;
|
||||
int flags = multi ? NLM_F_MULTI : 0;
|
||||
int t = done ? NLMSG_DONE : type;
|
||||
|
||||
skb = alloc_skb(len, GFP_KERNEL);
|
||||
skb = nlmsg_new(size, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
nlh = NLMSG_PUT(skb, pid, seq, t, size);
|
||||
nlh->nlmsg_flags = flags;
|
||||
data = NLMSG_DATA(nlh);
|
||||
nlh = NLMSG_NEW(skb, pid, seq, t, size, flags);
|
||||
data = NLMSG_DATA(nlh);
|
||||
memcpy(data, payload, size);
|
||||
return skb;
|
||||
|
||||
nlmsg_failure: /* Used by NLMSG_PUT */
|
||||
nlmsg_failure: /* Used by NLMSG_NEW */
|
||||
if (skb)
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
@@ -926,28 +919,29 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
}
|
||||
|
||||
/*
|
||||
* Get message from skb (based on rtnetlink_rcv_skb). Each message is
|
||||
* processed by audit_receive_msg. Malformed skbs with wrong length are
|
||||
* discarded silently.
|
||||
* Get message from skb. Each message is processed by audit_receive_msg.
|
||||
* Malformed skbs with wrong length are discarded silently.
|
||||
*/
|
||||
static void audit_receive_skb(struct sk_buff *skb)
|
||||
{
|
||||
int err;
|
||||
struct nlmsghdr *nlh;
|
||||
u32 rlen;
|
||||
struct nlmsghdr *nlh;
|
||||
/*
|
||||
* len MUST be signed for NLMSG_NEXT to be able to dec it below 0
|
||||
* if the nlmsg_len was not aligned
|
||||
*/
|
||||
int len;
|
||||
int err;
|
||||
|
||||
while (skb->len >= NLMSG_SPACE(0)) {
|
||||
nlh = nlmsg_hdr(skb);
|
||||
if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
|
||||
return;
|
||||
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
|
||||
if (rlen > skb->len)
|
||||
rlen = skb->len;
|
||||
if ((err = audit_receive_msg(skb, nlh))) {
|
||||
nlh = nlmsg_hdr(skb);
|
||||
len = skb->len;
|
||||
|
||||
while (NLMSG_OK(nlh, len)) {
|
||||
err = audit_receive_msg(skb, nlh);
|
||||
/* if err or if this message says it wants a response */
|
||||
if (err || (nlh->nlmsg_flags & NLM_F_ACK))
|
||||
netlink_ack(skb, nlh, err);
|
||||
} else if (nlh->nlmsg_flags & NLM_F_ACK)
|
||||
netlink_ack(skb, nlh, 0);
|
||||
skb_pull(skb, rlen);
|
||||
|
||||
nlh = NLMSG_NEXT(nlh, len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -959,13 +953,6 @@ static void audit_receive(struct sk_buff *skb)
|
||||
mutex_unlock(&audit_cmd_mutex);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
static const struct inotify_operations audit_inotify_ops = {
|
||||
.handle_event = audit_handle_ievent,
|
||||
.destroy_watch = audit_free_parent,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Initialize audit support at boot time. */
|
||||
static int __init audit_init(void)
|
||||
{
|
||||
@@ -991,12 +978,6 @@ static int __init audit_init(void)
|
||||
|
||||
audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
|
||||
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
audit_ih = inotify_init(&audit_inotify_ops);
|
||||
if (IS_ERR(audit_ih))
|
||||
audit_panic("cannot initialize inotify handle");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
|
||||
INIT_LIST_HEAD(&audit_inode_hash[i]);
|
||||
|
||||
@@ -1070,18 +1051,20 @@ static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
|
||||
goto err;
|
||||
}
|
||||
|
||||
ab->skb = alloc_skb(AUDIT_BUFSIZ, gfp_mask);
|
||||
if (!ab->skb)
|
||||
goto err;
|
||||
|
||||
ab->ctx = ctx;
|
||||
ab->gfp_mask = gfp_mask;
|
||||
nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));
|
||||
nlh->nlmsg_type = type;
|
||||
nlh->nlmsg_flags = 0;
|
||||
nlh->nlmsg_pid = 0;
|
||||
nlh->nlmsg_seq = 0;
|
||||
|
||||
ab->skb = nlmsg_new(AUDIT_BUFSIZ, gfp_mask);
|
||||
if (!ab->skb)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nlh = NLMSG_NEW(ab->skb, 0, 0, type, 0, 0);
|
||||
|
||||
return ab;
|
||||
|
||||
nlmsg_failure: /* Used by NLMSG_NEW */
|
||||
kfree_skb(ab->skb);
|
||||
ab->skb = NULL;
|
||||
err:
|
||||
audit_buffer_free(ab);
|
||||
return NULL;
|
||||
@@ -1452,6 +1435,15 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
|
||||
kfree(pathname);
|
||||
}
|
||||
|
||||
void audit_log_key(struct audit_buffer *ab, char *key)
|
||||
{
|
||||
audit_log_format(ab, " key=");
|
||||
if (key)
|
||||
audit_log_untrustedstring(ab, key);
|
||||
else
|
||||
audit_log_format(ab, "(null)");
|
||||
}
|
||||
|
||||
/**
|
||||
* audit_log_end - end one audit record
|
||||
* @ab: the audit_buffer
|
||||
@@ -1475,15 +1467,7 @@ void audit_log_end(struct audit_buffer *ab)
|
||||
skb_queue_tail(&audit_skb_queue, ab->skb);
|
||||
wake_up_interruptible(&kauditd_wait);
|
||||
} else {
|
||||
if (nlh->nlmsg_type != AUDIT_EOE) {
|
||||
if (printk_ratelimit()) {
|
||||
printk(KERN_NOTICE "type=%d %s\n",
|
||||
nlh->nlmsg_type,
|
||||
ab->skb->data + NLMSG_SPACE(0));
|
||||
} else
|
||||
audit_log_lost("printk limit exceeded\n");
|
||||
}
|
||||
audit_hold_skb(ab->skb);
|
||||
audit_printk_skb(ab->skb);
|
||||
}
|
||||
ab->skb = NULL;
|
||||
}
|
||||
|
||||
+22
-21
@@ -53,18 +53,7 @@ enum audit_state {
|
||||
};
|
||||
|
||||
/* Rule lists */
|
||||
struct audit_parent;
|
||||
|
||||
struct audit_watch {
|
||||
atomic_t count; /* reference count */
|
||||
char *path; /* insertion path */
|
||||
dev_t dev; /* associated superblock device */
|
||||
unsigned long ino; /* associated inode number */
|
||||
struct audit_parent *parent; /* associated parent */
|
||||
struct list_head wlist; /* entry in parent->watches list */
|
||||
struct list_head rules; /* associated rules */
|
||||
};
|
||||
|
||||
struct audit_watch;
|
||||
struct audit_tree;
|
||||
struct audit_chunk;
|
||||
|
||||
@@ -108,19 +97,28 @@ struct audit_netlink_list {
|
||||
|
||||
int audit_send_list(void *);
|
||||
|
||||
struct inotify_watch;
|
||||
/* Inotify handle */
|
||||
extern struct inotify_handle *audit_ih;
|
||||
|
||||
extern void audit_free_parent(struct inotify_watch *);
|
||||
extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32,
|
||||
const char *, struct inode *);
|
||||
extern int selinux_audit_rule_update(void);
|
||||
|
||||
extern struct mutex audit_filter_mutex;
|
||||
extern void audit_free_rule_rcu(struct rcu_head *);
|
||||
extern struct list_head audit_filter_list[];
|
||||
|
||||
/* audit watch functions */
|
||||
extern unsigned long audit_watch_inode(struct audit_watch *watch);
|
||||
extern dev_t audit_watch_dev(struct audit_watch *watch);
|
||||
extern void audit_put_watch(struct audit_watch *watch);
|
||||
extern void audit_get_watch(struct audit_watch *watch);
|
||||
extern int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op);
|
||||
extern int audit_add_watch(struct audit_krule *krule);
|
||||
extern void audit_remove_watch(struct audit_watch *watch);
|
||||
extern void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list);
|
||||
extern void audit_inotify_unregister(struct list_head *in_list);
|
||||
extern char *audit_watch_path(struct audit_watch *watch);
|
||||
extern struct list_head *audit_watch_rules(struct audit_watch *watch);
|
||||
|
||||
extern struct audit_entry *audit_dupe_rule(struct audit_krule *old,
|
||||
struct audit_watch *watch);
|
||||
|
||||
#ifdef CONFIG_AUDIT_TREE
|
||||
extern struct audit_chunk *audit_tree_lookup(const struct inode *);
|
||||
extern void audit_put_chunk(struct audit_chunk *);
|
||||
@@ -130,10 +128,9 @@ extern int audit_add_tree_rule(struct audit_krule *);
|
||||
extern int audit_remove_tree_rule(struct audit_krule *);
|
||||
extern void audit_trim_trees(void);
|
||||
extern int audit_tag_tree(char *old, char *new);
|
||||
extern void audit_schedule_prune(void);
|
||||
extern void audit_prune_trees(void);
|
||||
extern const char *audit_tree_path(struct audit_tree *);
|
||||
extern void audit_put_tree(struct audit_tree *);
|
||||
extern void audit_kill_trees(struct list_head *);
|
||||
#else
|
||||
#define audit_remove_tree_rule(rule) BUG()
|
||||
#define audit_add_tree_rule(rule) -EINVAL
|
||||
@@ -142,6 +139,7 @@ extern void audit_put_tree(struct audit_tree *);
|
||||
#define audit_put_tree(tree) (void)0
|
||||
#define audit_tag_tree(old, new) -EINVAL
|
||||
#define audit_tree_path(rule) "" /* never called */
|
||||
#define audit_kill_trees(list) BUG()
|
||||
#endif
|
||||
|
||||
extern char *audit_unpack_string(void **, size_t *, size_t);
|
||||
@@ -160,7 +158,10 @@ static inline int audit_signal_info(int sig, struct task_struct *t)
|
||||
return 0;
|
||||
}
|
||||
extern void audit_filter_inodes(struct task_struct *, struct audit_context *);
|
||||
extern struct list_head *audit_killed_trees(void);
|
||||
#else
|
||||
#define audit_signal_info(s,t) AUDIT_DISABLED
|
||||
#define audit_filter_inodes(t,c) AUDIT_DISABLED
|
||||
#endif
|
||||
|
||||
extern struct mutex audit_cmd_mutex;
|
||||
|
||||
+55
-11
@@ -2,6 +2,7 @@
|
||||
#include <linux/inotify.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
struct audit_tree;
|
||||
struct audit_chunk;
|
||||
@@ -441,13 +442,11 @@ static void kill_rules(struct audit_tree *tree)
|
||||
if (rule->tree) {
|
||||
/* not a half-baked one */
|
||||
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
|
||||
audit_log_format(ab, "op=remove rule dir=");
|
||||
audit_log_format(ab, "op=");
|
||||
audit_log_string(ab, "remove rule");
|
||||
audit_log_format(ab, " dir=");
|
||||
audit_log_untrustedstring(ab, rule->tree->pathname);
|
||||
if (rule->filterkey) {
|
||||
audit_log_format(ab, " key=");
|
||||
audit_log_untrustedstring(ab, rule->filterkey);
|
||||
} else
|
||||
audit_log_format(ab, " key=(null)");
|
||||
audit_log_key(ab, rule->filterkey);
|
||||
audit_log_format(ab, " list=%d res=1", rule->listnr);
|
||||
audit_log_end(ab);
|
||||
rule->tree = NULL;
|
||||
@@ -519,6 +518,8 @@ static void trim_marked(struct audit_tree *tree)
|
||||
}
|
||||
}
|
||||
|
||||
static void audit_schedule_prune(void);
|
||||
|
||||
/* called with audit_filter_mutex */
|
||||
int audit_remove_tree_rule(struct audit_krule *rule)
|
||||
{
|
||||
@@ -824,10 +825,11 @@ int audit_tag_tree(char *old, char *new)
|
||||
|
||||
/*
|
||||
* That gets run when evict_chunk() ends up needing to kill audit_tree.
|
||||
* Runs from a separate thread, with audit_cmd_mutex held.
|
||||
* Runs from a separate thread.
|
||||
*/
|
||||
void audit_prune_trees(void)
|
||||
static int prune_tree_thread(void *unused)
|
||||
{
|
||||
mutex_lock(&audit_cmd_mutex);
|
||||
mutex_lock(&audit_filter_mutex);
|
||||
|
||||
while (!list_empty(&prune_list)) {
|
||||
@@ -844,6 +846,40 @@ void audit_prune_trees(void)
|
||||
}
|
||||
|
||||
mutex_unlock(&audit_filter_mutex);
|
||||
mutex_unlock(&audit_cmd_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void audit_schedule_prune(void)
|
||||
{
|
||||
kthread_run(prune_tree_thread, NULL, "audit_prune_tree");
|
||||
}
|
||||
|
||||
/*
|
||||
* ... and that one is done if evict_chunk() decides to delay until the end
|
||||
* of syscall. Runs synchronously.
|
||||
*/
|
||||
void audit_kill_trees(struct list_head *list)
|
||||
{
|
||||
mutex_lock(&audit_cmd_mutex);
|
||||
mutex_lock(&audit_filter_mutex);
|
||||
|
||||
while (!list_empty(list)) {
|
||||
struct audit_tree *victim;
|
||||
|
||||
victim = list_entry(list->next, struct audit_tree, list);
|
||||
kill_rules(victim);
|
||||
list_del_init(&victim->list);
|
||||
|
||||
mutex_unlock(&audit_filter_mutex);
|
||||
|
||||
prune_one(victim);
|
||||
|
||||
mutex_lock(&audit_filter_mutex);
|
||||
}
|
||||
|
||||
mutex_unlock(&audit_filter_mutex);
|
||||
mutex_unlock(&audit_cmd_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -854,6 +890,8 @@ void audit_prune_trees(void)
|
||||
static void evict_chunk(struct audit_chunk *chunk)
|
||||
{
|
||||
struct audit_tree *owner;
|
||||
struct list_head *postponed = audit_killed_trees();
|
||||
int need_prune = 0;
|
||||
int n;
|
||||
|
||||
if (chunk->dead)
|
||||
@@ -869,15 +907,21 @@ static void evict_chunk(struct audit_chunk *chunk)
|
||||
owner->root = NULL;
|
||||
list_del_init(&owner->same_root);
|
||||
spin_unlock(&hash_lock);
|
||||
kill_rules(owner);
|
||||
list_move(&owner->list, &prune_list);
|
||||
audit_schedule_prune();
|
||||
if (!postponed) {
|
||||
kill_rules(owner);
|
||||
list_move(&owner->list, &prune_list);
|
||||
need_prune = 1;
|
||||
} else {
|
||||
list_move(&owner->list, postponed);
|
||||
}
|
||||
spin_lock(&hash_lock);
|
||||
}
|
||||
list_del_rcu(&chunk->hash);
|
||||
for (n = 0; n < chunk->count; n++)
|
||||
list_del_init(&chunk->owners[n].list);
|
||||
spin_unlock(&hash_lock);
|
||||
if (need_prune)
|
||||
audit_schedule_prune();
|
||||
mutex_unlock(&audit_filter_mutex);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+22
-496
File diff suppressed because it is too large
Load Diff
+22
-11
@@ -199,6 +199,7 @@ struct audit_context {
|
||||
|
||||
struct audit_tree_refs *trees, *first_trees;
|
||||
int tree_count;
|
||||
struct list_head killed_trees;
|
||||
|
||||
int type;
|
||||
union {
|
||||
@@ -548,9 +549,9 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||
}
|
||||
break;
|
||||
case AUDIT_WATCH:
|
||||
if (name && rule->watch->ino != (unsigned long)-1)
|
||||
result = (name->dev == rule->watch->dev &&
|
||||
name->ino == rule->watch->ino);
|
||||
if (name && audit_watch_inode(rule->watch) != (unsigned long)-1)
|
||||
result = (name->dev == audit_watch_dev(rule->watch) &&
|
||||
name->ino == audit_watch_inode(rule->watch));
|
||||
break;
|
||||
case AUDIT_DIR:
|
||||
if (ctx)
|
||||
@@ -853,6 +854,7 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
|
||||
if (!(context = kmalloc(sizeof(*context), GFP_KERNEL)))
|
||||
return NULL;
|
||||
audit_zero_context(context, state);
|
||||
INIT_LIST_HEAD(&context->killed_trees);
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -1024,8 +1026,8 @@ static int audit_log_single_execve_arg(struct audit_context *context,
|
||||
{
|
||||
char arg_num_len_buf[12];
|
||||
const char __user *tmp_p = p;
|
||||
/* how many digits are in arg_num? 3 is the length of " a=" */
|
||||
size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 3;
|
||||
/* how many digits are in arg_num? 5 is the length of ' a=""' */
|
||||
size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 5;
|
||||
size_t len, len_left, to_send;
|
||||
size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN;
|
||||
unsigned int i, has_cntl = 0, too_long = 0;
|
||||
@@ -1137,7 +1139,7 @@ static int audit_log_single_execve_arg(struct audit_context *context,
|
||||
if (has_cntl)
|
||||
audit_log_n_hex(*ab, buf, to_send);
|
||||
else
|
||||
audit_log_format(*ab, "\"%s\"", buf);
|
||||
audit_log_string(*ab, buf);
|
||||
|
||||
p += to_send;
|
||||
len_left -= to_send;
|
||||
@@ -1372,11 +1374,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
|
||||
|
||||
|
||||
audit_log_task_info(ab, tsk);
|
||||
if (context->filterkey) {
|
||||
audit_log_format(ab, " key=");
|
||||
audit_log_untrustedstring(ab, context->filterkey);
|
||||
} else
|
||||
audit_log_format(ab, " key=(null)");
|
||||
audit_log_key(ab, context->filterkey);
|
||||
audit_log_end(ab);
|
||||
|
||||
for (aux = context->aux; aux; aux = aux->next) {
|
||||
@@ -1549,6 +1547,8 @@ void audit_free(struct task_struct *tsk)
|
||||
/* that can happen only if we are called from do_exit() */
|
||||
if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT)
|
||||
audit_log_exit(context, tsk);
|
||||
if (!list_empty(&context->killed_trees))
|
||||
audit_kill_trees(&context->killed_trees);
|
||||
|
||||
audit_free_context(context);
|
||||
}
|
||||
@@ -1692,6 +1692,9 @@ void audit_syscall_exit(int valid, long return_code)
|
||||
context->in_syscall = 0;
|
||||
context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
|
||||
|
||||
if (!list_empty(&context->killed_trees))
|
||||
audit_kill_trees(&context->killed_trees);
|
||||
|
||||
if (context->previous) {
|
||||
struct audit_context *new_context = context->previous;
|
||||
context->previous = NULL;
|
||||
@@ -2525,3 +2528,11 @@ void audit_core_dumps(long signr)
|
||||
audit_log_format(ab, " sig=%ld", signr);
|
||||
audit_log_end(ab);
|
||||
}
|
||||
|
||||
struct list_head *audit_killed_trees(void)
|
||||
{
|
||||
struct audit_context *ctx = current->audit_context;
|
||||
if (likely(!ctx || !ctx->in_syscall))
|
||||
return NULL;
|
||||
return &ctx->killed_trees;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user