From mboxrd@z Thu Jan 1 00:00:00 1970 From: Sasha Levin Subject: [PATCH] pipe: Fail cleanly when root tries F_SETPIPE_SZ with big size Date: Fri, 18 Nov 2011 22:04:34 +0200 Message-ID: <1321646674-26890-1-git-send-email-levinsasha928@gmail.com> Cc: Sasha Levin , Alexander Viro , Pekka Enberg , linux-fsdevel@vger.kernel.org To: linux-kernel@vger.kernel.org Return-path: Sender: linux-kernel-owner@vger.kernel.org List-Id: linux-fsdevel.vger.kernel.org When a user with the CAP_SYS_RESOURCE cap tries to F_SETPIPE_SZ a pipe with size bigger than what kmalloc() can alloc it spits out an ugly warning: [ 3.651552] ------------[ cut here ]------------ [ 3.652644] WARNING: at mm/page_alloc.c:2095 __alloc_pages_nodemask+0x5d3/0x7a0() [ 3.654313] Pid: 733, comm: a.out Not tainted 3.2.0-rc1+ #4 [ 3.655568] Call Trace: [ 3.656207] [] ? __alloc_pages_nodemask+0x5d3/0x7a0 [ 3.657698] [] warn_slowpath_common+0x75/0xb0 [ 3.659018] [] warn_slowpath_null+0x15/0x20 [ 3.660468] [] __alloc_pages_nodemask+0x5d3/0x7a0 [ 3.665725] [] ? handle_pte_fault+0xf2/0x200 [ 3.667032] [] ? _raw_spin_unlock+0x9/0x40 [ 3.668283] [] ? __pte_alloc+0x96/0x150 [ 3.669354] [] ? get_empty_filp+0x91/0x160 [ 3.670238] [] ? handle_mm_fault+0x1a4/0x360 [ 3.671139] [] __get_free_pages+0x12/0x50 [ 3.671972] [] __kmalloc+0x12b/0x150 [ 3.672782] [] pipe_set_size+0x75/0x120 [ 3.673681] [] pipe_fcntl+0xf8/0x140 [ 3.674833] [] do_fcntl+0x2d4/0x410 [ 3.675960] [] ? do_pipe_flags+0xb2/0x100 [ 3.677218] [] sys_fcntl+0x66/0xa0 [ 3.678037] [] system_call_fastpath+0x16/0x1b [ 3.679008] ---[ end trace 432f702e6db7b5ee ]--- Instead, make sure we are trying to allocate less than the max possible before even trying to allocate it. This way we can avoid the warning if possible. Cc: Alexander Viro Cc: Pekka Enberg Cc: linux-fsdevel@vger.kernel.org Signed-off-by: Sasha Levin --- fs/pipe.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index 4065f07..c5a4ef1 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -1137,6 +1137,9 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages) if (nr_pages < pipe->nrbufs) return -EBUSY; + if (nr_pages * sizeof(struct pipe_buffer) > KMALLOC_MAX_SIZE) + return -ENOMEM; + bufs = kcalloc(nr_pages, sizeof(struct pipe_buffer), GFP_KERNEL); if (unlikely(!bufs)) return -ENOMEM; -- 1.7.8.rc1