Merge branch 'audit.b64' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current
* 'audit.b64' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current: audit mmap audit: make link()/linkat() match "attribute change" predicate audit: Use rcu for task lookup protection audit: Do not send uninitialized data for AUDIT_TTY_GET audit: Call tty_audit_push_task() outside preempt disabled in untag_chunk() we need to do alloc_chunk() a bit earlier audit: make functions static Audit: add support to match lsm labels on user audit messages
This commit is contained in:
commit
847f877600
|
@ -188,25 +188,43 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch)
|
|||
}
|
||||
|
||||
/**
|
||||
* tty_audit_push_task - Flush task's pending audit data
|
||||
* tty_audit_push_task - Flush task's pending audit data
|
||||
* @tsk: task pointer
|
||||
* @loginuid: sender login uid
|
||||
* @sessionid: sender session id
|
||||
*
|
||||
* Called with a ref on @tsk held. Try to lock sighand and get a
|
||||
* reference to the tty audit buffer if available.
|
||||
* Flush the buffer or return an appropriate error code.
|
||||
*/
|
||||
void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
|
||||
int tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
|
||||
{
|
||||
struct tty_audit_buf *buf;
|
||||
struct tty_audit_buf *buf = ERR_PTR(-EPERM);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
buf = tsk->signal->tty_audit_buf;
|
||||
if (buf)
|
||||
atomic_inc(&buf->count);
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
if (!buf)
|
||||
return;
|
||||
if (!lock_task_sighand(tsk, &flags))
|
||||
return -ESRCH;
|
||||
|
||||
if (tsk->signal->audit_tty) {
|
||||
buf = tsk->signal->tty_audit_buf;
|
||||
if (buf)
|
||||
atomic_inc(&buf->count);
|
||||
}
|
||||
unlock_task_sighand(tsk, &flags);
|
||||
|
||||
/*
|
||||
* Return 0 when signal->audit_tty set
|
||||
* but tsk->signal->tty_audit_buf == NULL.
|
||||
*/
|
||||
if (!buf || IS_ERR(buf))
|
||||
return PTR_ERR(buf);
|
||||
|
||||
mutex_lock(&buf->mutex);
|
||||
tty_audit_buf_push(tsk, loginuid, sessionid, buf);
|
||||
mutex_unlock(&buf->mutex);
|
||||
|
||||
tty_audit_buf_put(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,3 +20,7 @@ __NR_chown32,
|
|||
__NR_fchown32,
|
||||
__NR_lchown32,
|
||||
#endif
|
||||
__NR_link,
|
||||
#ifdef __NR_linkat
|
||||
__NR_linkat,
|
||||
#endif
|
||||
|
|
|
@ -102,6 +102,7 @@
|
|||
#define AUDIT_EOE 1320 /* End of multi-record event */
|
||||
#define AUDIT_BPRM_FCAPS 1321 /* Information about fcaps increasing perms */
|
||||
#define AUDIT_CAPSET 1322 /* Record showing argument to sys_capset */
|
||||
#define AUDIT_MMAP 1323 /* Record showing descriptor and flags in mmap */
|
||||
|
||||
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
|
||||
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
|
||||
|
@ -478,6 +479,7 @@ extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
|
|||
const struct cred *new,
|
||||
const struct cred *old);
|
||||
extern void __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old);
|
||||
extern void __audit_mmap_fd(int fd, int flags);
|
||||
|
||||
static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
|
||||
{
|
||||
|
@ -531,6 +533,12 @@ static inline void audit_log_capset(pid_t pid, const struct cred *new,
|
|||
__audit_log_capset(pid, new, old);
|
||||
}
|
||||
|
||||
static inline void audit_mmap_fd(int fd, int flags)
|
||||
{
|
||||
if (unlikely(!audit_dummy_context()))
|
||||
__audit_mmap_fd(fd, flags);
|
||||
}
|
||||
|
||||
extern int audit_n_rules;
|
||||
extern int audit_signals;
|
||||
#else
|
||||
|
@ -564,6 +572,7 @@ extern int audit_signals;
|
|||
#define audit_mq_getsetattr(d,s) ((void)0)
|
||||
#define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
|
||||
#define audit_log_capset(pid, ncr, ocr) ((void)0)
|
||||
#define audit_mmap_fd(fd, flags) ((void)0)
|
||||
#define audit_ptrace(t) ((void)0)
|
||||
#define audit_n_rules 0
|
||||
#define audit_signals 0
|
||||
|
|
|
@ -541,8 +541,8 @@ extern void tty_audit_exit(void);
|
|||
extern void tty_audit_fork(struct signal_struct *sig);
|
||||
extern void tty_audit_tiocsti(struct tty_struct *tty, char ch);
|
||||
extern void tty_audit_push(struct tty_struct *tty);
|
||||
extern void tty_audit_push_task(struct task_struct *tsk,
|
||||
uid_t loginuid, u32 sessionid);
|
||||
extern int tty_audit_push_task(struct task_struct *tsk,
|
||||
uid_t loginuid, u32 sessionid);
|
||||
#else
|
||||
static inline void tty_audit_add_data(struct tty_struct *tty,
|
||||
unsigned char *data, size_t size)
|
||||
|
@ -560,9 +560,10 @@ static inline void tty_audit_fork(struct signal_struct *sig)
|
|||
static inline void tty_audit_push(struct tty_struct *tty)
|
||||
{
|
||||
}
|
||||
static inline void tty_audit_push_task(struct task_struct *tsk,
|
||||
uid_t loginuid, u32 sessionid)
|
||||
static inline int tty_audit_push_task(struct task_struct *tsk,
|
||||
uid_t loginuid, u32 sessionid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -467,23 +467,16 @@ static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid)
|
|||
struct task_struct *tsk;
|
||||
int err;
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
rcu_read_lock();
|
||||
tsk = find_task_by_vpid(pid);
|
||||
err = -ESRCH;
|
||||
if (!tsk)
|
||||
goto out;
|
||||
err = 0;
|
||||
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
if (!tsk->signal->audit_tty)
|
||||
err = -EPERM;
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
tty_audit_push_task(tsk, loginuid, sessionid);
|
||||
out:
|
||||
read_unlock(&tasklist_lock);
|
||||
if (!tsk) {
|
||||
rcu_read_unlock();
|
||||
return -ESRCH;
|
||||
}
|
||||
get_task_struct(tsk);
|
||||
rcu_read_unlock();
|
||||
err = tty_audit_push_task(tsk, loginuid, sessionid);
|
||||
put_task_struct(tsk);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -506,7 +499,7 @@ int audit_send_list(void *_dest)
|
|||
}
|
||||
|
||||
struct sk_buff *audit_make_reply(int pid, int seq, int type, int done,
|
||||
int multi, void *payload, int size)
|
||||
int multi, const void *payload, int size)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct nlmsghdr *nlh;
|
||||
|
@ -555,8 +548,8 @@ static int audit_send_reply_thread(void *arg)
|
|||
* Allocates an skb, builds the netlink message, and sends it to the pid.
|
||||
* No failure notifications.
|
||||
*/
|
||||
void audit_send_reply(int pid, int seq, int type, int done, int multi,
|
||||
void *payload, int size)
|
||||
static void audit_send_reply(int pid, int seq, int type, int done, int multi,
|
||||
const void *payload, int size)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct task_struct *tsk;
|
||||
|
@ -880,40 +873,40 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||
case AUDIT_TTY_GET: {
|
||||
struct audit_tty_status s;
|
||||
struct task_struct *tsk;
|
||||
unsigned long flags;
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
rcu_read_lock();
|
||||
tsk = find_task_by_vpid(pid);
|
||||
if (!tsk)
|
||||
err = -ESRCH;
|
||||
else {
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
if (tsk && lock_task_sighand(tsk, &flags)) {
|
||||
s.enabled = tsk->signal->audit_tty != 0;
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
}
|
||||
read_unlock(&tasklist_lock);
|
||||
audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_TTY_GET, 0, 0,
|
||||
&s, sizeof(s));
|
||||
unlock_task_sighand(tsk, &flags);
|
||||
} else
|
||||
err = -ESRCH;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!err)
|
||||
audit_send_reply(NETLINK_CB(skb).pid, seq,
|
||||
AUDIT_TTY_GET, 0, 0, &s, sizeof(s));
|
||||
break;
|
||||
}
|
||||
case AUDIT_TTY_SET: {
|
||||
struct audit_tty_status *s;
|
||||
struct task_struct *tsk;
|
||||
unsigned long flags;
|
||||
|
||||
if (nlh->nlmsg_len < sizeof(struct audit_tty_status))
|
||||
return -EINVAL;
|
||||
s = data;
|
||||
if (s->enabled != 0 && s->enabled != 1)
|
||||
return -EINVAL;
|
||||
read_lock(&tasklist_lock);
|
||||
rcu_read_lock();
|
||||
tsk = find_task_by_vpid(pid);
|
||||
if (!tsk)
|
||||
err = -ESRCH;
|
||||
else {
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
if (tsk && lock_task_sighand(tsk, &flags)) {
|
||||
tsk->signal->audit_tty = s->enabled != 0;
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
}
|
||||
read_unlock(&tasklist_lock);
|
||||
unlock_task_sighand(tsk, &flags);
|
||||
} else
|
||||
err = -ESRCH;
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -84,10 +84,7 @@ extern int audit_compare_dname_path(const char *dname, const char *path,
|
|||
int *dirlen);
|
||||
extern struct sk_buff * audit_make_reply(int pid, int seq, int type,
|
||||
int done, int multi,
|
||||
void *payload, int size);
|
||||
extern void audit_send_reply(int pid, int seq, int type,
|
||||
int done, int multi,
|
||||
void *payload, int size);
|
||||
const void *payload, int size);
|
||||
extern void audit_panic(const char *message);
|
||||
|
||||
struct audit_netlink_list {
|
||||
|
|
|
@ -223,7 +223,7 @@ static void untag_chunk(struct node *p)
|
|||
{
|
||||
struct audit_chunk *chunk = find_chunk(p);
|
||||
struct fsnotify_mark *entry = &chunk->mark;
|
||||
struct audit_chunk *new;
|
||||
struct audit_chunk *new = NULL;
|
||||
struct audit_tree *owner;
|
||||
int size = chunk->count - 1;
|
||||
int i, j;
|
||||
|
@ -232,9 +232,14 @@ static void untag_chunk(struct node *p)
|
|||
|
||||
spin_unlock(&hash_lock);
|
||||
|
||||
if (size)
|
||||
new = alloc_chunk(size);
|
||||
|
||||
spin_lock(&entry->lock);
|
||||
if (chunk->dead || !entry->i.inode) {
|
||||
spin_unlock(&entry->lock);
|
||||
if (new)
|
||||
free_chunk(new);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -255,9 +260,9 @@ static void untag_chunk(struct node *p)
|
|||
goto out;
|
||||
}
|
||||
|
||||
new = alloc_chunk(size);
|
||||
if (!new)
|
||||
goto Fallback;
|
||||
|
||||
fsnotify_duplicate_mark(&new->mark, entry);
|
||||
if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) {
|
||||
free_chunk(new);
|
||||
|
|
|
@ -60,7 +60,7 @@ struct audit_parent {
|
|||
};
|
||||
|
||||
/* fsnotify handle. */
|
||||
struct fsnotify_group *audit_watch_group;
|
||||
static struct fsnotify_group *audit_watch_group;
|
||||
|
||||
/* fsnotify events we care about. */
|
||||
#define AUDIT_FS_WATCH (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\
|
||||
|
@ -123,7 +123,7 @@ void audit_put_watch(struct audit_watch *watch)
|
|||
}
|
||||
}
|
||||
|
||||
void audit_remove_watch(struct audit_watch *watch)
|
||||
static void audit_remove_watch(struct audit_watch *watch)
|
||||
{
|
||||
list_del(&watch->wlist);
|
||||
audit_put_parent(watch->parent);
|
||||
|
|
|
@ -1252,6 +1252,18 @@ static int audit_filter_user_rules(struct netlink_skb_parms *cb,
|
|||
case AUDIT_LOGINUID:
|
||||
result = audit_comparator(cb->loginuid, f->op, f->val);
|
||||
break;
|
||||
case AUDIT_SUBJ_USER:
|
||||
case AUDIT_SUBJ_ROLE:
|
||||
case AUDIT_SUBJ_TYPE:
|
||||
case AUDIT_SUBJ_SEN:
|
||||
case AUDIT_SUBJ_CLR:
|
||||
if (f->lsm_rule)
|
||||
result = security_audit_rule_match(cb->sid,
|
||||
f->type,
|
||||
f->op,
|
||||
f->lsm_rule,
|
||||
NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!result)
|
||||
|
|
|
@ -241,6 +241,10 @@ struct audit_context {
|
|||
pid_t pid;
|
||||
struct audit_cap_data cap;
|
||||
} capset;
|
||||
struct {
|
||||
int fd;
|
||||
int flags;
|
||||
} mmap;
|
||||
};
|
||||
int fds[2];
|
||||
|
||||
|
@ -1305,6 +1309,10 @@ static void show_special(struct audit_context *context, int *call_panic)
|
|||
audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted);
|
||||
audit_log_cap(ab, "cap_pe", &context->capset.cap.effective);
|
||||
break; }
|
||||
case AUDIT_MMAP: {
|
||||
audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd,
|
||||
context->mmap.flags);
|
||||
break; }
|
||||
}
|
||||
audit_log_end(ab);
|
||||
}
|
||||
|
@ -2476,6 +2484,14 @@ void __audit_log_capset(pid_t pid,
|
|||
context->type = AUDIT_CAPSET;
|
||||
}
|
||||
|
||||
void __audit_mmap_fd(int fd, int flags)
|
||||
{
|
||||
struct audit_context *context = current->audit_context;
|
||||
context->mmap.fd = fd;
|
||||
context->mmap.flags = flags;
|
||||
context->type = AUDIT_MMAP;
|
||||
}
|
||||
|
||||
/**
|
||||
* audit_core_dumps - record information about processes that end abnormally
|
||||
* @signr: signal value
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/rmap.h>
|
||||
#include <linux/mmu_notifier.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/audit.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
@ -1108,6 +1109,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
|
|||
unsigned long retval = -EBADF;
|
||||
|
||||
if (!(flags & MAP_ANONYMOUS)) {
|
||||
audit_mmap_fd(fd, flags);
|
||||
if (unlikely(flags & MAP_HUGETLB))
|
||||
return -EINVAL;
|
||||
file = fget(fd);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/personality.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/audit.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/tlb.h>
|
||||
|
@ -1458,6 +1459,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
|
|||
struct file *file = NULL;
|
||||
unsigned long retval = -EBADF;
|
||||
|
||||
audit_mmap_fd(fd, flags);
|
||||
if (!(flags & MAP_ANONYMOUS)) {
|
||||
file = fget(fd);
|
||||
if (!file)
|
||||
|
|
Loading…
Reference in a new issue