Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp896335imu; Tue, 11 Dec 2018 09:13:01 -0800 (PST) X-Google-Smtp-Source: AFSGD/UY4X+/dkIWmLRioPM0Dq/uALHre8mUwTKmS9v8tz02b+aSTDPmsaslzxiotG+HDkj2XCjr X-Received: by 2002:a17:902:2c03:: with SMTP id m3mr5234451plb.6.1544548381695; Tue, 11 Dec 2018 09:13:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544548381; cv=none; d=google.com; s=arc-20160816; b=KL5cTAQpkHJUoSUCaayTze+KrZHiYYakz3JjsMTI4c63pS+j4tasTyJMpowsg3ax2T 0dIKto740/Tx+eWIVN53pZQJdneroPC/K6tVgWMNDJWVB3aFmIUAI5KErewmmEIRtrI9 /Nmbw1z74fWy9D+aduvIJeRgD0tmyfIrdXrcpPrzFzxG/DpLGSX2/er2rgODXiBMkq+C 9BRjWA8YH8EpjlCf3dQi0SclHoL6fJOEtVLdo6i189UEU+lY2EVc4J6ZssrAWxJ3PMM0 Tjr1CbqsL3YUMxkIJLwUjED1urebKJ/uAeNgLjuw3zpXal5EJZ7z3R4wXxBrg0KWHGSX kVBw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=ByGof7vvUQpU89bjBY9lOV2PtBhuVnEOnqwtnop8rVc=; b=ofSRUvD0pcW1BYUsiLjGg3K4ZFh1/wlVQVYQJrLVrc9IfUA8j+ys8GLk+BJYO24BGv H03iVCE/J9S6j2C0eghBqZ8Vcv288xHTUoo5mnVPNw1mr80glrc/nPE+YEXwkIPDojwX 0OV4XYHWT68qSWsZVlwPzLGNITb+mBQnBI9GlrVJc3sEaO9S2l95b9WlfUgFdRSXA5EO Uih7tYX0Y8GjhhXIenxJ4NwY1GPz8hfuUgUJfRhPP8xvTtTwuiA/0evxJ0rbWE1YX7Kf ZFexsVvV82oYBvkDYJd00lTh14yaiDd/ZlFb1fFsi6wM0Rq/yNNH1rtdmgLny//Bfpzt 6ySA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=codethink.co.uk Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h5si13738237pfg.233.2018.12.11.09.12.45; Tue, 11 Dec 2018 09:13:01 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=codethink.co.uk Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726848AbeLKPVc (ORCPT + 99 others); Tue, 11 Dec 2018 10:21:32 -0500 Received: from imap1.codethink.co.uk ([176.9.8.82]:57999 "EHLO imap1.codethink.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726809AbeLKPVb (ORCPT ); Tue, 11 Dec 2018 10:21:31 -0500 Received: from office.codethink.co.uk ([148.252.241.226] helo=devhw0) by imap1.codethink.co.uk with esmtpsa (Exim 4.84_2 #1 (Debian)) id 1gWjqW-0002GC-0P; Tue, 11 Dec 2018 15:21:16 +0000 Received: from tpreston by devhw0 with local (Exim 4.89) (envelope-from ) id 1gWjqV-0002EF-Ki; Tue, 11 Dec 2018 15:21:15 +0000 From: Thomas Preston To: akpm@linux-foundation.org, pmladek@suse.com, andriy.shevchenko@linux.intel.com, rostedt@goodmis.org, geert+renesas@glider.be, corbet@lwn.net, me@tobin.cc, sergey.senozhatsky@gmail.com, linux-kernel@vger.kernel.org Cc: Thomas Preston , Ben Dooks Subject: [PATCH 2/2] vsprintf: Stop using obsolete simple_strtoul() Date: Tue, 11 Dec 2018 15:21:13 +0000 Message-Id: <20181211152113.8523-3-thomas.preston@codethink.co.uk> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181211152113.8523-1-thomas.preston@codethink.co.uk> References: <20181211152113.8523-1-thomas.preston@codethink.co.uk> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Stop using the obsolete functions simple_strtoul() and simple_strtoull(). Instead, we should use the improved kstrtol() and kstrtoll() functions. To do this, we must copy the current field into a null-terminated tmpstr and advance the variable `next` manually. The width of tmpstr has been chosen because no integer field can be larger than 22 characters (ULLONG_MAX in octal), plus sign, radix, new-line, null-terminator and some extra for alignment. This patch fixes a bug with vsscanf. If passing sscan a 16-digit hex-string like so: sscanf("fafafafa0b0b0b0b", "%8x%8x", &hi, &lo) then the result comes out with hi always being 0. The issue is that the code calls simple_strtoul() which consumes up to 16-digits but only returns an unsigned long (8 hex digits on ARM). The vsscanf() code then checks and finds that the field_width of 8 was greater than the 16 consumed characters and tries to fix this by: while (next - str > field_width) { if (is_sign) val.s = div_s64(val.s, base); else val.u = div_u64(val.u, base); --next; } However val.{s,u} is already trunacted from the simple_strtoul call and all that happens is the value gets divided down to zero. Signed-off-by: Thomas Preston Signed-off-by: Ben Dooks --- lib/vsprintf.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index bbf2ac734711..ec23e18e8cc6 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -47,6 +47,8 @@ #include #include "kstrtox.h" +#define INT_BUF_LEN 28 + /** * simple_strtoull - convert a string to an unsigned long long * @cp: The start of the string @@ -2914,7 +2916,9 @@ int vsscanf(const char *buf, const char *fmt, va_list args) u8 qualifier; unsigned int base; union { + long sl; long long sll; + unsigned long ul; unsigned long long ull; } val; s16 field_width; @@ -3119,14 +3123,30 @@ int vsscanf(const char *buf, const char *fmt, va_list args) || (base == 0 && !isdigit(digit))) break; - if (is_sign) - val.sll = qualifier != 'L' ? - simple_strtol(str, &next, base) : - simple_strtoll(str, &next, base); - else - val.ull = qualifier != 'L' ? - simple_strtoul(str, &next, base) : - simple_strtoull(str, &next, base); + if (unlikely((field_width+1) > INT_BUF_LEN)) + return num; + + if (field_width > 0) { + char tmpstr[INT_BUF_LEN]; + int ret; + + strscpy(tmpstr, str, field_width+1); + + if (is_sign) + if (qualifier != 'L') + ret = kstrtol(tmpstr, base, &val.sl); + else + ret = kstrtoll(tmpstr, base, &val.sll); + else + if (qualifier != 'L') + ret = kstrtoul(tmpstr, base, &val.ul); + else + ret = kstrtoull(tmpstr, base, &val.ull); + if (ret < 0) + return num; + + } + next = (char *)str + field_width; if (field_width > 0 && next - str > field_width) { if (base == 0) -- 2.11.0