Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe0bdec6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'audit.b61' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current:
  audit: validate comparison operations, store them in sane form
  clean up audit_rule_{add,del} a bit
  make sure that filterkey of task,always rules is reported
  audit rules ordering, part 2
  fixing audit rule ordering mess, part 1
  audit_update_lsm_rules() misses the audit_inode_hash[] ones
  sanitize audit_log_capset()
  sanitize audit_fd_pair()
  sanitize audit_mq_open()
  sanitize AUDIT_MQ_SENDRECV
  sanitize audit_mq_notify()
  sanitize audit_mq_getsetattr()
  sanitize audit_ipc_set_perm()
  sanitize audit_ipc_obj()
  sanitize audit_socketcall
  don't reallocate buffer in every audit_sockaddr()
parents 099e6576 5af75d8d
Loading
Loading
Loading
Loading
+1 −6
Original line number Diff line number Diff line
@@ -1016,10 +1016,7 @@ int do_pipe_flags(int *fd, int flags)
		goto err_fdr;
	fdw = error;

	error = audit_fd_pair(fdr, fdw);
	if (error < 0)
		goto err_fdw;

	audit_fd_pair(fdr, fdw);
	fd_install(fdr, fr);
	fd_install(fdw, fw);
	fd[0] = fdr;
@@ -1027,8 +1024,6 @@ int do_pipe_flags(int *fd, int flags)

	return 0;

 err_fdw:
	put_unused_fd(fdw);
 err_fdr:
	put_unused_fd(fdr);
 err_read_pipe:
+48 −50
Original line number Diff line number Diff line
@@ -247,6 +247,18 @@
#define AUDIT_GREATER_THAN_OR_EQUAL	(AUDIT_GREATER_THAN|AUDIT_EQUAL)
#define AUDIT_OPERATORS			(AUDIT_EQUAL|AUDIT_NOT_EQUAL|AUDIT_BIT_MASK)

enum {
	Audit_equal,
	Audit_not_equal,
	Audit_bitmask,
	Audit_bittest,
	Audit_lt,
	Audit_gt,
	Audit_le,
	Audit_ge,
	Audit_bad
};

/* Status symbols */
				/* Mask values */
#define AUDIT_STATUS_ENABLED		0x0001
@@ -373,6 +385,8 @@ struct audit_krule {
	struct audit_watch	*watch;	/* associated watch */
	struct audit_tree	*tree;	/* associated watched tree */
	struct list_head	rlist;	/* entry in audit_{watch,tree}.rules list */
	struct list_head	list;	/* for AUDIT_LIST* purposes only */
	u64			prio;
};

struct audit_field {
@@ -443,70 +457,56 @@ extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid);
#define audit_get_loginuid(t) ((t)->loginuid)
#define audit_get_sessionid(t) ((t)->sessionid)
extern void audit_log_task_context(struct audit_buffer *ab);
extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp);
extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
extern int audit_bprm(struct linux_binprm *bprm);
extern int audit_socketcall(int nargs, unsigned long *args);
extern void audit_socketcall(int nargs, unsigned long *args);
extern int audit_sockaddr(int len, void *addr);
extern int __audit_fd_pair(int fd1, int fd2);
extern void __audit_fd_pair(int fd1, int fd2);
extern int audit_set_macxattr(const char *name);
extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr);
extern int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout);
extern int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout);
extern int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification);
extern int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
extern void __audit_mq_open(int oflag, mode_t mode, struct mq_attr *attr);
extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);
extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification);
extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
				  const struct cred *new,
				  const struct cred *old);
extern int __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old);
extern void __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old);

