#include <linux/proc_fs.h>
#include <linux/shmem_fs.h>
#include <linux/security.h>
-#include <linux/vs_base.h>
+#include <linux/syscalls.h>
+#include <linux/audit.h>
+#include <linux/ptrace.h>
+#include <linux/vs_limit.h>
#include <asm/uaccess.h>
*/
static void shm_destroy (struct shmid_kernel *shp)
{
- shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ struct vx_info *vxi = locate_vx_info(shp->shm_perm.xid);
+ int numpages = (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ vx_ipcshm_sub(vxi, shp, numpages);
+ shm_tot -= numpages;
+
shm_rmid (shp->id);
shm_unlock(shp);
if (!is_file_hugepages(shp->shm_file))
shp->mlock_user);
fput (shp->shm_file);
security_shm_free(shp);
+ put_vx_info(vxi);
ipc_rcu_putref(shp);
}
if (shm_tot + numpages >= shm_ctlall)
return -ENOSPC;
+ if (!vx_ipcshm_avail(current->vx_info, numpages))
+ return -ENOSPC;
shp = ipc_rcu_alloc(sizeof(*shp));
if (!shp)
return -ENOMEM;
shp->shm_perm.key = key;
- shp->shm_perm.xid = current->xid;
+ shp->shm_perm.xid = vx_current_xid();
shp->shm_flags = (shmflg & S_IRWXUGO);
shp->mlock_user = NULL;
else
file->f_op = &shm_file_operations;
shm_tot += numpages;
+ vx_ipcshm_add(current->vx_info, key, numpages);
shm_unlock(shp);
return shp->id;
case SHM_LOCK:
case SHM_UNLOCK:
{
- /* 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;
if(err)
goto out_unlock;
+ if (!capable(CAP_IPC_LOCK)) {
+ err = -EPERM;
+ if (current->euid != shp->shm_perm.uid &&
+ current->euid != shp->shm_perm.cuid)
+ goto out_unlock;
+ if (cmd == SHM_LOCK &&
+ !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
+ goto out_unlock;
+ }
+
err = security_shm_shmctl(shp, cmd);
if (err)
goto out_unlock;
err = -EFAULT;
goto out;
}
+ if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
+ return err;
down(&shm_ids.sem);
shp = shm_lock(shmid);
err=-EINVAL;
return err;
}
+asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg)
+{
+ unsigned long ret;
+ long err;
+
+ err = do_shmat(shmid, shmaddr, shmflg, &ret);
+ if (err)
+ return err;
+ force_successful_syscall_return();
+ return (long)ret;
+}
+
/*
* detach and kill segment if marked destroyed.
* The work is done in shm_close.