 110ecd69a9
			
		
	
	
	110ecd69a9
	
	
	
		
			
			p9_release_pages() would attempt to dereference one value past the end of pages[]. This would cause the following crashes: [ 6293.171817] BUG: unable to handle kernel paging request at ffff8807c96f3000 [ 6293.174146] IP: [<ffffffff8412793b>] p9_release_pages+0x3b/0x60 [ 6293.176447] PGD 79c5067 PUD 82c1e3067 PMD 82c197067 PTE 80000007c96f3060 [ 6293.180060] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC [ 6293.180060] Modules linked in: [ 6293.180060] CPU: 62 PID: 174043 Comm: modprobe Tainted: G W 3.10.0-next-20130710-sasha #3954 [ 6293.180060] task: ffff8807b803b000 ti: ffff880787dde000 task.ti: ffff880787dde000 [ 6293.180060] RIP: 0010:[<ffffffff8412793b>] [<ffffffff8412793b>] p9_release_pages+0x3b/0x60 [ 6293.214316] RSP: 0000:ffff880787ddfc28 EFLAGS: 00010202 [ 6293.214316] RAX: 0000000000000001 RBX: ffff8807c96f2ff8 RCX: 0000000000000000 [ 6293.222017] RDX: ffff8807b803b000 RSI: 0000000000000001 RDI: ffffea001c7e3d40 [ 6293.222017] RBP: ffff880787ddfc48 R08: 0000000000000000 R09: 0000000000000000 [ 6293.222017] R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000001 [ 6293.222017] R13: 0000000000000001 R14: ffff8807cc50c070 R15: ffff8807cc50c070 [ 6293.222017] FS: 00007f572641d700(0000) GS:ffff8807f3600000(0000) knlGS:0000000000000000 [ 6293.256784] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 6293.256784] CR2: ffff8807c96f3000 CR3: 00000007c8e81000 CR4: 00000000000006e0 [ 6293.256784] Stack: [ 6293.256784] ffff880787ddfcc8 ffff880787ddfcc8 0000000000000000 ffff880787ddfcc8 [ 6293.256784] ffff880787ddfd48 ffffffff84128be8 ffff880700000002 0000000000000001 [ 6293.256784] ffff8807b803b000 ffff880787ddfce0 0000100000000000 0000000000000000 [ 6293.256784] Call Trace: [ 6293.256784] [<ffffffff84128be8>] p9_virtio_zc_request+0x598/0x630 [ 6293.256784] [<ffffffff8115c610>] ? wake_up_bit+0x40/0x40 [ 6293.256784] [<ffffffff841209b1>] p9_client_zc_rpc+0x111/0x3a0 [ 6293.256784] [<ffffffff81174b78>] ? sched_clock_cpu+0x108/0x120 [ 6293.256784] [<ffffffff84122a21>] p9_client_read+0xe1/0x2c0 [ 6293.256784] [<ffffffff81708a90>] v9fs_file_read+0x90/0xc0 [ 6293.256784] [<ffffffff812bd073>] vfs_read+0xc3/0x130 [ 6293.256784] [<ffffffff811a78bd>] ? trace_hardirqs_on+0xd/0x10 [ 6293.256784] [<ffffffff812bd5a2>] SyS_read+0x62/0xa0 [ 6293.256784] [<ffffffff841a1a00>] tracesys+0xdd/0xe2 [ 6293.256784] Code: 66 90 48 89 fb 41 89 f5 48 8b 3f 48 85 ff 74 29 85 f6 74 25 45 31 e4 66 0f 1f 84 00 00 00 00 00 e8 eb 14 12 fd 41 ff c4 49 63 c4 <48> 8b 3c c3 48 85 ff 74 05 45 39 e5 75 e7 48 83 c4 08 5b 41 5c [ 6293.256784] RIP [<ffffffff8412793b>] p9_release_pages+0x3b/0x60 [ 6293.256784] RSP <ffff880787ddfc28> [ 6293.256784] CR2: ffff8807c96f3000 [ 6293.256784] ---[ end trace 50822ee72cd360fc ]--- Signed-off-by: Sasha Levin <sasha.levin@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
		
			
				
	
	
		
			69 lines
		
	
	
	
		
			2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
	
		
			2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright IBM Corporation, 2010
 | |
|  * Author Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify it
 | |
|  * under the terms of version 2.1 of the GNU Lesser General Public License
 | |
|  * as published by the Free Software Foundation.
 | |
|  *
 | |
|  * This program is distributed in the hope that it would be useful, but
 | |
|  * WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <linux/slab.h>
 | |
| #include <linux/module.h>
 | |
| #include <net/9p/9p.h>
 | |
| #include <net/9p/client.h>
 | |
| #include <linux/scatterlist.h>
 | |
| #include "trans_common.h"
 | |
| 
 | |
| /**
 | |
|  *  p9_release_req_pages - Release pages after the transaction.
 | |
|  */
 | |
| void p9_release_pages(struct page **pages, int nr_pages)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < nr_pages; i++)
 | |
| 		if (pages[i])
 | |
| 			put_page(pages[i]);
 | |
| }
 | |
| EXPORT_SYMBOL(p9_release_pages);
 | |
| 
 | |
| /**
 | |
|  * p9_nr_pages - Return number of pages needed to accommodate the payload.
 | |
|  */
 | |
| int p9_nr_pages(char *data, int len)
 | |
| {
 | |
| 	unsigned long start_page, end_page;
 | |
| 	start_page =  (unsigned long)data >> PAGE_SHIFT;
 | |
| 	end_page = ((unsigned long)data + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 | |
| 	return end_page - start_page;
 | |
| }
 | |
| EXPORT_SYMBOL(p9_nr_pages);
 | |
| 
 | |
| /**
 | |
|  * payload_gup - Translates user buffer into kernel pages and
 | |
|  * pins them either for read/write through get_user_pages_fast().
 | |
|  * @req: Request to be sent to server.
 | |
|  * @pdata_off: data offset into the first page after translation (gup).
 | |
|  * @pdata_len: Total length of the IO. gup may not return requested # of pages.
 | |
|  * @nr_pages: number of pages to accommodate the payload
 | |
|  * @rw: Indicates if the pages are for read or write.
 | |
|  */
 | |
| 
 | |
| int p9_payload_gup(char *data, int *nr_pages, struct page **pages, int write)
 | |
| {
 | |
| 	int nr_mapped_pages;
 | |
| 
 | |
| 	nr_mapped_pages = get_user_pages_fast((unsigned long)data,
 | |
| 					      *nr_pages, write, pages);
 | |
| 	if (nr_mapped_pages <= 0)
 | |
| 		return nr_mapped_pages;
 | |
| 
 | |
| 	*nr_pages = nr_mapped_pages;
 | |
| 	return 0;
 | |
| }
 | |
| EXPORT_SYMBOL(p9_payload_gup);
 |