Received: by 2002:a25:868d:0:0:0:0:0 with SMTP id z13csp502752ybk; Wed, 13 May 2020 05:53:25 -0700 (PDT) X-Google-Smtp-Source: APiQypJIvPTJw906rRZZnDYlsxz9+tkmKHvtkv+B5rCdP2K5OtlBKCBd4SlVougqrYJQsfWtqYB7 X-Received: by 2002:a05:6402:688:: with SMTP id f8mr21682710edy.233.1589374404912; Wed, 13 May 2020 05:53:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1589374404; cv=none; d=google.com; s=arc-20160816; b=TXQQSvc4oRaGPUh9Uci2dSGDgUPl5a7K09CFu7shWD9GM3zuxy17in1dkbU+STByMJ J7I9jwGQ1ydhg7c2mc3cbYIBQSyNVfEKrwYnzONcomLADhnozPWMdLnqngORLcY1PGGm 1awN3f4MMSvu0kmdQyU6CW1m8h1SF88JIykekOjAUkGVwmBxPIvYEUI2dra5De1vawMd tVUaL6n9qYZd35/Td7k56gFKXDF5RD4uL577PzMkX1UeGTE8KmEiazLxN5smE64BvAuh HLWNfi3bRYzuN/ekcV9S7YmZf7jDzGNO0ir2Pe9pk7hyvaflpvC41NvUMz+h97M/GIqN WP5A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date :dkim-signature:dkim-signature; bh=aeqv2tw69Ou73Ks80LeYEsoBf/9Sf5jfqw/n6jWNiu8=; b=wGTLioiLV8kNUNLE2N7PCteoFf9PjcqL3TqxKhzyfrm4maPE+8FbK/KvPjRNnkoHGK C8N8t135UcYWaA5Y/AsVUBOjQsFUj4KRKn+sUa+CHQHqsyUdpJUjlrZ7YcvlZ3AzO9kL MioOw8JXheVf2uOF+9PH42x/kh5jx3z8T+qCiOOSo5Xb2SpGvOyfxhuTj4tY3bSm+94y dkFPZKz/dBgwY8d6xlj3/1q2bTrVMuiDISxAc4hMsNP7HmlIAvmPTRJb6VTf/GYpdMkf sN2jX2alHQLzvM4hJDM65+w7O2nL7OurorqWX8ksUuYl+zqpbJeUrtRuc+1xSERySoCO 7HXw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kroah.com header.s=fm3 header.b=SXLj0aP6; dkim=pass header.i=@messagingengine.com header.s=fm2 header.b=VxSOX7XO; 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 c2si5648112ejb.278.2020.05.13.05.53.01; Wed, 13 May 2020 05:53:24 -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; dkim=pass header.i=@kroah.com header.s=fm3 header.b=SXLj0aP6; dkim=pass header.i=@messagingengine.com header.s=fm2 header.b=VxSOX7XO; 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 S1730848AbgEMMvU (ORCPT + 99 others); Wed, 13 May 2020 08:51:20 -0400 Received: from wout2-smtp.messagingengine.com ([64.147.123.25]:54299 "EHLO wout2-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728172AbgEMMvT (ORCPT ); Wed, 13 May 2020 08:51:19 -0400 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id D10997E3; Wed, 13 May 2020 08:51:17 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Wed, 13 May 2020 08:51:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kroah.com; h= date:from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm3; bh=aeqv2tw69Ou73Ks80LeYEsoBf/9 Sf5jfqw/n6jWNiu8=; b=SXLj0aP6PySWVLoEkMErwoCIBG+JjYjz58KGTwK1jYV OAXUgL7/JgHQJoS5YT6tYDmeXt6Yah6LLk9d2rJljbTrxYBt/3kIn4miy5E9nbcH C4CYx6MWJIiqMQLEAAgDhWFzEBNNNXts1t+WNOY3Z7Ygs4MFJdMUC3e+UbgZtMR9 vpeAffBK9MrrfNtonxB15jRfjOr+Cfc1n4a761+i4QeUUV0vo6FFDe/4MMhzoHI7 xILmvnZ/8aH3KSWA+nUMau4amQ6vZiiC3oVu+fppJLTKwjDXS4NTLBji+868lyUp /z9trypv5BEZN1MFDyjzASHqCFlh9AXjdwCNoTY1mdQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; bh=aeqv2t w69Ou73Ks80LeYEsoBf/9Sf5jfqw/n6jWNiu8=; b=VxSOX7XO3Luoc6SGQ8yML1 wQm8wqEySAq7L37HSqmMGUUIhGcp2Lx94/389Q/Odx/q5EZao5rKNaAgvn4yIK74 pB1Egez1vLGUNTtHOqlG+wvYQs1momAIJ8B+sFhTanqxczznriMIBp6Qeo/oiUpA 0KK4cJVk0srCT1zI4ngnr/hEgS4QX0OiRYoN5W50zdJ0W2vIiJhGy/1AQ7L6DdQ8 GWlTF6in56wR2dh8qnc7TNZpL+2k6gzaxP7zqMh/TpJmAJUcMLCO4GkjS9frleKK 0i+mGRW3C7E3WaIFHSaRHZ22NSKIPpJ1nfLRpgJPGkrdvZw1jZJyJhmFjWs38Uzg == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduhedrleeggdehiecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvuffkfhggtggujgesthdtredttddtvdenucfhrhhomhepifhrvghgucfm jfcuoehgrhgvgheskhhrohgrhhdrtghomheqnecuggftrfgrthhtvghrnhepueelledthe ekleethfeludduvdfhffeuvdffudevgeehkeegieffveehgeeftefgnecuffhomhgrihhn pehkvghrnhgvlhdrohhrghenucfkphepkeefrdekiedrkeelrddutdejnecuvehluhhsth gvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepghhrvghgsehkrhhorghh rdgtohhm X-ME-Proxy: Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) by mail.messagingengine.com (Postfix) with ESMTPA id CE6B83066309; Wed, 13 May 2020 08:51:16 -0400 (EDT) Date: Wed, 13 May 2020 14:51:12 +0200 From: Greg KH To: Charan Teja Kalla Cc: sumit.semwal@linaro.org, ghackmann@google.com, fengc@google.com, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, vinmenon@codeaurora.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org Subject: Re: [PATCH v2] dma-buf: fix use-after-free in dmabuffs_dname Message-ID: <20200513125112.GC1083139@kroah.com> References: <1588920063-17624-1-git-send-email-charante@codeaurora.org> <20200512085221.GB3557007@kroah.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, May 13, 2020 at 05:40:26PM +0530, Charan Teja Kalla wrote: > > Thank you Greg for the comments. > On 5/12/2020 2:22 PM, Greg KH wrote: > > On Fri, May 08, 2020 at 12:11:03PM +0530, Charan Teja Reddy wrote: > >> The following race occurs while accessing the dmabuf object exported as > >> file: > >> P1 P2 > >> dma_buf_release() dmabuffs_dname() > >> [say lsof reading /proc//fd/] > >> > >> read dmabuf stored in dentry->d_fsdata > >> Free the dmabuf object > >> Start accessing the dmabuf structure > >> > >> In the above description, the dmabuf object freed in P1 is being > >> accessed from P2 which is resulting into the use-after-free. Below is > >> the dump stack reported. > >> > >> We are reading the dmabuf object stored in the dentry->d_fsdata but > >> there is no binding between the dentry and the dmabuf which means that > >> the dmabuf can be freed while it is being read from ->d_fsdata and > >> inuse. Reviews on the patch V1 says that protecting the dmabuf inuse > >> with an extra refcount is not a viable solution as the exported dmabuf > >> is already under file's refcount and keeping the multiple refcounts on > >> the same object coordinated is not possible. > >> > >> As we are reading the dmabuf in ->d_fsdata just to get the user passed > >> name, we can directly store the name in d_fsdata thus can avoid the > >> reading of dmabuf altogether. > >> > >> Call Trace: > >> kasan_report+0x12/0x20 > >> __asan_report_load8_noabort+0x14/0x20 > >> dmabuffs_dname+0x4f4/0x560 > >> tomoyo_realpath_from_path+0x165/0x660 > >> tomoyo_get_realpath > >> tomoyo_check_open_permission+0x2a3/0x3e0 > >> tomoyo_file_open > >> tomoyo_file_open+0xa9/0xd0 > >> security_file_open+0x71/0x300 > >> do_dentry_open+0x37a/0x1380 > >> vfs_open+0xa0/0xd0 > >> path_openat+0x12ee/0x3490 > >> do_filp_open+0x192/0x260 > >> do_sys_openat2+0x5eb/0x7e0 > >> do_sys_open+0xf2/0x180 > >> > >> Fixes: bb2bb9030425 ("dma-buf: add DMA_BUF_SET_NAME ioctls") > >> Reported-by: syzbot+3643a18836bce555bff6@syzkaller.appspotmail.com > >> Cc: [5.3+] > >> Signed-off-by: Charan Teja Reddy > >> --- > >> > >> Changes in v2: > >> > >> - Pass the user passed name in ->d_fsdata instead of dmabuf > >> - Improve the commit message > >> > >> Changes in v1: (https://patchwork.kernel.org/patch/11514063/) > >> > >> drivers/dma-buf/dma-buf.c | 17 ++++++++++------- > >> 1 file changed, 10 insertions(+), 7 deletions(-) > >> > >> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c > >> index 01ce125..0071f7d 100644 > >> --- a/drivers/dma-buf/dma-buf.c > >> +++ b/drivers/dma-buf/dma-buf.c > >> @@ -25,6 +25,7 @@ > >> #include > >> #include > >> #include > >> +#include > >> > >> #include > >> #include > >> @@ -40,15 +41,13 @@ struct dma_buf_list { > >> > >> static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen) > >> { > >> - struct dma_buf *dmabuf; > >> char name[DMA_BUF_NAME_LEN]; > >> size_t ret = 0; > >> > >> - dmabuf = dentry->d_fsdata; > >> - dma_resv_lock(dmabuf->resv, NULL); > >> - if (dmabuf->name) > >> - ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN); > >> - dma_resv_unlock(dmabuf->resv); > >> + spin_lock(&dentry->d_lock); > > > > Are you sure this lock always protects d_fsdata? > > I think yes. In the dma-buf.c, I have to make sure that d_fsdata should > always be under d_lock thus it will be protected. (In this posted patch > there is one place(in dma_buf_set_name) that is missed, will update this > in V3). > > > > >> + if (dentry->d_fsdata) > >> + ret = strlcpy(name, dentry->d_fsdata, DMA_BUF_NAME_LEN); > >> + spin_unlock(&dentry->d_lock); > >> > >> return dynamic_dname(dentry, buffer, buflen, "/%s:%s", > >> dentry->d_name.name, ret > 0 ? name : ""); > > > > If the above check fails the name will be what? How could d_name.name > > be valid but d_fsdata not be valid? > > In case of check fails, empty string "" is appended to the name by the > code, ret > 0 ? name : "", ret is initialized to zero. Thus the name > string will be like "/dmabuf:". So multiple objects can have the same "name" if this happens to multiple ones at once? > Regarding the validity of d_fsdata, we are setting the dmabuf's > dentry->d_fsdata to NULL in the dma_buf_release() thus can go invalid if > that dmabuf is in the free path. Why are we allowing the name to be set if the dmabuf is on the free path at all? Shouldn't that be the real fix here? > >> @@ -80,12 +79,16 @@ static int dma_buf_fs_init_context(struct fs_context *fc) > >> static int dma_buf_release(struct inode *inode, struct file *file) > >> { > >> struct dma_buf *dmabuf; > >> + struct dentry *dentry = file->f_path.dentry; > >> > >> if (!is_dma_buf_file(file)) > >> return -EINVAL; > >> > >> dmabuf = file->private_data; > >> > >> + spin_lock(&dentry->d_lock); > >> + dentry->d_fsdata = NULL; > >> + spin_unlock(&dentry->d_lock); > >> BUG_ON(dmabuf->vmapping_counter); > >> > >> /* > >> @@ -343,6 +346,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf) > >> } > >> kfree(dmabuf->name); > >> dmabuf->name = name; > >> + dmabuf->file->f_path.dentry->d_fsdata = name; > > > > You are just changing the use of d_fsdata from being a pointer to the > > dmabuf to being a pointer to the name string? What's to keep that name > > string around and not have the same reference counting issues that the > > dmabuf structure itself has? Who frees that string memory? > > > > Yes, I am just storing the name string in the d_fsdata in place of > dmabuf and this helps to get rid of any extra refcount requirement. > Because the user passed name carried in the d_fsdata is copied to the > local buffer in dmabuffs_dname under spin_lock(d_lock) and the same > d_fsdata is set to NULL(under the d_lock only) when that dmabuf is in > the release path. So, when d_fsdata is NULL, name string is not accessed > from the dmabuffs_dname thus extra count is not required. > > String memory, stored in the dmabuf->name, is released from the > dma_buf_release(). Flow will be like, It fist sets d_fsdata=NULL and > then free the dmabuf->name. > > However from your comments I have realized that there is a race in this > patch when using the name string between dma_buf_set_name() and > dmabuffs_dname(). But, If the idea of passing the name string inplace of > dmabuf in d_fsdata looks fine, I can update this next patch. I'll leave that to the dmabuf authors/maintainers, but it feels odd to me... thanks, greg k-h