Reimplement RLIMIT_MEMLOCK on top of ucounts
The rlimit counter is tied to uid in the user_namespace. This allows rlimit values to be specified in userns even if they are already globally exceeded by the user. However, the value of the previous user_namespaces cannot be exceeded. Changelog v11: * Fix issue found by lkp robot. v8: * Fix issues found by lkp-tests project. v7: * Keep only ucounts for RLIMIT_MEMLOCK checks instead of struct cred. v6: * Fix bug in hugetlb_file_setup() detected by trinity. Reported-by: kernel test robot <oliver.sang@intel.com> Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Alexey Gladkov <legion@kernel.org> Link: https://lkml.kernel.org/r/970d50c70c71bfd4496e0e8d2a0a32feebebb350.1619094428.git.legion@kernel.org Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
This commit is contained in:
committed by
Eric W. Biederman
parent
d646969055
commit
d7c9e99aee
26
ipc/shm.c
26
ipc/shm.c
@@ -60,7 +60,7 @@ struct shmid_kernel /* private to the kernel */
|
||||
time64_t shm_ctim;
|
||||
struct pid *shm_cprid;
|
||||
struct pid *shm_lprid;
|
||||
struct user_struct *mlock_user;
|
||||
struct ucounts *mlock_ucounts;
|
||||
|
||||
/* The task created the shm object. NULL if the task is dead. */
|
||||
struct task_struct *shm_creator;
|
||||
@@ -286,10 +286,10 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
|
||||
shm_rmid(ns, shp);
|
||||
shm_unlock(shp);
|
||||
if (!is_file_hugepages(shm_file))
|
||||
shmem_lock(shm_file, 0, shp->mlock_user);
|
||||
else if (shp->mlock_user)
|
||||
shmem_lock(shm_file, 0, shp->mlock_ucounts);
|
||||
else if (shp->mlock_ucounts)
|
||||
user_shm_unlock(i_size_read(file_inode(shm_file)),
|
||||
shp->mlock_user);
|
||||
shp->mlock_ucounts);
|
||||
fput(shm_file);
|
||||
ipc_update_pid(&shp->shm_cprid, NULL);
|
||||
ipc_update_pid(&shp->shm_lprid, NULL);
|
||||
@@ -625,7 +625,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
|
||||
|
||||
shp->shm_perm.key = key;
|
||||
shp->shm_perm.mode = (shmflg & S_IRWXUGO);
|
||||
shp->mlock_user = NULL;
|
||||
shp->mlock_ucounts = NULL;
|
||||
|
||||
shp->shm_perm.security = NULL;
|
||||
error = security_shm_alloc(&shp->shm_perm);
|
||||
@@ -650,7 +650,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
|
||||
if (shmflg & SHM_NORESERVE)
|
||||
acctflag = VM_NORESERVE;
|
||||
file = hugetlb_file_setup(name, hugesize, acctflag,
|
||||
&shp->mlock_user, HUGETLB_SHMFS_INODE,
|
||||
&shp->mlock_ucounts, HUGETLB_SHMFS_INODE,
|
||||
(shmflg >> SHM_HUGE_SHIFT) & SHM_HUGE_MASK);
|
||||
} else {
|
||||
/*
|
||||
@@ -698,8 +698,8 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
|
||||
no_id:
|
||||
ipc_update_pid(&shp->shm_cprid, NULL);
|
||||
ipc_update_pid(&shp->shm_lprid, NULL);
|
||||
if (is_file_hugepages(file) && shp->mlock_user)
|
||||
user_shm_unlock(size, shp->mlock_user);
|
||||
if (is_file_hugepages(file) && shp->mlock_ucounts)
|
||||
user_shm_unlock(size, shp->mlock_ucounts);
|
||||
fput(file);
|
||||
ipc_rcu_putref(&shp->shm_perm, shm_rcu_free);
|
||||
return error;
|
||||
@@ -1105,12 +1105,12 @@ static int shmctl_do_lock(struct ipc_namespace *ns, int shmid, int cmd)
|
||||
goto out_unlock0;
|
||||
|
||||
if (cmd == SHM_LOCK) {
|
||||
struct user_struct *user = current_user();
|
||||
struct ucounts *ucounts = current_ucounts();
|
||||
|
||||
err = shmem_lock(shm_file, 1, user);
|
||||
err = shmem_lock(shm_file, 1, ucounts);
|
||||
if (!err && !(shp->shm_perm.mode & SHM_LOCKED)) {
|
||||
shp->shm_perm.mode |= SHM_LOCKED;
|
||||
shp->mlock_user = user;
|
||||
shp->mlock_ucounts = ucounts;
|
||||
}
|
||||
goto out_unlock0;
|
||||
}
|
||||
@@ -1118,9 +1118,9 @@ static int shmctl_do_lock(struct ipc_namespace *ns, int shmid, int cmd)
|
||||
/* SHM_UNLOCK */
|
||||
if (!(shp->shm_perm.mode & SHM_LOCKED))
|
||||
goto out_unlock0;
|
||||
shmem_lock(shm_file, 0, shp->mlock_user);
|
||||
shmem_lock(shm_file, 0, shp->mlock_ucounts);
|
||||
shp->shm_perm.mode &= ~SHM_LOCKED;
|
||||
shp->mlock_user = NULL;
|
||||
shp->mlock_ucounts = NULL;
|
||||
get_file(shm_file);
|
||||
ipc_unlock_object(&shp->shm_perm);
|
||||
rcu_read_unlock();
|
||||
|
||||
Reference in New Issue
Block a user