X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ipc%2Fshm.c;h=54a50c29da275edf04e32b231950d935c7659f57;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=62c5393bbbe722a8462519fbd24927b5bcb5a17f;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/ipc/shm.c b/ipc/shm.c index 62c5393bb..54a50c29d 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -80,7 +80,7 @@ static inline struct shmid_kernel *shm_rmid(int id) static inline int shm_addid(struct shmid_kernel *shp) { - return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni+1); + return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni); } @@ -116,10 +116,13 @@ static void shm_destroy (struct shmid_kernel *shp) shm_rmid (shp->id); shm_unlock(shp); if (!is_file_hugepages(shp->shm_file)) - shmem_lock(shp->shm_file, 0); + shmem_lock(shp->shm_file, 0, shp->mlock_user); + else + user_shm_unlock(shp->shm_file->f_dentry->d_inode->i_size, + shp->mlock_user); fput (shp->shm_file); security_shm_free(shp); - ipc_rcu_free(shp, sizeof(struct shmid_kernel)); + ipc_rcu_putref(shp); } /* @@ -193,17 +196,20 @@ static int newseg (key_t key, int shmflg, size_t size) shp->shm_perm.key = key; shp->shm_perm.xid = current->xid; shp->shm_flags = (shmflg & S_IRWXUGO); + shp->mlock_user = NULL; shp->shm_perm.security = NULL; error = security_shm_alloc(shp); if (error) { - ipc_rcu_free(shp, sizeof(*shp)); + ipc_rcu_putref(shp); return error; } - if (shmflg & SHM_HUGETLB) + if (shmflg & SHM_HUGETLB) { + /* hugetlb_zero_setup takes care of mlock user accounting */ file = hugetlb_zero_setup(size); - else { + shp->mlock_user = current->user; + } else { sprintf (name, "SYSV%08x", key); file = shmem_file_setup(name, size, VM_ACCOUNT); } @@ -237,7 +243,7 @@ no_id: fput(file); no_file: security_shm_free(shp); - ipc_rcu_free(shp, sizeof(*shp)); + ipc_rcu_putref(shp); return error; } @@ -507,14 +513,11 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) case SHM_LOCK: case SHM_UNLOCK: { -/* Allow superuser to lock segment in memory */ -/* Should the pages be faulted in here or leave it to user? */ -/* need to determine interaction with current->swappable */ - if (!capable(CAP_IPC_LOCK)) { + /* Allow superuser to lock segment in memory */ + if (!can_do_mlock() && cmd == SHM_LOCK) { err = -EPERM; goto out; } - shp = shm_lock(shmid); if(shp==NULL) { err = -EINVAL; @@ -529,13 +532,18 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) goto out_unlock; if(cmd==SHM_LOCK) { - if (!is_file_hugepages(shp->shm_file)) - shmem_lock(shp->shm_file, 1); - shp->shm_flags |= SHM_LOCKED; - } else { - if (!is_file_hugepages(shp->shm_file)) - shmem_lock(shp->shm_file, 0); + struct user_struct * user = current->user; + if (!is_file_hugepages(shp->shm_file)) { + err = shmem_lock(shp->shm_file, 1, user); + if (!err) { + shp->shm_flags |= SHM_LOCKED; + shp->mlock_user = user; + } + } + } else if (!is_file_hugepages(shp->shm_file)) { + shmem_lock(shp->shm_file, 0, shp->mlock_user); shp->shm_flags &= ~SHM_LOCKED; + shp->mlock_user = NULL; } shm_unlock(shp); goto out; @@ -683,6 +691,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) o_flags = O_RDWR; acc_mode = S_IRUGO | S_IWUGO; } + if (shmflg & SHM_EXEC) { + prot |= PROT_EXEC; + acc_mode |= S_IXUGO; + } /* * We cannot rely on the fs check since SYSV IPC does have an @@ -857,7 +869,7 @@ static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int l if (!vx_check(shp->shm_perm.xid, VX_IDENT)) { shm_unlock(shp); - continue; + continue; } if (sizeof(size_t) <= sizeof(int)) format = SMALL_STRING;