Received: by 2002:a05:6a10:9e8c:0:0:0:0 with SMTP id y12csp261522pxx; Thu, 29 Oct 2020 01:51:04 -0700 (PDT) X-Google-Smtp-Source: ABdhPJynDscxTyf8kxL/p1BG1H5KVinvbRfHwfA9+1aXrM+HE8gRIXdgR/7zJJvi08i1Z5sS1YZi X-Received: by 2002:a05:6402:941:: with SMTP id h1mr2807029edz.154.1603961463997; Thu, 29 Oct 2020 01:51:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1603961463; cv=none; d=google.com; s=arc-20160816; b=nko2suIRuWBl8jt9prUHZVv17Zierpp7QtIZSkEJ/WlixLwSNsNzCtdlknPF/m1Hts 73AiGV4QNXYMabfZ9twqDnIhR+xRAbVCw4q0CXUeQTCJ1OAtB2odAICjMJr/0TcC9eUP ABCKwt8HL8WAzYc8OdypUXqVXI7QTLtFFXMt1aDWWWB1WbNeA01n2MZQvGWmFpFVqUQU Lb469MR8nHUGlwOyvCinz04TddYFJSZJIyA2XvoUVa3t8Rtq7WEfjNtI8r5a8oJjXpNA IuXyhxQ8WZT4TN/uKLZhMtKmdjX9ieitOtj+/IJH1WtHdVI7fLlvnKjq0UpcA4Ik67Ny uLcQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:user-agent:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date; bh=AizHBq8oMCoTbLymgDhhcdkpB2AIWfKNHJwTVaEKJJA=; b=mAMqNwQ6bgLyhmQvutxoPvml7sXXSGKtbqV9S6alMHRYIVX2k1HT+F3Lx3ayZufuoA 3+DzBszfe0OCkmrAEvjvEhG1oWEIpfYlXrkVfNy8L6ZVGKkCVMlrfZR+EHk5CihfNmWH 7vo/O0ET+f40Qyq3TLoBljPW1eFu2Uh506w4XjM16/EMeItVJ+tbr1xXf14tKCVWKfoI OwWWaaMDQR8wpoZolOmUfku8kwUmLm3vCboI9JW4hLeNm5b1uU0lyhMB9x7oqHeNIW6w jQB/LacpI3+CRT1X2NNW9qVsye9WVkMkbwwYfQ2KbeTMQms3z08A0aU+RezxJzi6aMgH +lVw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id r26si1551150edt.63.2020.10.29.01.50.42; Thu, 29 Oct 2020 01:51:03 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729202AbgJ2CC7 (ORCPT + 99 others); Wed, 28 Oct 2020 22:02:59 -0400 Received: from bmailout3.hostsharing.net ([176.9.242.62]:56277 "EHLO bmailout3.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727953AbgJ1Vsu (ORCPT ); Wed, 28 Oct 2020 17:48:50 -0400 Received: from h08.hostsharing.net (h08.hostsharing.net [83.223.95.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by bmailout3.hostsharing.net (Postfix) with ESMTPS id DF3BF100E4169; Wed, 28 Oct 2020 10:59:46 +0100 (CET) Received: by h08.hostsharing.net (Postfix, from userid 100393) id A7AAA12805F; Wed, 28 Oct 2020 10:59:46 +0100 (CET) Date: Wed, 28 Oct 2020 10:59:46 +0100 From: Lukas Wunner To: Mark Brown Cc: Vladimir Oltean , Florian Fainelli , "linux-kernel@vger.kernel.org" , linux-spi , Sascha Hauer Subject: Re: Use after free in bcm2835_spi_remove() Message-ID: <20201028095946.GA25358@wunner.de> References: <20201014140912.GB24850@wunner.de> <20201014194035.ukduovokggu37uba@skbuf> <20201014202505.GF4580@sirena.org.uk> <20201015053829.GA2461@wunner.de> <20201015125335.GB4390@sirena.org.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20201015125335.GB4390@sirena.org.uk> User-Agent: Mutt/1.10.1 (2018-07-13) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Oct 15, 2020 at 01:53:35PM +0100, Mark Brown wrote: > On Thu, Oct 15, 2020 at 07:38:29AM +0200, Lukas Wunner wrote: > > On Wed, Oct 14, 2020 at 09:25:05PM +0100, Mark Brown wrote: > > How about holding a ref on the controller as long as the SPI driver > > is bound to the controller's parent device? See below for a patch, > > compile-tested only for lack of an SPI-equipped machine. [...] > > + spi_controller_get(ctlr); > > + ret = devm_add_action(dev, __spi_controller_put, ctlr); > > + if (ret) { > > + kfree(ctlr); > > This feels a bit icky - we're masking a standard use after free bug that > affects devm in general, not just this instance, and so while it will > work it doesn't feel great. If we did do this it'd need more comments > and should probably be conditional on using the feature. TBH I'm just > thinking it's better to just remove the feature, it's clearly error > prone and pretty redundant with devm. I'm not sure any memory savings > it's delivering are worth the sharp edges. A combined memory allocation for struct spi_controller and the private data has more benefits than just memory savings: Having them adjacent in memory reduces the chance of cache misses. Also, one can get from one struct to the other with a cheap subtraction (using container_of()) instead of having to chase pointers. So it helps performance. And a lack of pointers arguably helps security. Most subsystems embed the controller struct in the private data, but there *is* precedence for doing it the other way round. E.g. the IIO subsystem likewise appends the private data to the controller struct. So I think that's fine, it need not and should not be changed. The problem is that the ->probe() and ->remove() code is currently asymmetric, which is unintuitive: On ->probe(), there's an allocation step and a registration step: spi_alloc_master() spi_register_controller() Whereas on ->remove(), there's no step to free the master which would balance the prior alloc step: spi_unregister_controller() That's because the spi_controller struct is ref-counted and the last ref is usually dropped by spi_unregister_controller(). If the private data is accessed after the spi_unregister_controller() step, a ref needs to be held. I maintain that it would be more intuitive to automatically hold a ref. We could offer a devm_spi_alloc_master() function which holds this ref and automatically releases it on unbind. There are three drivers which call spi_alloc_master() with a size of zero for the private data. In these three cases it is fine to free the spi_controller struct upon spi_unregister_controller(). So these drivers can continue to use spi_alloc_master(). All other drivers could be changed to use the new devm_spi_alloc_master(), or I could scrutinize each of them and convert to the new function only if necessary. Does this sound more convincing to you? Thanks, Lukas