Received: by 2002:a5b:505:0:0:0:0:0 with SMTP id o5csp1672765ybp; Wed, 9 Oct 2019 18:41:13 -0700 (PDT) X-Google-Smtp-Source: APXvYqxwy/+lEJAsE+neZycVyt0QaC+OhrZhUN5LhPkxmicBcfY3yXjer5mO5SYP+S+3adTywJHC X-Received: by 2002:a17:906:7e0c:: with SMTP id e12mr5684103ejr.20.1570671673712; Wed, 09 Oct 2019 18:41:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1570671673; cv=none; d=google.com; s=arc-20160816; b=JSgFUVVZiV1BOhnMitRes5M23CHtAuCUSGWcNE9zJvH1z0nIkDzQfiqb1X1YRTFj6f /RQPouD7oruCCQqTJNViqpuWO6ZAAlDtwLibpsRS9xcbCTjAQ8npNH+/CqYQex9eMTIf UnCFFemCc1AnVXZUPkkFzuORimMjK9qTrQYR2ebRJFOuRNlpgurYBqwIhdaf0NjnoACI oo4BxnMF8A5v/g96Zg//VS8nPa+QFXbY3IDyxLVuIak/UVtVAqfYukRYCCArH5ys6u2Z y7VJOIVKtYyUD2v7LCIK3gUHaPPGkelhpLY56Jy8RrYoQHS2ZA6mrsW1iaMuJTTJGXxr Elzw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=UFJYsUva5FRhcAbZsdQcSuIVXzC9BSS6Ql6F/47Wmsk=; b=iPcGNXJcqiTBk7WQO6KXSvJfghbqidzp/PEqli+CPQrXuo1s48jYDHyAQCQ6HNDixh +S8AqvRCzALgzxfdqkV1wYTUf0wiEJwJvu+xwYcr9UiHQj+3Fxi7xwBa/TPPP9W6vPHc Dqy2iENOHMS42hBqHI3CxmEqvuiMkweJYZ7IFdzxjJ4DgOE6He6OPpr/iEd96/JRPaQ8 uj9tGTPogE5Hkg5lCeryWi98UF5ILEJjut+E7PKXO8iQaomD9jfm13tShaqRECxaNSMu V1UKxm2+wtlCzLeQk+3G1OWYliAlPz1kaB0gUM61Ykeoa1Ad+ralGtEeIcEMcz3+Nlyb x6Dw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=cvXsAm1q; 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=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z10si2258858edx.168.2019.10.09.18.40.49; Wed, 09 Oct 2019 18:41:13 -0700 (PDT) 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; dkim=pass header.i=@gmail.com header.s=20161025 header.b=cvXsAm1q; 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=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732447AbfJJBiZ (ORCPT + 99 others); Wed, 9 Oct 2019 21:38:25 -0400 Received: from mail-yb1-f195.google.com ([209.85.219.195]:44024 "EHLO mail-yb1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731553AbfJJBiY (ORCPT ); Wed, 9 Oct 2019 21:38:24 -0400 Received: by mail-yb1-f195.google.com with SMTP id y204so1395261yby.10 for ; Wed, 09 Oct 2019 18:38:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=UFJYsUva5FRhcAbZsdQcSuIVXzC9BSS6Ql6F/47Wmsk=; b=cvXsAm1qlmc+Kbv8i7YhK9zObTtu1ly7yMvlUxQMutSbYVH95MgCajf07z+x+zufvJ agz6VDwepjFNpv0zWKXH1nYHgoOgA+JmuYf63UOHiqz8yowM+06edu7A8w+EWHGDJcC3 4/JCFGwNqfNV8Z5rt+xsZVoLuslm2q1AMNPPeofdPgphamXuUaIZAKOZXkvnaRi2XIaU f0+WcyTD0LVRdG4VnbNCpnmyhyVOPDkWYhCdLGB7hGP4PgsbAuz9ZwQ7/yAfaOpyL7VF jZKlHGYStG7dboM/75SjdMtz1mNsq3C3npFYuxO3IQlg+qxZCbFXtXfAV6a5IVUwppxn ZGqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=UFJYsUva5FRhcAbZsdQcSuIVXzC9BSS6Ql6F/47Wmsk=; b=SuNWqY/Z5gQvUhjcpNbhGrEGeVbj3TP83adQKP5O77q4Ex0F0/2GuVAg1h+EwdodC7 BQFZ1JhwVT4TkZ51xWy2+VkZbhCTQwIezuZ3Gm9xn4oTxOjbiSAGMPHfJIsANqrUv6VO UN+sglh6y2VO5uADKJxZVcA7wI/0u/dM1LVMDUO+HsjRddR0nloKyAZhn0eO48NyCZQ+ CNDcVvvF7NBHMaOYRJF8iNfXtSwIS0COwFRzDkAijKs42sfjvbgFNNrSSFl7aae80J4p HtbX285D4enfAg5lv3lV01X7oBwZAZZ3YyaLZDJXjbA+/uQnBfsYIC34pc8sT4Kcwojv 0Ugw== X-Gm-Message-State: APjAAAV/R7tn6A9DFuvmgVDDb0W0DLrw3CSbi12uSl+DMOqQdai4sfOg g8us74tvvD2Z1fLyuCTbm+pApw6ghM7LO4UPdz6/zjUI8yY= X-Received: by 2002:a5b:d50:: with SMTP id f16mr3995164ybr.25.1570671503860; Wed, 09 Oct 2019 18:38:23 -0700 (PDT) MIME-Version: 1.0 References: <20191009192105.GC26530@ZenIV.linux.org.uk> In-Reply-To: <20191009192105.GC26530@ZenIV.linux.org.uk> From: Max Filippov Date: Wed, 9 Oct 2019 18:38:12 -0700 Message-ID: Subject: Re: [PATCH] xtensa: fix {get,put}_user() for 64bit values To: Al Viro Cc: "open list:TENSILICA XTENSA PORT (xtensa)" , LKML Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Oct 9, 2019 at 12:21 PM Al Viro wrote: > > First of all, on short copies __copy_{to,from}_user() return the amount > of bytes left uncopied, *not* -EFAULT. get_user() and put_user() are > expected to return -EFAULT on failure. > > Another problem is get_user(v32, (__u64 __user *)p); that should > fetch 64bit value and the assign it to v32, truncating it in process. > Current code, OTOH, reads 8 bytes of data and stores them at the > address of v32, stomping on the 4 bytes that follow v32 itself. > > Signed-off-by: Al Viro > -- > diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h > index 6792928ba84a..155174ddb7ae 100644 > --- a/arch/xtensa/include/asm/uaccess.h > +++ b/arch/xtensa/include/asm/uaccess.h > @@ -100,7 +100,7 @@ do { \ > case 4: __put_user_asm(x, ptr, retval, 4, "s32i", __cb); break; \ > case 8: { \ > __typeof__(*ptr) __v64 = x; \ > - retval = __copy_to_user(ptr, &__v64, 8); \ > + retval = __copy_to_user(ptr, &__v64, 8) ? -EFAULT : 0; \ Sure, I agree with that. > break; \ > } \ > default: __put_user_bad(); \ > @@ -198,7 +198,12 @@ do { \ > case 1: __get_user_asm(x, ptr, retval, 1, "l8ui", __cb); break;\ > case 2: __get_user_asm(x, ptr, retval, 2, "l16ui", __cb); break;\ > case 4: __get_user_asm(x, ptr, retval, 4, "l32i", __cb); break;\ > - case 8: retval = __copy_from_user(&x, ptr, 8); break; \ > + case 8: { \ > + __u64 __x = 0; \ > + retval = __copy_from_user(&__x, ptr, 8) ? -EFAULT : 0; \ > + (x) = *(__force __typeof__(*(ptr)) *) &__x; \ > + break; \ > + } \ There's also the following code in the callers of this macro, e.g. in __get_user_nocheck: long __gu_err, __gu_val; \ __get_user_size(__gu_val, (ptr), (size), __gu_err); \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ the last line is important for sizes 1..4, because it takes care of sign extension of the value loaded by the assembly. At the same time the first line doesn't make sense for the size 8 as it will result in value truncation. How about the following change instead: diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index 6792928ba84a..c54893651d69 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h @@ -100,7 +100,7 @@ do { \ case 4: __put_user_asm(x, ptr, retval, 4, "s32i", __cb); break; \ case 8: { \ __typeof__(*ptr) __v64 = x; \ - retval = __copy_to_user(ptr, &__v64, 8); \ + retval = __copy_to_user(ptr, &__v64, 8) ? -EFAULT : 0; \ break; \ } \ default: __put_user_bad(); \ @@ -172,7 +172,8 @@ __asm__ __volatile__( \ #define __get_user_nocheck(x, ptr, size) \ ({ \ - long __gu_err, __gu_val; \ + long __gu_err; \ + __typeof__(*(ptr) + 0) __gu_val; \ __get_user_size(__gu_val, (ptr), (size), __gu_err); \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ @@ -180,7 +181,8 @@ __asm__ __volatile__( \ #define __get_user_check(x, ptr, size) \ ({ \ - long __gu_err = -EFAULT, __gu_val = 0; \ + long __gu_err = -EFAULT; \ + __typeof__(*(ptr) + 0) __gu_val = 0; \ const __typeof__(*(ptr)) *__gu_addr = (ptr); \ if (access_ok(__gu_addr, size)) \ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ @@ -198,7 +200,7 @@ do { \ case 1: __get_user_asm(x, ptr, retval, 1, "l8ui", __cb); break;\ case 2: __get_user_asm(x, ptr, retval, 2, "l16ui", __cb); break;\ case 4: __get_user_asm(x, ptr, retval, 4, "l32i", __cb); break;\ - case 8: retval = __copy_from_user(&x, ptr, 8); break; \ + case 8: retval = __copy_from_user(&x, ptr, 8) ? -EFAULT : 0; break; \ default: (x) = __get_user_bad(); \ } \ } while (0) Here __typeof__(*(ptr) + 0) makes enough room for all cases in the __get_user_size and the "+0" part takes care of pointers to const data. -- Thanks. -- Max