diff options
Diffstat (limited to 'ipc/shm.c')
-rw-r--r-- | ipc/shm.c | 23 |
1 files changed, 15 insertions, 8 deletions
@@ -43,7 +43,7 @@ | |||
43 | #include <linux/mount.h> | 43 | #include <linux/mount.h> |
44 | #include <linux/ipc_namespace.h> | 44 | #include <linux/ipc_namespace.h> |
45 | 45 | ||
46 | #include <asm/uaccess.h> | 46 | #include <linux/uaccess.h> |
47 | 47 | ||
48 | #include "util.h" | 48 | #include "util.h" |
49 | 49 | ||
@@ -493,7 +493,11 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) | |||
493 | if (size < SHMMIN || size > ns->shm_ctlmax) | 493 | if (size < SHMMIN || size > ns->shm_ctlmax) |
494 | return -EINVAL; | 494 | return -EINVAL; |
495 | 495 | ||
496 | if (ns->shm_tot + numpages > ns->shm_ctlall) | 496 | if (numpages << PAGE_SHIFT < size) |
497 | return -ENOSPC; | ||
498 | |||
499 | if (ns->shm_tot + numpages < ns->shm_tot || | ||
500 | ns->shm_tot + numpages > ns->shm_ctlall) | ||
497 | return -ENOSPC; | 501 | return -ENOSPC; |
498 | 502 | ||
499 | shp = ipc_rcu_alloc(sizeof(*shp)); | 503 | shp = ipc_rcu_alloc(sizeof(*shp)); |
@@ -609,15 +613,15 @@ static inline int shm_more_checks(struct kern_ipc_perm *ipcp, | |||
609 | SYSCALL_DEFINE3(shmget, key_t, key, size_t, size, int, shmflg) | 613 | SYSCALL_DEFINE3(shmget, key_t, key, size_t, size, int, shmflg) |
610 | { | 614 | { |
611 | struct ipc_namespace *ns; | 615 | struct ipc_namespace *ns; |
612 | struct ipc_ops shm_ops; | 616 | static const struct ipc_ops shm_ops = { |
617 | .getnew = newseg, | ||
618 | .associate = shm_security, | ||
619 | .more_checks = shm_more_checks, | ||
620 | }; | ||
613 | struct ipc_params shm_params; | 621 | struct ipc_params shm_params; |
614 | 622 | ||
615 | ns = current->nsproxy->ipc_ns; | 623 | ns = current->nsproxy->ipc_ns; |
616 | 624 | ||
617 | shm_ops.getnew = newseg; | ||
618 | shm_ops.associate = shm_security; | ||
619 | shm_ops.more_checks = shm_more_checks; | ||
620 | |||
621 | shm_params.key = key; | 625 | shm_params.key = key; |
622 | shm_params.flg = shmflg; | 626 | shm_params.flg = shmflg; |
623 | shm_params.u.size = size; | 627 | shm_params.u.size = size; |
@@ -694,7 +698,7 @@ static inline unsigned long copy_shminfo_to_user(void __user *buf, struct shminf | |||
694 | out.shmmin = in->shmmin; | 698 | out.shmmin = in->shmmin; |
695 | out.shmmni = in->shmmni; | 699 | out.shmmni = in->shmmni; |
696 | out.shmseg = in->shmseg; | 700 | out.shmseg = in->shmseg; |
697 | out.shmall = in->shmall; | 701 | out.shmall = in->shmall; |
698 | 702 | ||
699 | return copy_to_user(buf, &out, sizeof(out)); | 703 | return copy_to_user(buf, &out, sizeof(out)); |
700 | } | 704 | } |
@@ -1160,6 +1164,9 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, | |||
1160 | down_write(¤t->mm->mmap_sem); | 1164 | down_write(¤t->mm->mmap_sem); |
1161 | if (addr && !(shmflg & SHM_REMAP)) { | 1165 | if (addr && !(shmflg & SHM_REMAP)) { |
1162 | err = -EINVAL; | 1166 | err = -EINVAL; |
1167 | if (addr + size < addr) | ||
1168 | goto invalid; | ||
1169 | |||
1163 | if (find_vma_intersection(current->mm, addr, addr + size)) | 1170 | if (find_vma_intersection(current->mm, addr, addr + size)) |
1164 | goto invalid; | 1171 | goto invalid; |
1165 | /* | 1172 | /* |