Commit 847f8776 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 79346507 120a795d
......@@ -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)
......
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