From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753417Ab0H0WDo (ORCPT ); Fri, 27 Aug 2010 18:03:44 -0400 Received: from smtp.outflux.net ([198.145.64.163]:50208 "EHLO smtp.outflux.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751565Ab0H0WDm (ORCPT ); Fri, 27 Aug 2010 18:03:42 -0400 Date: Fri, 27 Aug 2010 15:02:58 -0700 From: Kees Cook To: linux-kernel@vger.kernel.org Cc: oss-security@lists.openwall.com, Al Viro , Andrew Morton , Oleg Nesterov , KOSAKI Motohiro , Neil Horman , Roland McGrath , linux-fsdevel@vger.kernel.org Subject: [PATCH] exec argument expansion can inappropriately trigger OOM-killer Message-ID: <20100827220258.GF4703@outflux.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Organization: Canonical X-HELO: www.outflux.net Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Brad Spengler published a local memory-allocation DoS that evades the OOM-killer (though not the virtual memory RLIMIT): http://www.grsecurity.net/~spender/64bit_dos.c The recent changes to create a stack guard page helps slightly to discourage this attack, but it is not sufficient. Compiling it statically moves the libraries out of the way, allowing the stack VMA to fill the entire TASK_SIZE. There are two issues: 1) the OOM killer doesn't notice this argv memory explosion 2) the argv expansion does not check if rlim[RLIMIT_STACK].rlim_cur is -1. I figure a quick solution for #2 would be the following patch. However, running multiple copies of this program could result in similar OOM behavior, so issue #1 still needs a solution. Reported-by: Brad Spengler Signed-off-by: Kees Cook --- fs/exec.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index dab85ec..be40063 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -194,7 +194,8 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, * to work from. */ rlim = current->signal->rlim; - if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) { + if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4 || + size > TASK_SIZE / 4) { put_page(page); return NULL; } -- 1.7.1 -- Kees Cook Ubuntu Security Team