mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
Merge branch 'upstream' of git://git.infradead.org/users/pcmoore/audit
Pull audit fixes from Paul Moore: "Seven audit patches for v4.1, all bug fixes. The largest, and perhaps most significant commit helps resolve some memory pressure issues related to the inode cache and audit, there are also a few small commits which help resolve some timing issues with the audit log queue, and the rest fall into the always popular "code clean-up" category. In general, nothing really substantial, just a nice set of maintenance patches" * 'upstream' of git://git.infradead.org/users/pcmoore/audit: audit: Remove condition which always evaluates to false audit: reduce mmap_sem hold for mm->exe_file audit: consolidate handling of mm->exe_file audit: code clean up audit: don't reset working wait time accidentally with auditd audit: don't lose set wait time on first successful call to audit_log_start() audit: move the tree pruning to a dedicated thread
This commit is contained in:
@@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
#include <linux/file.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
@@ -107,6 +108,7 @@ static u32 audit_rate_limit;
|
|||||||
* When set to zero, this means unlimited. */
|
* When set to zero, this means unlimited. */
|
||||||
static u32 audit_backlog_limit = 64;
|
static u32 audit_backlog_limit = 64;
|
||||||
#define AUDIT_BACKLOG_WAIT_TIME (60 * HZ)
|
#define AUDIT_BACKLOG_WAIT_TIME (60 * HZ)
|
||||||
|
static u32 audit_backlog_wait_time_master = AUDIT_BACKLOG_WAIT_TIME;
|
||||||
static u32 audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
|
static u32 audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
|
||||||
static u32 audit_backlog_wait_overflow = 0;
|
static u32 audit_backlog_wait_overflow = 0;
|
||||||
|
|
||||||
@@ -338,13 +340,13 @@ static int audit_set_backlog_limit(u32 limit)
|
|||||||
static int audit_set_backlog_wait_time(u32 timeout)
|
static int audit_set_backlog_wait_time(u32 timeout)
|
||||||
{
|
{
|
||||||
return audit_do_config_change("audit_backlog_wait_time",
|
return audit_do_config_change("audit_backlog_wait_time",
|
||||||
&audit_backlog_wait_time, timeout);
|
&audit_backlog_wait_time_master, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audit_set_enabled(u32 state)
|
static int audit_set_enabled(u32 state)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
if (state < AUDIT_OFF || state > AUDIT_LOCKED)
|
if (state > AUDIT_LOCKED)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
rc = audit_do_config_change("audit_enabled", &audit_enabled, state);
|
rc = audit_do_config_change("audit_enabled", &audit_enabled, state);
|
||||||
@@ -663,7 +665,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
|
|||||||
case AUDIT_MAKE_EQUIV:
|
case AUDIT_MAKE_EQUIV:
|
||||||
/* Only support auditd and auditctl in initial pid namespace
|
/* Only support auditd and auditctl in initial pid namespace
|
||||||
* for now. */
|
* for now. */
|
||||||
if ((task_active_pid_ns(current) != &init_pid_ns))
|
if (task_active_pid_ns(current) != &init_pid_ns)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
if (!netlink_capable(skb, CAP_AUDIT_CONTROL))
|
if (!netlink_capable(skb, CAP_AUDIT_CONTROL))
|
||||||
@@ -834,7 +836,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||||||
s.lost = atomic_read(&audit_lost);
|
s.lost = atomic_read(&audit_lost);
|
||||||
s.backlog = skb_queue_len(&audit_skb_queue);
|
s.backlog = skb_queue_len(&audit_skb_queue);
|
||||||
s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL;
|
s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL;
|
||||||
s.backlog_wait_time = audit_backlog_wait_time;
|
s.backlog_wait_time = audit_backlog_wait_time_master;
|
||||||
audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s));
|
audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -877,8 +879,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||||||
if (s.mask & AUDIT_STATUS_BACKLOG_WAIT_TIME) {
|
if (s.mask & AUDIT_STATUS_BACKLOG_WAIT_TIME) {
|
||||||
if (sizeof(s) > (size_t)nlh->nlmsg_len)
|
if (sizeof(s) > (size_t)nlh->nlmsg_len)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (s.backlog_wait_time < 0 ||
|
if (s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME)
|
||||||
s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
err = audit_set_backlog_wait_time(s.backlog_wait_time);
|
err = audit_set_backlog_wait_time(s.backlog_wait_time);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@@ -1385,7 +1386,8 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
|
if (!reserve)
|
||||||
|
audit_backlog_wait_time = audit_backlog_wait_time_master;
|
||||||
|
|
||||||
ab = audit_buffer_alloc(ctx, gfp_mask, type);
|
ab = audit_buffer_alloc(ctx, gfp_mask, type);
|
||||||
if (!ab) {
|
if (!ab) {
|
||||||
@@ -1759,7 +1761,7 @@ void audit_log_name(struct audit_context *context, struct audit_names *n,
|
|||||||
} else
|
} else
|
||||||
audit_log_format(ab, " name=(null)");
|
audit_log_format(ab, " name=(null)");
|
||||||
|
|
||||||
if (n->ino != (unsigned long)-1) {
|
if (n->ino != (unsigned long)-1)
|
||||||
audit_log_format(ab, " inode=%lu"
|
audit_log_format(ab, " inode=%lu"
|
||||||
" dev=%02x:%02x mode=%#ho"
|
" dev=%02x:%02x mode=%#ho"
|
||||||
" ouid=%u ogid=%u rdev=%02x:%02x",
|
" ouid=%u ogid=%u rdev=%02x:%02x",
|
||||||
@@ -1771,7 +1773,6 @@ void audit_log_name(struct audit_context *context, struct audit_names *n,
|
|||||||
from_kgid(&init_user_ns, n->gid),
|
from_kgid(&init_user_ns, n->gid),
|
||||||
MAJOR(n->rdev),
|
MAJOR(n->rdev),
|
||||||
MINOR(n->rdev));
|
MINOR(n->rdev));
|
||||||
}
|
|
||||||
if (n->osid != 0) {
|
if (n->osid != 0) {
|
||||||
char *ctx = NULL;
|
char *ctx = NULL;
|
||||||
u32 len;
|
u32 len;
|
||||||
@@ -1838,11 +1839,29 @@ error_path:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(audit_log_task_context);
|
EXPORT_SYMBOL(audit_log_task_context);
|
||||||
|
|
||||||
|
void audit_log_d_path_exe(struct audit_buffer *ab,
|
||||||
|
struct mm_struct *mm)
|
||||||
|
{
|
||||||
|
struct file *exe_file;
|
||||||
|
|
||||||
|
if (!mm)
|
||||||
|
goto out_null;
|
||||||
|
|
||||||
|
exe_file = get_mm_exe_file(mm);
|
||||||
|
if (!exe_file)
|
||||||
|
goto out_null;
|
||||||
|
|
||||||
|
audit_log_d_path(ab, " exe=", &exe_file->f_path);
|
||||||
|
fput(exe_file);
|
||||||
|
return;
|
||||||
|
out_null:
|
||||||
|
audit_log_format(ab, " exe=(null)");
|
||||||
|
}
|
||||||
|
|
||||||
void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
|
void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
|
||||||
{
|
{
|
||||||
const struct cred *cred;
|
const struct cred *cred;
|
||||||
char comm[sizeof(tsk->comm)];
|
char comm[sizeof(tsk->comm)];
|
||||||
struct mm_struct *mm = tsk->mm;
|
|
||||||
char *tty;
|
char *tty;
|
||||||
|
|
||||||
if (!ab)
|
if (!ab)
|
||||||
@@ -1878,13 +1897,7 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
|
|||||||
audit_log_format(ab, " comm=");
|
audit_log_format(ab, " comm=");
|
||||||
audit_log_untrustedstring(ab, get_task_comm(comm, tsk));
|
audit_log_untrustedstring(ab, get_task_comm(comm, tsk));
|
||||||
|
|
||||||
if (mm) {
|
audit_log_d_path_exe(ab, tsk->mm);
|
||||||
down_read(&mm->mmap_sem);
|
|
||||||
if (mm->exe_file)
|
|
||||||
audit_log_d_path(ab, " exe=", &mm->exe_file->f_path);
|
|
||||||
up_read(&mm->mmap_sem);
|
|
||||||
} else
|
|
||||||
audit_log_format(ab, " exe=(null)");
|
|
||||||
audit_log_task_context(ab);
|
audit_log_task_context(ab);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(audit_log_task_info);
|
EXPORT_SYMBOL(audit_log_task_info);
|
||||||
|
@@ -257,6 +257,9 @@ 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);
|
||||||
|
|
||||||
|
extern void audit_log_d_path_exe(struct audit_buffer *ab,
|
||||||
|
struct mm_struct *mm);
|
||||||
|
|
||||||
/* audit watch functions */
|
/* audit watch functions */
|
||||||
#ifdef CONFIG_AUDIT_WATCH
|
#ifdef CONFIG_AUDIT_WATCH
|
||||||
extern void audit_put_watch(struct audit_watch *watch);
|
extern void audit_put_watch(struct audit_watch *watch);
|
||||||
|
@@ -37,6 +37,7 @@ struct audit_chunk {
|
|||||||
|
|
||||||
static LIST_HEAD(tree_list);
|
static LIST_HEAD(tree_list);
|
||||||
static LIST_HEAD(prune_list);
|
static LIST_HEAD(prune_list);
|
||||||
|
static struct task_struct *prune_thread;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* One struct chunk is attached to each inode of interest.
|
* One struct chunk is attached to each inode of interest.
|
||||||
@@ -651,6 +652,57 @@ static int tag_mount(struct vfsmount *mnt, void *arg)
|
|||||||
return tag_chunk(mnt->mnt_root->d_inode, arg);
|
return tag_chunk(mnt->mnt_root->d_inode, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* That gets run when evict_chunk() ends up needing to kill audit_tree.
|
||||||
|
* Runs from a separate thread.
|
||||||
|
*/
|
||||||
|
static int prune_tree_thread(void *unused)
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
if (list_empty(&prune_list))
|
||||||
|
schedule();
|
||||||
|
__set_current_state(TASK_RUNNING);
|
||||||
|
|
||||||
|
mutex_lock(&audit_cmd_mutex);
|
||||||
|
mutex_lock(&audit_filter_mutex);
|
||||||
|
|
||||||
|
while (!list_empty(&prune_list)) {
|
||||||
|
struct audit_tree *victim;
|
||||||
|
|
||||||
|
victim = list_entry(prune_list.next,
|
||||||
|
struct audit_tree, list);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int audit_launch_prune(void)
|
||||||
|
{
|
||||||
|
if (prune_thread)
|
||||||
|
return 0;
|
||||||
|
prune_thread = kthread_create(prune_tree_thread, NULL,
|
||||||
|
"audit_prune_tree");
|
||||||
|
if (IS_ERR(prune_thread)) {
|
||||||
|
pr_err("cannot start thread audit_prune_tree");
|
||||||
|
prune_thread = NULL;
|
||||||
|
return -ENOMEM;
|
||||||
|
} else {
|
||||||
|
wake_up_process(prune_thread);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* called with audit_filter_mutex */
|
/* called with audit_filter_mutex */
|
||||||
int audit_add_tree_rule(struct audit_krule *rule)
|
int audit_add_tree_rule(struct audit_krule *rule)
|
||||||
{
|
{
|
||||||
@@ -674,6 +726,12 @@ int audit_add_tree_rule(struct audit_krule *rule)
|
|||||||
/* do not set rule->tree yet */
|
/* do not set rule->tree yet */
|
||||||
mutex_unlock(&audit_filter_mutex);
|
mutex_unlock(&audit_filter_mutex);
|
||||||
|
|
||||||
|
if (unlikely(!prune_thread)) {
|
||||||
|
err = audit_launch_prune();
|
||||||
|
if (err)
|
||||||
|
goto Err;
|
||||||
|
}
|
||||||
|
|
||||||
err = kern_path(tree->pathname, 0, &path);
|
err = kern_path(tree->pathname, 0, &path);
|
||||||
if (err)
|
if (err)
|
||||||
goto Err;
|
goto Err;
|
||||||
@@ -811,36 +869,10 @@ int audit_tag_tree(char *old, char *new)
|
|||||||
return failed;
|
return failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* That gets run when evict_chunk() ends up needing to kill audit_tree.
|
|
||||||
* Runs from a separate thread.
|
|
||||||
*/
|
|
||||||
static int prune_tree_thread(void *unused)
|
|
||||||
{
|
|
||||||
mutex_lock(&audit_cmd_mutex);
|
|
||||||
mutex_lock(&audit_filter_mutex);
|
|
||||||
|
|
||||||
while (!list_empty(&prune_list)) {
|
|
||||||
struct audit_tree *victim;
|
|
||||||
|
|
||||||
victim = list_entry(prune_list.next, struct audit_tree, list);
|
|
||||||
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);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void audit_schedule_prune(void)
|
static void audit_schedule_prune(void)
|
||||||
{
|
{
|
||||||
kthread_run(prune_tree_thread, NULL, "audit_prune_tree");
|
wake_up_process(prune_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -907,9 +939,9 @@ static void evict_chunk(struct audit_chunk *chunk)
|
|||||||
for (n = 0; n < chunk->count; n++)
|
for (n = 0; n < chunk->count; n++)
|
||||||
list_del_init(&chunk->owners[n].list);
|
list_del_init(&chunk->owners[n].list);
|
||||||
spin_unlock(&hash_lock);
|
spin_unlock(&hash_lock);
|
||||||
|
mutex_unlock(&audit_filter_mutex);
|
||||||
if (need_prune)
|
if (need_prune)
|
||||||
audit_schedule_prune();
|
audit_schedule_prune();
|
||||||
mutex_unlock(&audit_filter_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audit_tree_handle_event(struct fsnotify_group *group,
|
static int audit_tree_handle_event(struct fsnotify_group *group,
|
||||||
|
@@ -2361,7 +2361,6 @@ static void audit_log_task(struct audit_buffer *ab)
|
|||||||
kuid_t auid, uid;
|
kuid_t auid, uid;
|
||||||
kgid_t gid;
|
kgid_t gid;
|
||||||
unsigned int sessionid;
|
unsigned int sessionid;
|
||||||
struct mm_struct *mm = current->mm;
|
|
||||||
char comm[sizeof(current->comm)];
|
char comm[sizeof(current->comm)];
|
||||||
|
|
||||||
auid = audit_get_loginuid(current);
|
auid = audit_get_loginuid(current);
|
||||||
@@ -2376,13 +2375,7 @@ static void audit_log_task(struct audit_buffer *ab)
|
|||||||
audit_log_task_context(ab);
|
audit_log_task_context(ab);
|
||||||
audit_log_format(ab, " pid=%d comm=", task_pid_nr(current));
|
audit_log_format(ab, " pid=%d comm=", task_pid_nr(current));
|
||||||
audit_log_untrustedstring(ab, get_task_comm(comm, current));
|
audit_log_untrustedstring(ab, get_task_comm(comm, current));
|
||||||
if (mm) {
|
audit_log_d_path_exe(ab, current->mm);
|
||||||
down_read(&mm->mmap_sem);
|
|
||||||
if (mm->exe_file)
|
|
||||||
audit_log_d_path(ab, " exe=", &mm->exe_file->f_path);
|
|
||||||
up_read(&mm->mmap_sem);
|
|
||||||
} else
|
|
||||||
audit_log_format(ab, " exe=(null)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user