提交 4f089acc 编写于 作者: A Al Viro

do_shmat(): grab shp->shm_file earlier, switch to alloc_file_clone()

Acked-by: NLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
上级 183266f2
...@@ -1354,14 +1354,13 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ...@@ -1354,14 +1354,13 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
struct shmid_kernel *shp; struct shmid_kernel *shp;
unsigned long addr = (unsigned long)shmaddr; unsigned long addr = (unsigned long)shmaddr;
unsigned long size; unsigned long size;
struct file *file; struct file *file, *base;
int err; int err;
unsigned long flags = MAP_SHARED; unsigned long flags = MAP_SHARED;
unsigned long prot; unsigned long prot;
int acc_mode; int acc_mode;
struct ipc_namespace *ns; struct ipc_namespace *ns;
struct shm_file_data *sfd; struct shm_file_data *sfd;
struct path path;
int f_flags; int f_flags;
unsigned long populate = 0; unsigned long populate = 0;
...@@ -1435,46 +1434,44 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ...@@ -1435,46 +1434,44 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
goto out_unlock; goto out_unlock;
} }
path = shp->shm_file->f_path; /*
path_get(&path); * We need to take a reference to the real shm file to prevent the
* pointer from becoming stale in cases where the lifetime of the outer
* file extends beyond that of the shm segment. It's not usually
* possible, but it can happen during remap_file_pages() emulation as
* that unmaps the memory, then does ->mmap() via file reference only.
* We'll deny the ->mmap() if the shm segment was since removed, but to
* detect shm ID reuse we need to compare the file pointers.
*/
base = get_file(shp->shm_file);
shp->shm_nattch++; shp->shm_nattch++;
size = i_size_read(d_inode(path.dentry)); size = i_size_read(file_inode(base));
ipc_unlock_object(&shp->shm_perm); ipc_unlock_object(&shp->shm_perm);
rcu_read_unlock(); rcu_read_unlock();
err = -ENOMEM; err = -ENOMEM;
sfd = kzalloc(sizeof(*sfd), GFP_KERNEL); sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
if (!sfd) { if (!sfd) {
path_put(&path); fput(base);
goto out_nattch; goto out_nattch;
} }
file = alloc_file(&path, f_flags, file = alloc_file_clone(base, f_flags,
is_file_hugepages(shp->shm_file) ? is_file_hugepages(base) ?
&shm_file_operations_huge : &shm_file_operations_huge :
&shm_file_operations); &shm_file_operations);
err = PTR_ERR(file); err = PTR_ERR(file);
if (IS_ERR(file)) { if (IS_ERR(file)) {
kfree(sfd); kfree(sfd);
path_put(&path); fput(base);
goto out_nattch; goto out_nattch;
} }
file->private_data = sfd;
file->f_mapping = shp->shm_file->f_mapping;
sfd->id = shp->shm_perm.id; sfd->id = shp->shm_perm.id;
sfd->ns = get_ipc_ns(ns); sfd->ns = get_ipc_ns(ns);
/* sfd->file = base;
* We need to take a reference to the real shm file to prevent the
* pointer from becoming stale in cases where the lifetime of the outer
* file extends beyond that of the shm segment. It's not usually
* possible, but it can happen during remap_file_pages() emulation as
* that unmaps the memory, then does ->mmap() via file reference only.
* We'll deny the ->mmap() if the shm segment was since removed, but to
* detect shm ID reuse we need to compare the file pointers.
*/
sfd->file = get_file(shp->shm_file);
sfd->vm_ops = NULL; sfd->vm_ops = NULL;
file->private_data = sfd;
err = security_mmap_file(file, prot, flags); err = security_mmap_file(file, prot, flags);
if (err) if (err)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册