Updated from Linux LTS 3.10.21 to 3.10.22
This commit is contained in:
@@ -62,7 +62,7 @@ static int proc_ipc_dointvec_minmax_orphans(ctl_table *table, int write,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int proc_ipc_callback_dointvec(ctl_table *table, int write,
|
||||
static int proc_ipc_callback_dointvec_minmax(ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct ctl_table ipc_table;
|
||||
@@ -72,7 +72,7 @@ static int proc_ipc_callback_dointvec(ctl_table *table, int write,
|
||||
memcpy(&ipc_table, table, sizeof(ipc_table));
|
||||
ipc_table.data = get_ipc(table);
|
||||
|
||||
rc = proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
|
||||
rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
|
||||
|
||||
if (write && !rc && lenp_bef == *lenp)
|
||||
/*
|
||||
@@ -152,15 +152,13 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
|
||||
#define proc_ipc_dointvec NULL
|
||||
#define proc_ipc_dointvec_minmax NULL
|
||||
#define proc_ipc_dointvec_minmax_orphans NULL
|
||||
#define proc_ipc_callback_dointvec NULL
|
||||
#define proc_ipc_callback_dointvec_minmax NULL
|
||||
#define proc_ipcauto_dointvec_minmax NULL
|
||||
#endif
|
||||
|
||||
static int zero;
|
||||
static int one = 1;
|
||||
#ifdef CONFIG_CHECKPOINT_RESTORE
|
||||
static int int_max = INT_MAX;
|
||||
#endif
|
||||
|
||||
static struct ctl_table ipc_kern_table[] = {
|
||||
{
|
||||
@@ -198,21 +196,27 @@ static struct ctl_table ipc_kern_table[] = {
|
||||
.data = &init_ipc_ns.msg_ctlmax,
|
||||
.maxlen = sizeof (init_ipc_ns.msg_ctlmax),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_ipc_dointvec,
|
||||
.proc_handler = proc_ipc_dointvec_minmax,
|
||||
.extra1 = &zero,
|
||||
.extra2 = &int_max,
|
||||
},
|
||||
{
|
||||
.procname = "msgmni",
|
||||
.data = &init_ipc_ns.msg_ctlmni,
|
||||
.maxlen = sizeof (init_ipc_ns.msg_ctlmni),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_ipc_callback_dointvec,
|
||||
.proc_handler = proc_ipc_callback_dointvec_minmax,
|
||||
.extra1 = &zero,
|
||||
.extra2 = &int_max,
|
||||
},
|
||||
{
|
||||
.procname = "msgmnb",
|
||||
.data = &init_ipc_ns.msg_ctlmnb,
|
||||
.maxlen = sizeof (init_ipc_ns.msg_ctlmnb),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_ipc_dointvec,
|
||||
.proc_handler = proc_ipc_dointvec_minmax,
|
||||
.extra1 = &zero,
|
||||
.extra2 = &int_max,
|
||||
},
|
||||
{
|
||||
.procname = "sem",
|
||||
|
||||
@@ -823,6 +823,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
|
||||
error = ro;
|
||||
goto out;
|
||||
}
|
||||
audit_inode_parent_hidden(name, root);
|
||||
filp = do_create(ipc_ns, root->d_inode,
|
||||
&path, oflag, mode,
|
||||
u_attr ? &attr : NULL);
|
||||
@@ -868,6 +869,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
|
||||
if (IS_ERR(name))
|
||||
return PTR_ERR(name);
|
||||
|
||||
audit_inode_parent_hidden(name, mnt->mnt_root);
|
||||
err = mnt_want_write(mnt);
|
||||
if (err)
|
||||
goto out_name;
|
||||
|
||||
@@ -41,15 +41,15 @@ struct msg_msgseg {
|
||||
/* the next part of the message follows immediately */
|
||||
};
|
||||
|
||||
#define DATALEN_MSG (int)(PAGE_SIZE-sizeof(struct msg_msg))
|
||||
#define DATALEN_SEG (int)(PAGE_SIZE-sizeof(struct msg_msgseg))
|
||||
#define DATALEN_MSG ((size_t)PAGE_SIZE-sizeof(struct msg_msg))
|
||||
#define DATALEN_SEG ((size_t)PAGE_SIZE-sizeof(struct msg_msgseg))
|
||||
|
||||
|
||||
static struct msg_msg *alloc_msg(int len)
|
||||
static struct msg_msg *alloc_msg(size_t len)
|
||||
{
|
||||
struct msg_msg *msg;
|
||||
struct msg_msgseg **pseg;
|
||||
int alen;
|
||||
size_t alen;
|
||||
|
||||
alen = min(len, DATALEN_MSG);
|
||||
msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
|
||||
@@ -80,12 +80,12 @@ out_err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct msg_msg *load_msg(const void __user *src, int len)
|
||||
struct msg_msg *load_msg(const void __user *src, size_t len)
|
||||
{
|
||||
struct msg_msg *msg;
|
||||
struct msg_msgseg *seg;
|
||||
int err = -EFAULT;
|
||||
int alen;
|
||||
size_t alen;
|
||||
|
||||
msg = alloc_msg(len);
|
||||
if (msg == NULL)
|
||||
@@ -117,8 +117,8 @@ out_err:
|
||||
struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
|
||||
{
|
||||
struct msg_msgseg *dst_pseg, *src_pseg;
|
||||
int len = src->m_ts;
|
||||
int alen;
|
||||
size_t len = src->m_ts;
|
||||
size_t alen;
|
||||
|
||||
BUG_ON(dst == NULL);
|
||||
if (src->m_ts > dst->m_ts)
|
||||
@@ -147,9 +147,9 @@ struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
#endif
|
||||
int store_msg(void __user *dest, struct msg_msg *msg, int len)
|
||||
int store_msg(void __user *dest, struct msg_msg *msg, size_t len)
|
||||
{
|
||||
int alen;
|
||||
size_t alen;
|
||||
struct msg_msgseg *seg;
|
||||
|
||||
alen = min(len, DATALEN_MSG);
|
||||
|
||||
42
ipc/sem.c
42
ipc/sem.c
@@ -1282,6 +1282,12 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
|
||||
|
||||
sem_lock(sma, NULL, -1);
|
||||
|
||||
if (sma->sem_perm.deleted) {
|
||||
sem_unlock(sma, -1);
|
||||
rcu_read_unlock();
|
||||
return -EIDRM;
|
||||
}
|
||||
|
||||
curr = &sma->sem_base[semnum];
|
||||
|
||||
ipc_assert_locked_object(&sma->sem_perm);
|
||||
@@ -1336,12 +1342,14 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
||||
int i;
|
||||
|
||||
sem_lock(sma, NULL, -1);
|
||||
if (sma->sem_perm.deleted) {
|
||||
err = -EIDRM;
|
||||
goto out_unlock;
|
||||
}
|
||||
if(nsems > SEMMSL_FAST) {
|
||||
if (!ipc_rcu_getref(sma)) {
|
||||
sem_unlock(sma, -1);
|
||||
rcu_read_unlock();
|
||||
err = -EIDRM;
|
||||
goto out_free;
|
||||
goto out_unlock;
|
||||
}
|
||||
sem_unlock(sma, -1);
|
||||
rcu_read_unlock();
|
||||
@@ -1354,10 +1362,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
||||
rcu_read_lock();
|
||||
sem_lock_and_putref(sma);
|
||||
if (sma->sem_perm.deleted) {
|
||||
sem_unlock(sma, -1);
|
||||
rcu_read_unlock();
|
||||
err = -EIDRM;
|
||||
goto out_free;
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < sma->sem_nsems; i++)
|
||||
@@ -1375,8 +1381,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
||||
struct sem_undo *un;
|
||||
|
||||
if (!ipc_rcu_getref(sma)) {
|
||||
rcu_read_unlock();
|
||||
return -EIDRM;
|
||||
err = -EIDRM;
|
||||
goto out_rcu_wakeup;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
@@ -1404,10 +1410,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
||||
rcu_read_lock();
|
||||
sem_lock_and_putref(sma);
|
||||
if (sma->sem_perm.deleted) {
|
||||
sem_unlock(sma, -1);
|
||||
rcu_read_unlock();
|
||||
err = -EIDRM;
|
||||
goto out_free;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
for (i = 0; i < nsems; i++)
|
||||
@@ -1431,6 +1435,10 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
||||
goto out_rcu_wakeup;
|
||||
|
||||
sem_lock(sma, NULL, -1);
|
||||
if (sma->sem_perm.deleted) {
|
||||
err = -EIDRM;
|
||||
goto out_unlock;
|
||||
}
|
||||
curr = &sma->sem_base[semnum];
|
||||
|
||||
switch (cmd) {
|
||||
@@ -1836,6 +1844,10 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
|
||||
if (error)
|
||||
goto out_rcu_wakeup;
|
||||
|
||||
error = -EIDRM;
|
||||
locknum = sem_lock(sma, sops, nsops);
|
||||
if (sma->sem_perm.deleted)
|
||||
goto out_unlock_free;
|
||||
/*
|
||||
* semid identifiers are not unique - find_alloc_undo may have
|
||||
* allocated an undo structure, it was invalidated by an RMID
|
||||
@@ -1843,8 +1855,6 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
|
||||
* This case can be detected checking un->semid. The existence of
|
||||
* "un" itself is guaranteed by rcu.
|
||||
*/
|
||||
error = -EIDRM;
|
||||
locknum = sem_lock(sma, sops, nsops);
|
||||
if (un && un->semid == -1)
|
||||
goto out_unlock_free;
|
||||
|
||||
@@ -2057,6 +2067,12 @@ void exit_sem(struct task_struct *tsk)
|
||||
}
|
||||
|
||||
sem_lock(sma, NULL, -1);
|
||||
/* exit_sem raced with IPC_RMID, nothing to do */
|
||||
if (sma->sem_perm.deleted) {
|
||||
sem_unlock(sma, -1);
|
||||
rcu_read_unlock();
|
||||
continue;
|
||||
}
|
||||
un = __lookup_undo(ulp, semid);
|
||||
if (un == NULL) {
|
||||
/* exit_sem raced with IPC_RMID+semget() that created
|
||||
|
||||
27
ipc/util.c
27
ipc/util.c
@@ -17,12 +17,27 @@
|
||||
* Pavel Emelianov <xemul@openvz.org>
|
||||
*
|
||||
* General sysv ipc locking scheme:
|
||||
* when doing ipc id lookups, take the ids->rwsem
|
||||
* rcu_read_lock()
|
||||
* obtain the ipc object (kern_ipc_perm)
|
||||
* perform security, capabilities, auditing and permission checks, etc.
|
||||
* acquire the ipc lock (kern_ipc_perm.lock) throught ipc_lock_object()
|
||||
* perform data updates (ie: SET, RMID, LOCK/UNLOCK commands)
|
||||
* rcu_read_lock()
|
||||
* obtain the ipc object (kern_ipc_perm) by looking up the id in an idr
|
||||
* tree.
|
||||
* - perform initial checks (capabilities, auditing and permission,
|
||||
* etc).
|
||||
* - perform read-only operations, such as STAT, INFO commands.
|
||||
* acquire the ipc lock (kern_ipc_perm.lock) through
|
||||
* ipc_lock_object()
|
||||
* - perform data updates, such as SET, RMID commands and
|
||||
* mechanism-specific operations (semop/semtimedop,
|
||||
* msgsnd/msgrcv, shmat/shmdt).
|
||||
* drop the ipc lock, through ipc_unlock_object().
|
||||
* rcu_read_unlock()
|
||||
*
|
||||
* The ids->rwsem must be taken when:
|
||||
* - creating, removing and iterating the existing entries in ipc
|
||||
* identifier sets.
|
||||
* - iterating through files under /proc/sysvipc/
|
||||
*
|
||||
* Note that sems have a special fast path that avoids kern_ipc_perm.lock -
|
||||
* see sem_lock().
|
||||
*/
|
||||
|
||||
#include <linux/mm.h>
|
||||
|
||||
@@ -148,9 +148,9 @@ int ipc_parse_version (int *cmd);
|
||||
#endif
|
||||
|
||||
extern void free_msg(struct msg_msg *msg);
|
||||
extern struct msg_msg *load_msg(const void __user *src, int len);
|
||||
extern struct msg_msg *load_msg(const void __user *src, size_t len);
|
||||
extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst);
|
||||
extern int store_msg(void __user *dest, struct msg_msg *msg, int len);
|
||||
extern int store_msg(void __user *dest, struct msg_msg *msg, size_t len);
|
||||
|
||||
extern void recompute_msgmni(struct ipc_namespace *);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user