static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp)
static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
	if (unlikely(!audit_dummy_context()))
		return __audit_ipc_obj(ipcp);
	return 0;
}
static inline int audit_fd_pair(int fd1, int fd2)
{
	if (unlikely(!audit_dummy_context()))
		return __audit_fd_pair(fd1, fd2);
	return 0;
		__audit_ipc_obj(ipcp);
}
static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
static inline void audit_fd_pair(int fd1, int fd2)
{
	if (unlikely(!audit_dummy_context()))
		return __audit_ipc_set_perm(qbytes, uid, gid, mode);
	return 0;
		__audit_fd_pair(fd1, fd2);
}
static inline int audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
{
	if (unlikely(!audit_dummy_context()))
		return __audit_mq_open(oflag, mode, u_attr);
	return 0;
		__audit_ipc_set_perm(qbytes, uid, gid, mode);
}
static inline int audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout)
static inline void audit_mq_open(int oflag, mode_t mode, struct mq_attr *attr)
{
	if (unlikely(!audit_dummy_context()))
		return __audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
	return 0;
		__audit_mq_open(oflag, mode, attr);
}
static inline int audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout)
static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout)
{
	if (unlikely(!audit_dummy_context()))
		return __audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
	return 0;
		__audit_mq_sendrecv(mqdes, msg_len, msg_prio, abs_timeout);
}
static inline int audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
static inline void audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)
{
	if (unlikely(!audit_dummy_context()))
		return __audit_mq_notify(mqdes, u_notification);
	return 0;
		__audit_mq_notify(mqdes, notification);
}
static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
static inline void audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
{
	if (unlikely(!audit_dummy_context()))
		return __audit_mq_getsetattr(mqdes, mqstat);
	return 0;
		__audit_mq_getsetattr(mqdes, mqstat);
}

