From patchwork Tue Aug 13 16:32:59 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Geert Uytterhoeven X-Patchwork-Id: 2843866 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 980C79F294 for ; Tue, 13 Aug 2013 16:33:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 56BE3205C2 for ; Tue, 13 Aug 2013 16:33:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8EF73205A7 for ; Tue, 13 Aug 2013 16:33:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757859Ab3HMQdN (ORCPT ); Tue, 13 Aug 2013 12:33:13 -0400 Received: from jacques.telenet-ops.be ([195.130.132.50]:58170 "EHLO jacques.telenet-ops.be" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754280Ab3HMQdK (ORCPT ); Tue, 13 Aug 2013 12:33:10 -0400 Received: from ayla.of.borg ([84.193.72.141]) by jacques.telenet-ops.be with bizsmtp id CGZ41m00V32ts5g0JGZ4xW; Tue, 13 Aug 2013 18:33:08 +0200 Received: from geert (helo=localhost) by ayla.of.borg with local-esmtp (Exim 4.76) (envelope-from ) id 1V9HWl-0006Rz-T7; Tue, 13 Aug 2013 18:32:59 +0200 Date: Tue, 13 Aug 2013 18:32:59 +0200 (CEST) From: Geert Uytterhoeven To: Zach Brown , Andrew Morton cc: Andreas Schwab , Josef Bacik , Thorsten Glaser , Joe Perches , Debian GNU/Linux m68k , linux-btrfs@vger.kernel.org, Linux Kernel Development , David Woodhouse , Chris Mason Subject: Re: btrfs zero divide In-Reply-To: <20130809180441.GB12314@lenny.home.zabbo.net> Message-ID: References: <20130730171329.GF24583@localhost.localdomain> <20130730204001.GG24583@localhost.localdomain> <87eha33v9f.fsf@igel.home> <20130809180441.GB12314@lenny.home.zabbo.net> User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-9.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On Fri, 9 Aug 2013, Zach Brown wrote: > On Fri, Aug 09, 2013 at 02:26:36PM +0200, Andreas Schwab wrote: > > Josef Bacik writes: > > > > > So stripe_len shouldn't be 0, if it is you have bigger problems :). > > > > The bigger problem is that stripe_nr is u64, this is completely bogus. > > The first operand of do_div must be u32. This goes through the whole > > file. This was introduced by commit 53b381b3abeb86f12787a6c40fee9b2f71edc23b ("Btrfs: RAID5 and RAID6"), which changed the divisor from map->stripe_len (struct map_lookup.stripe_len is int) to a 64-bit temporary. > Definitely. Can we get some typeof() tricks in the macros to have the > build fail if (when, evidently) someone gets it wrong? Not using typeof, as there are way too many callsites where int is used instead of u32. However, checking that sizeof() equals to 4 seems to work. Below is a patch for asm-generic, which is untested, but it works when adding the same checks to arch/m68k/include/asm/div64.h This is not something we just want to drop in, as it has the potential of breaking lots of things (yes, it breaks btrfs :-) From 7ccabf41beae38da514f3e09624219a9362375d7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 13 Aug 2013 18:04:40 +0200 Subject: [PATCH] asm-generic: Check divisor size in do_div() The second parameter of do_div() should be a 32-bit number. Enforce this using BUILD_BUG_ON(). The first parameter of do_div() should be a 64-bit number, enforce this on 64-bit architectures, just like is done on 32-bit architectures. Signed-off-by: Geert Uytterhoeven --- include/asm-generic/div64.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/asm-generic/div64.h b/include/asm-generic/div64.h index 8f4e319..69c0307 100644 --- a/include/asm-generic/div64.h +++ b/include/asm-generic/div64.h @@ -19,12 +19,15 @@ #include #include +#include #if BITS_PER_LONG == 64 # define do_div(n,base) ({ \ uint32_t __base = (base); \ uint32_t __rem; \ + (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \ + BUILD_BUG_ON(sizeof(base) != 4); \ __rem = ((uint64_t)(n)) % __base; \ (n) = ((uint64_t)(n)) / __base; \ __rem; \ @@ -41,6 +44,7 @@ extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor); uint32_t __base = (base); \ uint32_t __rem; \ (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \ + BUILD_BUG_ON(sizeof(base) != 4); \ if (likely(((n) >> 32) == 0)) { \ __rem = (uint32_t)(n) % __base; \ (n) = (uint32_t)(n) / __base; \