diff options
| author | Pavel Emelianov <xemul@openvz.org> | 2007-07-31 03:38:48 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-31 18:39:40 -0400 |
| commit | 7be77e20d59fc3dd3fdde31641e0bc821114d26b (patch) | |
| tree | 558507e6fe540d1deddb2dbce9b3a7cca855a57e /ipc | |
| parent | ad0b142772eb1f88f0e77cb63c38b0005e83c2bd (diff) | |
Fix user struct leakage with locked IPC shem segment
When user locks an ipc shmem segmant with SHM_LOCK ctl and the segment is
already locked the shmem_lock() function returns 0. After this the
subsequent code leaks the existing user struct:
== ipc/shm.c: sys_shmctl() ==
...
err = shmem_lock(shp->shm_file, 1, user);
if (!err) {
shp->shm_perm.mode |= SHM_LOCKED;
shp->mlock_user = user;
}
...
==
Other results of this are:
1. the new shp->mlock_user is not get-ed and will point to freed
memory when the task dies.
2. the RLIMIT_MEMLOCK is screwed on both user structs.
The exploit looks like this:
==
id = shmget(...);
setresuid(uid, 0, 0);
shmctl(id, SHM_LOCK, NULL);
setresuid(uid + 1, 0, 0);
shmctl(id, SHM_LOCK, NULL);
==
My solution is to return 0 to the userspace and do not change the
segment's user.
Signed-off-by: Pavel Emelianov <xemul@openvz.org>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc')
| -rw-r--r-- | ipc/shm.c | 2 |
1 files changed, 1 insertions, 1 deletions
| @@ -716,7 +716,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
| 716 | struct user_struct * user = current->user; | 716 | struct user_struct * user = current->user; |
| 717 | if (!is_file_hugepages(shp->shm_file)) { | 717 | if (!is_file_hugepages(shp->shm_file)) { |
| 718 | err = shmem_lock(shp->shm_file, 1, user); | 718 | err = shmem_lock(shp->shm_file, 1, user); |
| 719 | if (!err) { | 719 | if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){ |
| 720 | shp->shm_perm.mode |= SHM_LOCKED; | 720 | shp->shm_perm.mode |= SHM_LOCKED; |
| 721 | shp->mlock_user = user; | 721 | shp->mlock_user = user; |
| 722 | } | 722 | } |