static inline int audit_log_bprm_fcaps(struct linux_binprm *bprm,
@@ -518,12 +518,11 @@ static inline int audit_log_bprm_fcaps(struct linux_binprm *bprm,
	return 0;
}

static inline int audit_log_capset(pid_t pid, const struct cred *new,
static inline void audit_log_capset(pid_t pid, const struct cred *new,
				   const struct cred *old)
{
	if (unlikely(!audit_dummy_context()))
		return __audit_log_capset(pid, new, old);
	return 0;
		__audit_log_capset(pid, new, old);
}

extern int audit_n_rules;
@@ -546,20 +545,19 @@ extern int audit_signals;
#define audit_get_loginuid(t) (-1)
#define audit_get_sessionid(t) (-1)
#define audit_log_task_context(b) do { ; } while (0)
#define audit_ipc_obj(i) ({ 0; })
#define audit_ipc_set_perm(q,u,g,m) ({ 0; })
#define audit_ipc_obj(i) ((void)0)
#define audit_ipc_set_perm(q,u,g,m) ((void)0)
#define audit_bprm(p) ({ 0; })
#define audit_socketcall(n,a) ({ 0; })
#define audit_fd_pair(n,a) ({ 0; })
#define audit_socketcall(n,a) ((void)0)
#define audit_fd_pair(n,a) ((void)0)
#define audit_sockaddr(len, addr) ({ 0; })
#define audit_set_macxattr(n) do { ; } while (0)
#define audit_mq_open(o,m,a) ({ 0; })
#define audit_mq_timedsend(d,l,p,t) ({ 0; })
#define audit_mq_timedreceive(d,l,p,t) ({ 0; })
#define audit_mq_notify(d,n) ({ 0; })
#define audit_mq_getsetattr(d,s) ({ 0; })
#define audit_mq_open(o,m,a) ((void)0)
#define audit_mq_sendrecv(d,l,p,t) ((void)0)
#define audit_mq_notify(d,n) ((void)0)
#define audit_mq_getsetattr(d,s) ((void)0)
#define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
#define audit_log_capset(pid, ncr, ocr) ({ 0; })
#define audit_log_capset(pid, ncr, ocr) ((void)0)
#define audit_ptrace(t) ((void)0)
#define audit_n_rules 0
#define audit_signals 0
+49 −48
Original line number Diff line number Diff line
@@ -524,31 +524,27 @@ static void __do_notify(struct mqueue_inode_info *info)
	wake_up(&info->wait_q);
}

static long prepare_timeout(const struct timespec __user *u_arg)
static long prepare_timeout(struct timespec *p)
{
	struct timespec ts, nowts;
	struct timespec nowts;
	long timeout;

	if (u_arg) {
		if (unlikely(copy_from_user(&ts, u_arg,
					sizeof(struct timespec))))
			return -EFAULT;

		if (unlikely(ts.tv_nsec < 0 || ts.tv_sec < 0
			|| ts.tv_nsec >= NSEC_PER_SEC))
	if (p) {
		if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0
			|| p->tv_nsec >= NSEC_PER_SEC))
			return -EINVAL;
		nowts = CURRENT_TIME;
		/* first subtract as jiffies can't be too big */
		ts.tv_sec -= nowts.tv_sec;
		if (ts.tv_nsec < nowts.tv_nsec) {
			ts.tv_nsec += NSEC_PER_SEC;
			ts.tv_sec--;
		p->tv_sec -= nowts.tv_sec;
		if (p->tv_nsec < nowts.tv_nsec) {
			p->tv_nsec += NSEC_PER_SEC;
			p->tv_sec--;
		}
		ts.tv_nsec -= nowts.tv_nsec;
		if (ts.tv_sec < 0)
		p->tv_nsec -= nowts.tv_nsec;
		if (p->tv_sec < 0)
			return 0;

		timeout = timespec_to_jiffies(&ts) + 1;
		timeout = timespec_to_jiffies(p) + 1;
	} else
		return MAX_SCHEDULE_TIMEOUT;

@@ -592,22 +588,18 @@ static int mq_attr_ok(struct mq_attr *attr)
 * Invoked when creating a new queue via sys_mq_open
 */
static struct file *do_create(struct dentry *dir, struct dentry *dentry,
			int oflag, mode_t mode, struct mq_attr __user *u_attr)
			int oflag, mode_t mode, struct mq_attr *attr)
{
	const struct cred *cred = current_cred();
	struct mq_attr attr;
	struct file *result;
	int ret;

	if (u_attr) {
		ret = -EFAULT;
		if (copy_from_user(&attr, u_attr, sizeof(attr)))
			goto out;
	if (attr) {
		ret = -EINVAL;
		if (!mq_attr_ok(&attr))
		if (!mq_attr_ok(attr))
			goto out;
		/* store for use during create */
		dentry->d_fsdata = &attr;
		dentry->d_fsdata = attr;
	}

	mode &= ~current->fs->umask;
@@ -664,11 +656,13 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
	struct dentry *dentry;
	struct file *filp;
	char *name;
	struct mq_attr attr;
	int fd, error;

	error = audit_mq_open(oflag, mode, u_attr);
	if (error != 0)
		return error;
	if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))
		return -EFAULT;

	audit_mq_open(oflag, mode, u_attr ? &attr : NULL);

	if (IS_ERR(name = getname(u_name)))
		return PTR_ERR(name);
@@ -694,7 +688,8 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
			filp = do_open(dentry, oflag);
		} else {
			filp = do_create(mqueue_mnt->mnt_root, dentry,
						oflag, mode, u_attr);
						oflag, mode,
						u_attr ? &attr : NULL);
		}
	} else {
		error = -ENOENT;
@@ -829,17 +824,22 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
	struct ext_wait_queue *receiver;
	struct msg_msg *msg_ptr;
	struct mqueue_inode_info *info;
	struct timespec ts, *p = NULL;
	long timeout;
	int ret;

	ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
	if (ret != 0)
		return ret;
	if (u_abs_timeout) {
		if (copy_from_user(&ts, u_abs_timeout, 
					sizeof(struct timespec)))
			return -EFAULT;
		p = &ts;
	}

	if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
		return -EINVAL;

	timeout = prepare_timeout(u_abs_timeout);
	audit_mq_sendrecv(mqdes, msg_len, msg_prio, p);
	timeout = prepare_timeout(p);

	ret = -EBADF;
	filp = fget(mqdes);
@@ -918,12 +918,17 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
	struct inode *inode;
	struct mqueue_inode_info *info;
	struct ext_wait_queue wait;
	struct timespec ts, *p = NULL;

	ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
	if (ret != 0)
		return ret;
	if (u_abs_timeout) {
		if (copy_from_user(&ts, u_abs_timeout, 
					sizeof(struct timespec)))
			return -EFAULT;
		p = &ts;
	}

	timeout = prepare_timeout(u_abs_timeout);
	audit_mq_sendrecv(mqdes, msg_len, 0, p);
	timeout = prepare_timeout(p);

	ret = -EBADF;
	filp = fget(mqdes);
@@ -1003,17 +1008,17 @@ asmlinkage long sys_mq_notify(mqd_t mqdes,
	struct mqueue_inode_info *info;
	struct sk_buff *nc;

	ret = audit_mq_notify(mqdes, u_notification);
	if (ret != 0)
		return ret;

	nc = NULL;
	sock = NULL;
	if (u_notification != NULL) {
	if (u_notification) {
		if (copy_from_user(&notification, u_notification,
					sizeof(struct sigevent)))
			return -EFAULT;
	}

	audit_mq_notify(mqdes, u_notification ? &notification : NULL);

	nc = NULL;
	sock = NULL;
	if (u_notification != NULL) {
		if (unlikely(notification.sigev_notify != SIGEV_NONE &&
			     notification.sigev_notify != SIGEV_SIGNAL &&
			     notification.sigev_notify != SIGEV_THREAD))
@@ -1150,11 +1155,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
	omqstat = info->attr;
	omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
	if (u_mqstat) {
		ret = audit_mq_getsetattr(mqdes, &mqstat);
		if (ret != 0) {
			spin_unlock(&info->lock);
			goto out_fput;
		}
		audit_mq_getsetattr(mqdes, &mqstat);
		if (mqstat.mq_flags & O_NONBLOCK)
			filp->f_flags |= O_NONBLOCK;
		else
+1 −3
Original line number Diff line number Diff line
@@ -747,9 +747,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
			goto out;
		}

		err = audit_ipc_obj(&(shp->shm_perm));
		if (err)
			goto out_unlock;
		audit_ipc_obj(&(shp->shm_perm));

		if (!capable(CAP_IPC_LOCK)) {
			uid_t euid = current_euid();
+5 −13
Original line number Diff line number Diff line
@@ -624,10 +624,9 @@ void ipc_rcu_putref(void *ptr)
int ipcperms (struct kern_ipc_perm *ipcp, short flag)
{	/* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
	uid_t euid = current_euid();
	int requested_mode, granted_mode, err;
	int requested_mode, granted_mode;

	if (unlikely((err = audit_ipc_obj(ipcp))))
		return err;
	audit_ipc_obj(ipcp);
	requested_mode = (flag >> 6) | (flag >> 3) | flag;
	granted_mode = ipcp->mode;
	if (euid == ipcp->cuid ||
@@ -803,16 +802,10 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
		goto out_up;
	}

	err = audit_ipc_obj(ipcp);
	if (err)
		goto out_unlock;

	if (cmd == IPC_SET) {
		err = audit_ipc_set_perm(extra_perm, perm->uid,
	audit_ipc_obj(ipcp);
	if (cmd == IPC_SET)
		audit_ipc_set_perm(extra_perm, perm->uid,
					 perm->gid, perm->mode);
		if (err)
			goto out_unlock;
	}

	euid = current_euid();
	if (euid == ipcp->cuid ||
@@ -820,7 +813,6 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
		return ipcp;

	err = -EPERM;
out_unlock:
	ipc_unlock(ipcp);
out_up:
	up_write(&ids->rw_mutex);
Loading