aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorMichael Kerrisk <mtk-lkml@gmx.net>2004-11-28 21:38:43 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-11-28 21:38:43 -0800
commit193aa382b81583beee3b6c2f05f6d012bf8dacec (patch)
tree1ac5cdf1c6f0a44f945ff09ac65fd960788415b5 /mm
parent8b92757dc223d2eddf8beb914bd5266bc8d8fc96 (diff)
downloadhistory-193aa382b81583beee3b6c2f05f6d012bf8dacec.tar.gz
[PATCH] RLIMIT_MEMLOCK accounting of shmctl() SHM_LOCK is broken
The accounting of shmctl() SHM_LOCK memory locks against the user structure is broken. The check of the size of the to-be-locked region is based on the size of the segment as specified when it was created by shmget() (this size is *not* rounded up to a page boundary). Fix it by rounding the size properlt. Also, tune up the spinlock coverage in there a little. Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/mlock.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/mm/mlock.c b/mm/mlock.c
index 4a00277487bad9..a75902f0485efc 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -211,10 +211,10 @@ int user_shm_lock(size_t size, struct user_struct *user)
unsigned long lock_limit, locked;
int allowed = 0;
- spin_lock(&shmlock_user_lock);
- locked = size >> PAGE_SHIFT;
+ locked = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
lock_limit >>= PAGE_SHIFT;
+ spin_lock(&shmlock_user_lock);
if (locked + user->locked_shm > lock_limit && !capable(CAP_IPC_LOCK))
goto out;
get_uid(user);
@@ -228,7 +228,7 @@ out:
void user_shm_unlock(size_t size, struct user_struct *user)
{
spin_lock(&shmlock_user_lock);
- user->locked_shm -= (size >> PAGE_SHIFT);
+ user->locked_shm -= (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
spin_unlock(&shmlock_user_lock);
free_uid(user);
}