Merge branch 'master' into next
Conflicts: fs/namei.c Manually merged per: diff --cc fs/namei.c index 734f2b5,bbc15c2..0000000 --- a/fs/namei.c +++ b/fs/namei.c @@@ -860,9 -848,8 +849,10 @@@ static int __link_path_walk(const char nd->flags |= LOOKUP_CONTINUE; err = exec_permission_lite(inode); if (err == -EAGAIN) - err = vfs_permission(nd, MAY_EXEC); + err = inode_permission(nd->path.dentry->d_inode, + MAY_EXEC); + if (!err) + err = ima_path_check(&nd->path, MAY_EXEC); if (err) break; @@@ -1525,14 -1506,9 +1509,14 @@@ int may_open(struct path *path, int acc flag &= ~O_TRUNC; } - error = vfs_permission(nd, acc_mode); + error = inode_permission(inode, acc_mode); if (error) return error; + - error = ima_path_check(&nd->path, ++ error = ima_path_check(path, + acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC)); + if (error) + return error; /* * An append-only file must be opened in append mode for writing. */ Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
@@ -26,29 +26,6 @@ static void *get_ipc(ctl_table *table)
|
||||
return which;
|
||||
}
|
||||
|
||||
/*
|
||||
* Routine that is called when the file "auto_msgmni" has successfully been
|
||||
* written.
|
||||
* Two values are allowed:
|
||||
* 0: unregister msgmni's callback routine from the ipc namespace notifier
|
||||
* chain. This means that msgmni won't be recomputed anymore upon memory
|
||||
* add/remove or ipc namespace creation/removal.
|
||||
* 1: register back the callback routine.
|
||||
*/
|
||||
static void ipc_auto_callback(int val)
|
||||
{
|
||||
if (!val)
|
||||
unregister_ipcns_notifier(current->nsproxy->ipc_ns);
|
||||
else {
|
||||
/*
|
||||
* Re-enable automatic recomputing only if not already
|
||||
* enabled.
|
||||
*/
|
||||
recompute_msgmni(current->nsproxy->ipc_ns);
|
||||
cond_register_ipcns_notifier(current->nsproxy->ipc_ns);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
@@ -94,6 +71,29 @@ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
|
||||
lenp, ppos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Routine that is called when the file "auto_msgmni" has successfully been
|
||||
* written.
|
||||
* Two values are allowed:
|
||||
* 0: unregister msgmni's callback routine from the ipc namespace notifier
|
||||
* chain. This means that msgmni won't be recomputed anymore upon memory
|
||||
* add/remove or ipc namespace creation/removal.
|
||||
* 1: register back the callback routine.
|
||||
*/
|
||||
static void ipc_auto_callback(int val)
|
||||
{
|
||||
if (!val)
|
||||
unregister_ipcns_notifier(current->nsproxy->ipc_ns);
|
||||
else {
|
||||
/*
|
||||
* Re-enable automatic recomputing only if not already
|
||||
* enabled.
|
||||
*/
|
||||
recompute_msgmni(current->nsproxy->ipc_ns);
|
||||
cond_register_ipcns_notifier(current->nsproxy->ipc_ns);
|
||||
}
|
||||
}
|
||||
|
||||
static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
|
||||
struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
|
129
ipc/mqueue.c
129
ipc/mqueue.c
@@ -120,7 +120,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
|
||||
inode->i_mode = mode;
|
||||
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;
|
||||
|
||||
@@ -506,7 +505,8 @@ static void __do_notify(struct mqueue_inode_info *info)
|
||||
sig_i.si_errno = 0;
|
||||
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_pid = task_tgid_nr_ns(current,
|
||||
ns_of_pid(info->notify_owner));
|
||||
sig_i.si_uid = current_uid();
|
||||
|
||||
kill_pid_info(info->notify.sigev_signo,
|
||||
@@ -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;
|
||||
@@ -658,17 +650,19 @@ static struct file *do_open(struct dentry *dentry, int oflag)
|
||||
return dentry_open(dentry, mqueue_mnt, oflag, cred);
|
||||
}
|
||||
|
||||
asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
|
||||
struct mq_attr __user *u_attr)
|
||||
SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
|
||||
struct mq_attr __user *, u_attr)
|
||||
{
|
||||
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;
|
||||
@@ -726,7 +721,7 @@ out_putname:
|
||||
return fd;
|
||||
}
|
||||
|
||||
asmlinkage long sys_mq_unlink(const char __user *u_name)
|
||||
SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
|
||||
{
|
||||
int err;
|
||||
char *name;
|
||||
@@ -819,9 +814,9 @@ static inline void pipelined_receive(struct mqueue_inode_info *info)
|
||||
sender->state = STATE_READY;
|
||||
}
|
||||
|
||||
asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
|
||||
size_t msg_len, unsigned int msg_prio,
|
||||
const struct timespec __user *u_abs_timeout)
|
||||
SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
|
||||
size_t, msg_len, unsigned int, msg_prio,
|
||||
const struct timespec __user *, u_abs_timeout)
|
||||
{
|
||||
struct file *filp;
|
||||
struct inode *inode;
|
||||
@@ -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);
|
||||
@@ -907,9 +907,9 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
|
||||
size_t msg_len, unsigned int __user *u_msg_prio,
|
||||
const struct timespec __user *u_abs_timeout)
|
||||
SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
|
||||
size_t, msg_len, unsigned int __user *, u_msg_prio,
|
||||
const struct timespec __user *, u_abs_timeout)
|
||||
{
|
||||
long timeout;
|
||||
ssize_t ret;
|
||||
@@ -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);
|
||||
@@ -992,8 +997,8 @@ out:
|
||||
* and he isn't currently owner of notification, will be silently discarded.
|
||||
* It isn't explicitly defined in the POSIX.
|
||||
*/
|
||||
asmlinkage long sys_mq_notify(mqd_t mqdes,
|
||||
const struct sigevent __user *u_notification)
|
||||
SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
|
||||
const struct sigevent __user *, u_notification)
|
||||
{
|
||||
int ret;
|
||||
struct file *filp;
|
||||
@@ -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;
|
||||
if (u_notification) {
|
||||
if (copy_from_user(¬ification, u_notification,
|
||||
sizeof(struct sigevent)))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
audit_mq_notify(mqdes, u_notification ? ¬ification : NULL);
|
||||
|
||||
nc = NULL;
|
||||
sock = NULL;
|
||||
if (u_notification != NULL) {
|
||||
if (copy_from_user(¬ification, u_notification,
|
||||
sizeof(struct sigevent)))
|
||||
return -EFAULT;
|
||||
|
||||
if (unlikely(notification.sigev_notify != SIGEV_NONE &&
|
||||
notification.sigev_notify != SIGEV_SIGNAL &&
|
||||
notification.sigev_notify != SIGEV_THREAD))
|
||||
@@ -1118,9 +1123,9 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
|
||||
const struct mq_attr __user *u_mqstat,
|
||||
struct mq_attr __user *u_omqstat)
|
||||
SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
|
||||
const struct mq_attr __user *, u_mqstat,
|
||||
struct mq_attr __user *, u_omqstat)
|
||||
{
|
||||
int ret;
|
||||
struct mq_attr mqstat, omqstat;
|
||||
@@ -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
|
||||
|
12
ipc/msg.c
12
ipc/msg.c
@@ -309,7 +309,7 @@ static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg)
|
||||
return security_msg_queue_associate(msq, msgflg);
|
||||
}
|
||||
|
||||
asmlinkage long sys_msgget(key_t key, int msgflg)
|
||||
SYSCALL_DEFINE2(msgget, key_t, key, int, msgflg)
|
||||
{
|
||||
struct ipc_namespace *ns;
|
||||
struct ipc_ops msg_ops;
|
||||
@@ -466,7 +466,7 @@ out_up:
|
||||
return err;
|
||||
}
|
||||
|
||||
asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
|
||||
SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
|
||||
{
|
||||
struct msg_queue *msq;
|
||||
int err, version;
|
||||
@@ -723,8 +723,8 @@ out_free:
|
||||
return err;
|
||||
}
|
||||
|
||||
asmlinkage long
|
||||
sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
|
||||
SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
|
||||
int, msgflg)
|
||||
{
|
||||
long mtype;
|
||||
|
||||
@@ -904,8 +904,8 @@ out_unlock:
|
||||
return msgsz;
|
||||
}
|
||||
|
||||
asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
|
||||
long msgtyp, int msgflg)
|
||||
SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
|
||||
long, msgtyp, int, msgflg)
|
||||
{
|
||||
long err, mtype;
|
||||
|
||||
|
21
ipc/sem.c
21
ipc/sem.c
@@ -58,7 +58,7 @@
|
||||
* SMP-threaded, sysctl's added
|
||||
* (c) 1999 Manfred Spraul <manfred@colorfullife.com>
|
||||
* Enforced range limit on SEM_UNDO
|
||||
* (c) 2001 Red Hat Inc <alan@redhat.com>
|
||||
* (c) 2001 Red Hat Inc
|
||||
* Lockless wakeup
|
||||
* (c) 2003 Manfred Spraul <manfred@colorfullife.com>
|
||||
*
|
||||
@@ -308,7 +308,7 @@ static inline int sem_more_checks(struct kern_ipc_perm *ipcp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
asmlinkage long sys_semget(key_t key, int nsems, int semflg)
|
||||
SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg)
|
||||
{
|
||||
struct ipc_namespace *ns;
|
||||
struct ipc_ops sem_ops;
|
||||
@@ -887,7 +887,7 @@ out_up:
|
||||
return err;
|
||||
}
|
||||
|
||||
asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
|
||||
SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
int version;
|
||||
@@ -923,6 +923,13 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
|
||||
asmlinkage long SyS_semctl(int semid, int semnum, int cmd, union semun arg)
|
||||
{
|
||||
return SYSC_semctl((int) semid, (int) semnum, (int) cmd, arg);
|
||||
}
|
||||
SYSCALL_ALIAS(sys_semctl, SyS_semctl);
|
||||
#endif
|
||||
|
||||
/* If the task doesn't already have a undo_list, then allocate one
|
||||
* here. We guarantee there is only one thread using this undo list,
|
||||
@@ -1048,8 +1055,8 @@ out:
|
||||
return un;
|
||||
}
|
||||
|
||||
asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
|
||||
unsigned nsops, const struct timespec __user *timeout)
|
||||
SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
|
||||
unsigned, nsops, const struct timespec __user *, timeout)
|
||||
{
|
||||
int error = -EINVAL;
|
||||
struct sem_array *sma;
|
||||
@@ -1216,7 +1223,6 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
|
||||
if (timeout && jiffies_left == 0)
|
||||
error = -EAGAIN;
|
||||
list_del(&queue.list);
|
||||
goto out_unlock_free;
|
||||
|
||||
out_unlock_free:
|
||||
sem_unlock(sma);
|
||||
@@ -1226,7 +1232,8 @@ out_free:
|
||||
return error;
|
||||
}
|
||||
|
||||
asmlinkage long sys_semop (int semid, struct sembuf __user *tsops, unsigned nsops)
|
||||
SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops,
|
||||
unsigned, nsops)
|
||||
{
|
||||
return sys_semtimedop(semid, tsops, nsops, NULL);
|
||||
}
|
||||
|
47
ipc/shm.c
47
ipc/shm.c
@@ -76,7 +76,7 @@ void shm_init_ns(struct ipc_namespace *ns)
|
||||
ns->shm_ctlall = SHMALL;
|
||||
ns->shm_ctlmni = SHMMNI;
|
||||
ns->shm_tot = 0;
|
||||
ipc_init_ids(&ns->ids[IPC_SHM_IDS]);
|
||||
ipc_init_ids(&shm_ids(ns));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -369,14 +369,14 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
|
||||
file = hugetlb_file_setup(name, size);
|
||||
shp->mlock_user = current_user();
|
||||
} else {
|
||||
int acctflag = VM_ACCOUNT;
|
||||
int acctflag = 0;
|
||||
/*
|
||||
* Do not allow no accounting for OVERCOMMIT_NEVER, even
|
||||
* if it's asked for.
|
||||
*/
|
||||
if ((shmflg & SHM_NORESERVE) &&
|
||||
sysctl_overcommit_memory != OVERCOMMIT_NEVER)
|
||||
acctflag = 0;
|
||||
acctflag = VM_NORESERVE;
|
||||
file = shmem_file_setup(name, size, acctflag);
|
||||
}
|
||||
error = PTR_ERR(file);
|
||||
@@ -442,7 +442,7 @@ static inline int shm_more_checks(struct kern_ipc_perm *ipcp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
|
||||
SYSCALL_DEFINE3(shmget, key_t, key, size_t, size, int, shmflg)
|
||||
{
|
||||
struct ipc_namespace *ns;
|
||||
struct ipc_ops shm_ops;
|
||||
@@ -567,11 +567,15 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
|
||||
struct hstate *h = hstate_file(shp->shm_file);
|
||||
*rss += pages_per_huge_page(h) * mapping->nrpages;
|
||||
} else {
|
||||
#ifdef CONFIG_SHMEM
|
||||
struct shmem_inode_info *info = SHMEM_I(inode);
|
||||
spin_lock(&info->lock);
|
||||
*rss += inode->i_mapping->nrpages;
|
||||
*swp += info->swapped;
|
||||
spin_unlock(&info->lock);
|
||||
#else
|
||||
*rss += inode->i_mapping->nrpages;
|
||||
#endif
|
||||
}
|
||||
|
||||
total++;
|
||||
@@ -623,7 +627,7 @@ out_up:
|
||||
return err;
|
||||
}
|
||||
|
||||
asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
|
||||
SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
|
||||
{
|
||||
struct shmid_kernel *shp;
|
||||
int err, version;
|
||||
@@ -646,7 +650,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memset(&shminfo,0,sizeof(shminfo));
|
||||
memset(&shminfo, 0, sizeof(shminfo));
|
||||
shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
|
||||
shminfo.shmmax = ns->shm_ctlmax;
|
||||
shminfo.shmall = ns->shm_ctlall;
|
||||
@@ -671,7 +675,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memset(&shm_info,0,sizeof(shm_info));
|
||||
memset(&shm_info, 0, sizeof(shm_info));
|
||||
down_read(&shm_ids(ns).rw_mutex);
|
||||
shm_info.used_ids = shm_ids(ns).in_use;
|
||||
shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp);
|
||||
@@ -680,7 +684,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
|
||||
shm_info.swap_successes = 0;
|
||||
err = ipc_get_maxid(&shm_ids(ns));
|
||||
up_read(&shm_ids(ns).rw_mutex);
|
||||
if(copy_to_user (buf, &shm_info, sizeof(shm_info))) {
|
||||
if (copy_to_user(buf, &shm_info, sizeof(shm_info))) {
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
@@ -694,11 +698,6 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
|
||||
struct shmid64_ds tbuf;
|
||||
int result;
|
||||
|
||||
if (!buf) {
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cmd == SHM_STAT) {
|
||||
shp = shm_lock(ns, shmid);
|
||||
if (IS_ERR(shp)) {
|
||||
@@ -714,7 +713,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
|
||||
}
|
||||
result = 0;
|
||||
}
|
||||
err=-EACCES;
|
||||
err = -EACCES;
|
||||
if (ipcperms (&shp->shm_perm, S_IRUGO))
|
||||
goto out_unlock;
|
||||
err = security_shm_shmctl(shp, cmd);
|
||||
@@ -749,9 +748,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();
|
||||
@@ -949,7 +946,7 @@ out_put_dentry:
|
||||
goto out_nattch;
|
||||
}
|
||||
|
||||
asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg)
|
||||
SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg)
|
||||
{
|
||||
unsigned long ret;
|
||||
long err;
|
||||
@@ -965,7 +962,7 @@ asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg)
|
||||
* detach and kill segment if marked destroyed.
|
||||
* The work is done in shm_close.
|
||||
*/
|
||||
asmlinkage long sys_shmdt(char __user *shmaddr)
|
||||
SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma, *next;
|
||||
@@ -1000,6 +997,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
|
||||
*/
|
||||
vma = find_vma(mm, addr);
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
while (vma) {
|
||||
next = vma->vm_next;
|
||||
|
||||
@@ -1044,6 +1042,17 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
|
||||
vma = next;
|
||||
}
|
||||
|
||||
#else /* CONFIG_MMU */
|
||||
/* under NOMMU conditions, the exact address to be destroyed must be
|
||||
* given */
|
||||
retval = -EINVAL;
|
||||
if (vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) {
|
||||
do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
up_write(&mm->mmap_sem);
|
||||
return retval;
|
||||
}
|
||||
|
18
ipc/util.c
18
ipc/util.c
@@ -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);
|
||||
|
Reference in New Issue
Block a user