From patchwork Wed Sep 6 20:44:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Randy Dunlap X-Patchwork-Id: 9941291 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 406AE60216 for ; Wed, 6 Sep 2017 20:45:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3289A22376 for ; Wed, 6 Sep 2017 20:45:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 26A6D223A6; Wed, 6 Sep 2017 20:45:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EF82C223C6 for ; Wed, 6 Sep 2017 20:45:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752784AbdIFUow (ORCPT ); Wed, 6 Sep 2017 16:44:52 -0400 Received: from bombadil.infradead.org ([65.50.211.133]:50542 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752348AbdIFUov (ORCPT ); Wed, 6 Sep 2017 16:44:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=Content-Transfer-Encoding: Content-Type:In-Reply-To:MIME-Version:Date:Message-ID:From:Cc:References:To: Subject:Sender:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=NI90S/cdyNbta1MQr0r42WoARtaTyFFpyB9eS9R57SY=; b=uVGh7uDP4vxRcIm4KBSneenOs pBR/8NZKdLFt9Wbok6+/8fQn+9ZJ73RCEsjknw7wI11+TjR7ro8R42CFAN8n0+I9EvBpkM/+Wd9tR SSgneUijjTmJuHFvQ/a7aqjBo8rictFxF+opM1xvXoFskauNex8Ux5/4t9WeF5n7hWDutu9FhSUd9 qikqRbznkrJ1fkpak1PE3TqSDO3g8gdepLVdSyNfFQk7DTde2n5BOS6xOzraYkymPX74p1xwgJtQ8 Daf2+QP4JtSdD5+5FWaBqmC2GzQtzP6Z3srY37x7JHrzRPBd9TFOW61SbZUwkrM6cBtTJSA7RBJDb ifthJenCw==; Received: from static-50-53-52-16.bvtn.or.frontiernet.net ([50.53.52.16] helo=midway.dunlap) by bombadil.infradead.org with esmtpsa (Exim 4.87 #1 (Red Hat Linux)) id 1dphBp-0008LG-GR; Wed, 06 Sep 2017 20:44:49 +0000 Subject: Re: UBSAN: Undefined error in log2.h To: Shankara Pailoor , linux-kernel@vger.kernel.org References: Cc: Linux FS Devel , Al Viro , Andrew Morton From: Randy Dunlap Message-ID: <7ccba84e-7a41-3a89-ae01-fca62011081b@infradead.org> Date: Wed, 6 Sep 2017 13:44:48 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.3.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP [add Al Viro and linux-fsdevel] On 09/05/17 21:58, Shankara Pailoor wrote: > Hi, > > I am hitting this bug when running the syzkaller fuzzer on kernel 4.13-rc7 > > Syzkaller hit 'UBSAN: Undefined behaviour in ./include/linux/log2.h:LINE' bug. > > Guilty file: fs/pipe.c > > Maintainers: [] > > UBSAN: Undefined behaviour in ./include/linux/log2.h:57:13 > shift exponent 64 is too large for 64-bit type 'long unsigned int' See below. > CPU: 3 PID: 2712 Comm: syz-executor0 Not tainted 4.13.0-rc7 #2 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS > Ubuntu-1.8.2-1ubuntu1 04/01/2014 > Call Trace: > __dump_stack lib/dump_stack.c:16 [inline] > dump_stack+0xf7/0x1ae lib/dump_stack.c:52 > ubsan_epilogue+0x12/0x8f lib/ubsan.c:164 > __ubsan_handle_shift_out_of_bounds+0x2b2/0x32c lib/ubsan.c:421 > __roundup_pow_of_two include/linux/log2.h:57 [inline] > round_pipe_size fs/pipe.c:1027 [inline] > pipe_set_size fs/pipe.c:1041 [inline] > pipe_fcntl+0x6b6/0x7b0 fs/pipe.c:1158 > do_fcntl+0x362/0x1250 fs/fcntl.c:416 > SYSC_fcntl fs/fcntl.c:462 [inline] > SyS_fcntl+0xd6/0x110 fs/fcntl.c:447 > entry_SYSCALL_64_fastpath+0x18/0xad > RIP: 0033:0x451e59 > RSP: 002b:00007ffe1469d358 EFLAGS: 00000212 ORIG_RAX: 0000000000000048 > RAX: ffffffffffffffda RBX: 0000000000718000 RCX: 0000000000451e59 > RDX: 0000000000000000 RSI: 0000000000000407 RDI: 0000000000000003 > RBP: 0000000000000046 R08: 0000000000000000 R09: 0000000000000000 > R10: 0000000000000000 R11: 0000000000000212 R12: 0000000020011ff8 > R13: 0000000000718000 R14: 0000000000000000 R15: 0000000000000000 > ================================================================================ > > I have the full reproducer program here: https://pastebin.com/mLZx0ySS > > The main code is below: > > long r[4]; > void loop() > { > syscall(SYS_write, 1, "executing program\n", strlen("executing program\n")); > memset(r, -1, sizeof(r)); > r[0] = syscall(__NR_mmap, 0x20000000ul, 0x12000ul, 0x3ul, 0x32ul, > 0xfffffffffffffffful, 0x0ul); > r[1] = syscall(__NR_pipe, 0x20011ff8ul); > if (r[1] != -1) > NONFAILING(r[2] = *(uint32_t*)0x20011ff8); > r[3] = syscall(__NR_fcntl, r[2], 0x407ul, 0x0ul); That's F_SETPIPE_SZ to 0, right? > } so pipe_set_size(pipe, 0UL) does size = round_pipe_size(arg); which is: static inline unsigned int round_pipe_size(unsigned int size) { unsigned long nr_pages; nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; return roundup_pow_of_two(nr_pages) << PAGE_SHIFT; } so we have: nr_pages = (0 + 4096 - 1) >> 12; i.e. nr_pages = 0 return roundup_pow_of_two(0) << 12; ... return __roundup_pow_of_two(0) << 12; Look at __roundup_pow_of_two(0): return 1UL << fls_long(n - 1); ... return 1UL << fls_long(-1) ... return 1UL << 64; // UBSAN kicks in. We could try to fix the basic low-level functions to handle 0 (where says the result is undefined when n == 0), but ISTM the safest thing to do for now would be just to patch fs/pipe.c as follows; I think that I have stared at this long enough for now. eh? --- lnx-413.orig/fs/pipe.c +++ lnx-413/fs/pipe.c @@ -1038,6 +1038,8 @@ static long pipe_set_size(struct pipe_in unsigned long user_bufs; long ret = 0; + if (!arg) + arg = PAGE_SIZE; size = round_pipe_size(arg); nr_pages = size >> PAGE_SHIFT;