Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp218920ybi; Thu, 30 May 2019 23:56:52 -0700 (PDT) X-Google-Smtp-Source: APXvYqzoo51D8JJtWcfz0YZY373++maLb0Q3+89C/MZBciXMOOCT9CRW++pAMyBVdajNiCPOySP/ X-Received: by 2002:a62:7610:: with SMTP id r16mr8053302pfc.69.1559285812012; Thu, 30 May 2019 23:56:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1559285812; cv=none; d=google.com; s=arc-20160816; b=bRXAiSjo0i20Dq9GM6NiJkSTuu+zHD8WQ6IoreweJTUdzwyBlpInbyPcm5O7P/A6ww wPSqmBFAExcCRi0QQHcwjJL6umegjHUxS4xxqEeIaB0jP/WFcuzwLgTyv/moT+pFmWJ/ VLb91h697tWXXrY5yT3xSizD/ez8kW0MAiTyH+h1VWKVzGUYIgn/4YpW58nMcM3uLKU6 A0e+vvrAKsVoSnYJGAWlv+I6JHJWUE0vY/QN19KGlR5uJDjN0xaygJIcfIROVYeVpy/B GzLgezfzx3IM9n9JhLQ8g0X5R+r0+Ksj8JvAGcv+YbbtZR56a+IzfZCEOtYHJyuV/e2z 2EuQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date; bh=S2WTRBnRZlgqR9W5J8UFALGY4tvIo2PmWqjQP6YXXjk=; b=BGynk4Hq6XmbY6jcdmQR4z/TtTGGgya4xyf4WmTS9fS4utLc/4yM8leztokzVITvU2 VfmYIZLMDzEKT5Cc3iRlztkPdS8izYLSNGZPWAeGHeunmG9r/yucCdueTuTculfk3E0S sEN85+CWjR0k7bG2Bw7N4i9yG4bSA6ojZ+Xfcau8zPm9HgX1O+NyIBmpUB8j1/2ACkPm 9y4/uxShiphJlr6zAggYG6W184bnIbtoAQtk7OXqq1j7u5spoWB76N0Ys9bGCs5gxiaR yi0WjAlVydbDbPRwqYiUv6sC/ESqAwcPd0Bd083N31JEfJYZxOVZFanWB/kdb8qJEwYg GpVg== 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m4si4660539pjk.66.2019.05.30.23.56.35; Thu, 30 May 2019 23:56:51 -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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726797AbfEaGye (ORCPT + 99 others); Fri, 31 May 2019 02:54:34 -0400 Received: from mx2.suse.de ([195.135.220.15]:34226 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725963AbfEaGye (ORCPT ); Fri, 31 May 2019 02:54:34 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id C1C6FAF8D; Fri, 31 May 2019 06:54:32 +0000 (UTC) Received: by unicorn.suse.cz (Postfix, from userid 1000) id 28191E00E3; Fri, 31 May 2019 08:54:32 +0200 (CEST) Date: Fri, 31 May 2019 08:54:32 +0200 From: Michal Kubecek To: Vivien Didelot Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, "David S. Miller" , linville@redhat.com, f.fainelli@gmail.com Subject: Re: [PATCH net-next] ethtool: do not use regs->len after ops->get_regs Message-ID: <20190531065432.GB15954@unicorn.suse.cz> References: <20190530235450.11824-1-vivien.didelot@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20190530235450.11824-1-vivien.didelot@gmail.com> User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, May 30, 2019 at 07:54:50PM -0400, Vivien Didelot wrote: > The kernel allocates a buffer of size ops->get_regs_len(), and pass > it to the kernel driver via ops->get_regs() for filling. > > There is no restriction about what the kernel drivers can or cannot > do with the regs->len member. Drivers usually ignore it or set > the same size again. However, ethtool_get_regs() must not use this > value when copying the buffer back to the user, because userspace may > have allocated a smaller buffer. For instance ethtool does that when > dumping the raw registers directly into a fixed-size file. > > Software may still make use of the regs->len value updated by the > kernel driver, but ethtool_get_regs() must use the original regs->len > given by userspace, up to ops->get_regs_len(), when copying the buffer. > > Also no need to check regbuf twice. > > Signed-off-by: Vivien Didelot > --- > net/core/ethtool.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/net/core/ethtool.c b/net/core/ethtool.c > index 4a593853cbf2..8f95c7b7cafe 100644 > --- a/net/core/ethtool.c > +++ b/net/core/ethtool.c > @@ -1338,38 +1338,40 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, > static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) > { > struct ethtool_regs regs; > const struct ethtool_ops *ops = dev->ethtool_ops; > void *regbuf; > int reglen, ret; > > if (!ops->get_regs || !ops->get_regs_len) > return -EOPNOTSUPP; > > if (copy_from_user(®s, useraddr, sizeof(regs))) > return -EFAULT; > > reglen = ops->get_regs_len(dev); > if (reglen <= 0) > return reglen; > > if (regs.len > reglen) > regs.len = reglen; > + else > + reglen = regs.len; This seems wrong. Most drivers do not check regs.len in their get_regs() handler (I'm not sure if there are any that do) and simply write as much data as they have. Thus if userspace passes too short regs.len, this would replace overflow of a userspace buffer for few drivers by overflow of a kernel buffer for (almost) all drivers. So while we should use the original regs.len from userspace for final copy_to_user(), we have to allocate the buffer for driver ->get_regs() callback with size returned by its ->get_regs_len() callback. Michal Kubecek > > regbuf = vzalloc(reglen); > if (!regbuf) > return -ENOMEM; > > ops->get_regs(dev, ®s, regbuf); > > ret = -EFAULT; > if (copy_to_user(useraddr, ®s, sizeof(regs))) > goto out; > useraddr += offsetof(struct ethtool_regs, data); > - if (regbuf && copy_to_user(useraddr, regbuf, regs.len)) > + if (copy_to_user(useraddr, regbuf, reglen)) > goto out; > ret = 0; > > out: > vfree(regbuf); > return ret; > } > -- > 2.21.0 >