lkml.org 
[lkml]   [2018]   [Jul]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC][PATCH 25/27] do_shmat(): grab shp->shm_file earlier, switch to alloc_file_clone()
    Date
    From: Al Viro <viro@zeniv.linux.org.uk>

    Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
    ---
    ipc/shm.c | 39 ++++++++++++++++++---------------------
    1 file changed, 18 insertions(+), 21 deletions(-)

    diff --git a/ipc/shm.c b/ipc/shm.c
    index e37931121070..0cebcf74b669 100644
    --- a/ipc/shm.c
    +++ b/ipc/shm.c
    @@ -1354,14 +1354,13 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
    struct shmid_kernel *shp;
    unsigned long addr = (unsigned long)shmaddr;
    unsigned long size;
    - struct file *file;
    + struct file *file, *base;
    int err;
    unsigned long flags = MAP_SHARED;
    unsigned long prot;
    int acc_mode;
    struct ipc_namespace *ns;
    struct shm_file_data *sfd;
    - struct path path;
    fmode_t f_mode;
    unsigned long populate = 0;

    @@ -1435,46 +1434,44 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
    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++;
    - size = i_size_read(d_inode(path.dentry));
    + size = i_size_read(file_inode(base));
    ipc_unlock_object(&shp->shm_perm);
    rcu_read_unlock();

    err = -ENOMEM;
    sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
    if (!sfd) {
    - path_put(&path);
    + fput(base);
    goto out_nattch;
    }

    - file = alloc_file(&path, f_mode | FMODE_OPENED,
    - is_file_hugepages(shp->shm_file) ?
    + file = alloc_file_clone(base, f_mode,
    + is_file_hugepages(base) ?
    &shm_file_operations_huge :
    &shm_file_operations);
    err = PTR_ERR(file);
    if (IS_ERR(file)) {
    kfree(sfd);
    - path_put(&path);
    + fput(base);
    goto out_nattch;
    }

    - file->private_data = sfd;
    - file->f_mapping = shp->shm_file->f_mapping;
    sfd->id = shp->shm_perm.id;
    sfd->ns = get_ipc_ns(ns);
    - /*
    - * 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->file = base;
    sfd->vm_ops = NULL;
    + file->private_data = sfd;

    err = security_mmap_file(file, prot, flags);
    if (err)
    --
    2.11.0
    \
     
     \ /
      Last update: 2018-07-09 06:56    [W:3.285 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site