ipc: IPCMNI limit check for semmni
For SysV semaphores, the semmni value is the last part of the 4-element sem number array. To make semmni behave in a similar way to msgmni and shmmni, we can't directly use the _minmax handler. Instead, a special sem specific handler is added to check the last argument to make sure that it is limited to the [0, IPCMNI] range. An error will be returned if this is not the case. Link: http://lkml.kernel.org/r/1536352137-12003-3-git-send-email-longman@redhat.com Signed-off-by: Waiman Long <longman@redhat.com> Reviewed-by: Davidlohr Bueso <dave@stgolabs.net> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Kees Cook <keescook@chromium.org> Cc: Luis R. Rodriguez <mcgrof@kernel.org> Cc: Matthew Wilcox <willy@infradead.org> Cc: Takashi Iwai <tiwai@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
6730e65801
Коммит
8c81ddd2ac
|
@ -88,12 +88,33 @@ static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
|
|||
return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
|
||||
}
|
||||
|
||||
static int proc_ipc_sem_dointvec(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int ret, semmni;
|
||||
struct ipc_namespace *ns = current->nsproxy->ipc_ns;
|
||||
|
||||
semmni = ns->sem_ctls[3];
|
||||
ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos);
|
||||
|
||||
if (!ret)
|
||||
ret = sem_check_semmni(current->nsproxy->ipc_ns);
|
||||
|
||||
/*
|
||||
* Reset the semmni value if an error happens.
|
||||
*/
|
||||
if (ret)
|
||||
ns->sem_ctls[3] = semmni;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
#define proc_ipc_doulongvec_minmax NULL
|
||||
#define proc_ipc_dointvec NULL
|
||||
#define proc_ipc_dointvec_minmax NULL
|
||||
#define proc_ipc_dointvec_minmax_orphans NULL
|
||||
#define proc_ipc_auto_msgmni NULL
|
||||
#define proc_ipc_sem_dointvec NULL
|
||||
#endif
|
||||
|
||||
static int zero;
|
||||
|
@ -175,7 +196,7 @@ static struct ctl_table ipc_kern_table[] = {
|
|||
.data = &init_ipc_ns.sem_ctls,
|
||||
.maxlen = 4*sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_ipc_dointvec,
|
||||
.proc_handler = proc_ipc_sem_dointvec,
|
||||
},
|
||||
#ifdef CONFIG_CHECKPOINT_RESTORE
|
||||
{
|
||||
|
|
|
@ -217,6 +217,15 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
|
|||
void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
|
||||
void (*free)(struct ipc_namespace *, struct kern_ipc_perm *));
|
||||
|
||||
static inline int sem_check_semmni(struct ipc_namespace *ns) {
|
||||
/*
|
||||
* Check semmni range [0, IPCMNI]
|
||||
* semmni is the last element of sem_ctls[4] array
|
||||
*/
|
||||
return ((ns->sem_ctls[3] < 0) || (ns->sem_ctls[3] > IPCMNI))
|
||||
? -ERANGE : 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
#include <linux/compat.h>
|
||||
struct compat_ipc_perm {
|
||||
|
|
Загрузка…
Ссылка в новой задаче