Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=7be77e20d59fc3dd3fdde31641e0bc821114d26b
Commit:     7be77e20d59fc3dd3fdde31641e0bc821114d26b
Parent:     ad0b142772eb1f88f0e77cb63c38b0005e83c2bd
Author:     Pavel Emelianov <[EMAIL PROTECTED]>
AuthorDate: Tue Jul 31 00:38:48 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue Jul 31 15:39:40 2007 -0700

    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 <[EMAIL PROTECTED]>
    Cc: <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 ipc/shm.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/ipc/shm.c b/ipc/shm.c
index d88ac5a..a86a3a5 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -716,7 +716,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct 
shmid_ds __user *buf)
                        struct user_struct * user = current->user;
                        if (!is_file_hugepages(shp->shm_file)) {
                                err = shmem_lock(shp->shm_file, 1, user);
-                               if (!err) {
+                               if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){
                                        shp->shm_perm.mode |= SHM_LOCKED;
                                        shp->mlock_user = user;
                                }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to