Patch "ipc/shm: handle removed segments gracefully in shm_mmap()" has been added to the 4.4-stable tree
This is a note to let you know that I've just added the patch titled
ipc/shm: handle removed segments gracefully in shm_mmap()
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ipc-shm-handle-removed-segments-gracefully-in-shm_mmap.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
1ac0b6dec656f3f78d1c3dd216fad84cb4d0a01eMon Sep 17 00:00:00 2001
From: "Kirill A. Shutemov" <[email protected]>
Date: Wed, 17 Feb 2016 13:11:35 -0800
Subject: ipc/shm: handle removed segments gracefully in shm_mmap()
From: Kirill A. Shutemov <[email protected]>
commit 1ac0b6dec656f3f78d1c3dd216fad84cb4d0a01e upstream.
remap_file_pages(2) emulation can reach file which represents removed IPC ID as long as a memory segment is mapped. It breaks expectations of IPC subsystem.
Test case (rewritten to be more human readable, originally autogenerated by syzkaller[1]):
#define _GNU_SOURCE
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/shm.h>
#define PAGE_SIZE 4096
int main()
{
int id;
void *p;
id = shmget(IPC_PRIVATE, 3 * PAGE_SIZE, 0);
p = shmat(id, NULL, 0);
shmctl(id, IPC_RMID, NULL);
remap_file_pages(p, 3 * PAGE_SIZE, 0, 7, 0);
return 0;
}The patch changes shm_mmap() and code around shm_lock() to propagate locking error back to caller of shm_mmap().
[1] http://github.com/google/syzkaller
--- ipc/shm.c | 53 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 10 deletions(-)
ipc/shm.c +43 -10
@@ -156,11 +156,12 @@ static inline struct shmid_kernel *shm_lstruct kern_ipc_perm *ipcp =ipc_lock (&shm_ids (ns), id);/* -* We raced in the idr lookup or with shm_destroy(). Either way, the -* ID is busted. +* Callers of shm_lock() must validate the status of the returned ipc +* object pointer (as returned by ipc_lock()), and error out as +* appropriate. */ -WARN_ON (IS_ERR (ipcp)); - +if (IS_ERR (ipcp)) +return (void *)ipcp; return container_of(ipcp, struct shmid_kernel, shm_perm); }
@@ -186,18 +187,33 @@ static inline void shm_rmid(struct ipc_n } -/* This is called by fork, once for every shm attach. */ -static void shm_open (struct vm_area_struct *vma) +static int __shm_open (struct vm_area_struct *vma) {struct file *file = vma->vm_file;struct shm_file_data *sfd =shm_file_data (file);struct shmid_kernel *shp; shp =shm_lock (sfd->ns, sfd->id); + +if (IS_ERR (shp)) +return PTR_ERR (shp); + shp->shm_atim =get_seconds (); shp->shm_lprid =task_tgid_vnr (current); shp->shm_nattch++;shm_unlock (shp); +return 0 ; +} + +/* This is called by fork, once for every shm attach. */ +static void shm_open (struct vm_area_struct *vma) +{ +int err =__shm_open (vma); +/* +* We raced in the idr lookup or with shm_destroy(). +* Either way, the ID is busted. +*/ +WARN_ON_ONCE (err); }/*
@@ -260,6 +276,14 @@ static void shm_close(struct vm_area_strdown_write (&shm_ids (ns).rwsem);/* remove from the list of attaches of the shm segment */ shp =shm_lock (ns, sfd->id); + +/* +* We raced in the idr lookup or with shm_destroy(). +* Either way, the ID is busted. +*/ +if (WARN_ON_ONCE (IS_ERR (shp))) + goto done;/* no-op */ + shp->shm_lprid =task_tgid_vnr (current); shp->shm_dtim =get_seconds (); shp->shm_nattch--;
@@ -267,6 +291,7 @@ static void shm_close(struct vm_area_strshm_destroy (ns, shp); elseshm_unlock (shp ); +done:up_write (&shm_ids (ns).rwsem); }
@@ -388,17 +413,25 @@ static int shm_mmap(struct file *file, sstruct shm_file_data *sfd =shm_file_data (file);int ret; +/* +* In case of remap_file_pages() emulation, the file can represent +* removed IPC ID: propogate shm_lock() error to caller. +*/ + ret =__shm_open (vma); +if (ret) +return ret; + ret = sfd->file->f_op->mmap (sfd->file, vma); -if (ret !=0 ) +if (ret) { +shm_close (vma);return ret; + } sfd->vm_ops = vma->vm_ops;#ifdef CONFIG_MMU WARN_ON (!sfd->vm_ops->fault);#endif vma->vm_ops = &shm_vm_ops; -shm_open (vma); - -return ret; +return 0 ; }static int shm_release (struct inode *ino,struct file *file)
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/mm-thp-khugepaged-call-pte-flush-at-the-time-of-collapse.patch queue-4.4/ipc-shm-handle-removed-segments-gracefully-in-shm_mmap.patch queue-4.4/drivers-scsi-sg.c-mark-vma-as-vm_io-to-prevent-migration.patch queue-4.4/mm-fix-mlock-accouting.patch queue-4.4/mm-replace-vma_lock_anon_vma-with-anon_vma_lock_read-write.patch queue-4.4/mm-fix-regression-in-remap_file_pages-emulation.patch queue-4.4/scsi-add-marvell-console-to-vpd-blacklist.patch