summaryrefslogtreecommitdiff
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/mqueue.c116
-rw-r--r--ipc/shm.c13
-rw-r--r--ipc/util.c36
3 files changed, 84 insertions, 81 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 68eb857cfde..d448b69672b 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -112,13 +112,14 @@ static inline struct mqueue_inode_info *MQUEUE_I(struct inode *inode)
static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
struct mq_attr *attr)
{
+ struct user_struct *u = current_user();
struct inode *inode;
inode = new_inode(sb);
if (inode) {
inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
inode->i_blocks = 0;
inode->i_mtime = inode->i_ctime = inode->i_atime =
CURRENT_TIME;
@@ -126,7 +127,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
if (S_ISREG(mode)) {
struct mqueue_inode_info *info;
struct task_struct *p = current;
- struct user_struct *u = p->user;
unsigned long mq_bytes, mq_msg_tblsz;
inode->i_fop = &mqueue_file_operations;
@@ -507,7 +507,7 @@ static void __do_notify(struct mqueue_inode_info *info)
sig_i.si_code = SI_MESGQ;
sig_i.si_value = info->notify.sigev_value;
sig_i.si_pid = task_tgid_vnr(current);
- sig_i.si_uid = current->uid;
+ sig_i.si_uid = current_uid();
kill_pid_info(info->notify.sigev_signo,
&sig_i, info->notify_owner);
@@ -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,21 +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)
{
- struct mq_attr attr;
+ const struct cred *cred = current_cred();
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;
@@ -618,7 +611,7 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
if (ret)
goto out_drop_write;
- result = dentry_open(dentry, mqueue_mnt, oflag);
+ result = dentry_open(dentry, mqueue_mnt, oflag, cred);
/*
* dentry_open() took a persistent mnt_want_write(),
* so we can now drop this one.
@@ -637,8 +630,10 @@ out:
/* Opens existing queue */
static struct file *do_open(struct dentry *dentry, int oflag)
{
-static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
- MAY_READ | MAY_WRITE };
+ const struct cred *cred = current_cred();
+
+ static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
+ MAY_READ | MAY_WRITE };
if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
dput(dentry);
@@ -652,7 +647,7 @@ static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
return ERR_PTR(-EACCES);
}
- return dentry_open(dentry, mqueue_mnt, oflag);
+ return dentry_open(dentry, mqueue_mnt, oflag, cred);
}
asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
@@ -661,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);
@@ -691,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;
@@ -826,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);
@@ -915,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);
@@ -1000,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))
@@ -1147,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
diff --git a/ipc/shm.c b/ipc/shm.c
index 867e5d6a55c..57dd50046ce 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -366,7 +366,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
if (shmflg & SHM_HUGETLB) {
/* hugetlb_file_setup takes care of mlock user accounting */
file = hugetlb_file_setup(name, size);
- shp->mlock_user = current->user;
+ shp->mlock_user = current_user();
} else {
int acctflag = VM_ACCOUNT;
/*
@@ -747,14 +747,13 @@ 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();
err = -EPERM;
- if (current->euid != shp->shm_perm.uid &&
- current->euid != shp->shm_perm.cuid)
+ if (euid != shp->shm_perm.uid &&
+ euid != shp->shm_perm.cuid)
goto out_unlock;
if (cmd == SHM_LOCK &&
!current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
@@ -766,7 +765,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
goto out_unlock;
if(cmd==SHM_LOCK) {
- struct user_struct * user = current->user;
+ struct user_struct *user = current_user();
if (!is_file_hugepages(shp->shm_file)) {
err = shmem_lock(shp->shm_file, 1, user);
if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){
diff --git a/ipc/util.c b/ipc/util.c
index 361fd1c96fc..7585a72e259 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -258,6 +258,8 @@ int ipc_get_maxid(struct ipc_ids *ids)
int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
{
+ uid_t euid;
+ gid_t egid;
int id, err;
if (size > IPCMNI)
@@ -280,8 +282,9 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
ids->in_use++;
- new->cuid = new->uid = current->euid;
- new->gid = new->cgid = current->egid;
+ current_euid_egid(&euid, &egid);
+ new->cuid = new->uid = euid;
+ new->gid = new->cgid = egid;
new->seq = ids->seq++;
if(ids->seq > ids->seq_max)
@@ -620,13 +623,14 @@ 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> */
- int requested_mode, granted_mode, err;
+ uid_t euid = current_euid();
+ 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 (current->euid == ipcp->cuid || current->euid == ipcp->uid)
+ if (euid == ipcp->cuid ||
+ euid == ipcp->uid)
granted_mode >>= 6;
else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))
granted_mode >>= 3;
@@ -788,6 +792,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
struct ipc64_perm *perm, int extra_perm)
{
struct kern_ipc_perm *ipcp;
+ uid_t euid;
int err;
down_write(&ids->rw_mutex);
@@ -797,22 +802,17 @@ 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;
- }
- if (current->euid == ipcp->cuid ||
- current->euid == ipcp->uid || capable(CAP_SYS_ADMIN))
+
+ euid = current_euid();
+ if (euid == ipcp->cuid ||
+ euid == ipcp->uid || capable(CAP_SYS_ADMIN))
return ipcp;
err = -EPERM;
-out_unlock:
ipc_unlock(ipcp);
out_up:
up_write(&ids->rw_mutex);