From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f43.google.com (mail-wm1-f43.google.com [209.85.128.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 83AC63C553A for ; Wed, 27 May 2026 10:28:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.43 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779877684; cv=none; b=lMtaaCn3vxR3BI3g+mN6gxDdY1dysDkJMxrWA00I3qWihACC1mbin02oX9IN6LwI8dtBjVljwlvqM7regbIkBhOt36JyILXDYauHUvidGP86KgReXBrdqaV0qFaZ7FbTVGEHcytmnyc13FW+5xHScT0luUfsMMu1SXXj/l0fddU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779877684; c=relaxed/simple; bh=qKoShBmc+gDmPE3GgeVHAj77czNTJiRsMf19IzVPZcU=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=tIJ5zIMyy9uMAsIADWJZKpnp767rdxdimoazd6V4JXXn9g/F8XbIw3w4xNLVbOUnC/sH+XObFYMCZLWF5803JsU4agENFa3mWb7KA59LqpMBpqqJeQRZPispeUDbLdvL6gZWvSXl79O9zyVxlra2ZJcmHo5tSndIR2BqnPaf7GQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=debian.org; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.128.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm1-f43.google.com with SMTP id 5b1f17b1804b1-49040362e4aso59864545e9.0 for ; Wed, 27 May 2026 03:28:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779877679; x=1780482479; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GwGh4zf7B3gPFyimak7aCa+Z+XbFwJnS3td6dMioopc=; b=ePiDXajkC1UHFQmj1pELU3NybzPq0J26o6IvQitbeWDLN1NU14UKt08h5qiXHI+fGM Ce2NzDO+KKsbIVIgCOpdJqhXhsN2yR8r2d8n/8vmuBNf2s2tUMufWK2AEYd6uA8dKMjk z0kNMUGVSqVgd42FW7v38rmRIGMIgMhGJCLH/+mV8hBe0RpulRyARDQFMOuq23MPl95/ y8YykJ8BMnq/ny1MesnXkLn1lD2IAr/wqIYHkz/bmSM+W4pQvn4O/TNzccx3/XeYb/x7 M5HQMqStLwFtnozQXcbRjktyiq2EjoY5aWFUqd52qgdYbbsEj/mh1lRLg92sq1UUw+Ds WU/w== X-Forwarded-Encrypted: i=1; AFNElJ/CaGJdLc9hVsgV6gctXL++GEQ08NaAsWAIhhqLFsa/lCdEz/No8ELIxFTlO5LO9F4aGp8gRvy+7+Dv9Mo=@vger.kernel.org X-Gm-Message-State: AOJu0YzRUqd9MM+pb8yab2PSP0rxL4VAcoEOWNYU63bGCWSG+g38dVP0 CY4BBCEb+hdgxeXcSnVHONKKoc7DesteIayukimOCMqHpBsL9yMxh8FWNYtPCrOA X-Gm-Gg: Acq92OH71Vr40s3RQrwkDPP6nsZB1scQ3n6030vA8gabLUyD3DOQ8KicsN/8BVMwGvD hp1C7TdULkTfPo2LEkpJtqGHzecpD490wJ1H0tbdbE9YJXxW3MNh5ML2WeNtMqDTjEZC9VrFQWZ 7iK7qAkEdlkIo0qIshSm1raBFyQEqopESGTKAjLTJ9UTxCWp5Z1sXy/Ful8DdIROgcOA0+AuZHB WxV3HsMNTfbXU/Tc1TtAmv31oxrlcMuml3ojGBoQyDoT20Jicym1dxupY2wECYIqB/7tzkdfbCV 9fg85IEdt2aw5iv5SvhM1r2SITFxs+0zRH6iNEf4+Wnlae7iITreXFb94Mt720fp+zEpEZwmRsh 7vxCzQs3yqc9ZLBs3ewUrnUJ17DuAnRG0B7nMZr1aG2AGcUBdB/8nQA7xdS1hq/GP/Cmse15v5i RmUkCU4BQhvLEElEH2Snezn3FHYu4YJsbm/XFI X-Received: by 2002:a05:600c:6995:b0:490:482c:4384 with SMTP id 5b1f17b1804b1-490482c44ddmr371830255e9.24.1779877678707; Wed, 27 May 2026 03:27:58 -0700 (PDT) Received: from gmail.com ([62.197.47.167]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4904561f682sm410082785e9.13.2026.05.27.03.27.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 May 2026 03:27:58 -0700 (PDT) Date: Wed, 27 May 2026 11:27:57 +0100 From: Breno Leitao To: Farhad Alemi Cc: Andreas Hindborg , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [BUG] configfs: slab-use-after-free in configfs_drop_dentry() on rmdir Message-ID: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: On Tue, May 26, 2026 at 08:42:00PM +0000, Farhad Alemi wrote: > Hello Andreas and the configfs team, > > I am reporting a configfs use-after-free found by syzkaller. > > Summary: > A configfs config-item rmdir(2) can land in configfs_drop_dentry() with > sd->s_dentry pointing at a dentry whose RCU grace period has not yet > elapsed. The spin_lock(&dentry->d_lock) at fs/configfs/inode.c:209 then > reads freed slab memory and KASAN reports a slab-use-after-free. Thanks for the report. I was able to reproduce it on linus' upstream tree. I've came up with the following fix, would you mind trying it, please? commit d78c04736ef0ede76093c780a188560b6baed3c3 Author: Breno Leitao Date: Wed May 27 06:25:49 2026 -0400 configfs: fix UAF in configfs_drop_dentry() after failed attribute lookup When configfs_lookup() matches an attribute it publishes the new dentry into sd->s_dentry (and dentry->d_fsdata) before calling configfs_create() to allocate the inode: dentry->d_fsdata = configfs_get(sd); sd->s_dentry = dentry; spin_unlock(&configfs_dirent_lock); inode = configfs_create(dentry, mode); if (IS_ERR(inode)) { configfs_put(sd); return ERR_CAST(inode); } If configfs_create() fails (e.g. new_inode() returns NULL under memory pressure or fault injection), the lookup returns an error and the caller dputs the now-negative dentry, which goes through __dentry_kill() and is freed via call_rcu(). Because the dentry never gained an inode it does not go through the .d_iput op (configfs_d_iput), which is the only place that clears sd->s_dentry. sd therefore keeps a stale pointer to the freed dentry. A subsequent rmdir of the parent item walks the parent's s_children list in detach_attrs() and configfs_drop_dentry() does spin_lock(&sd->s_dentry->d_lock) on freed memory: BUG: KASAN: slab-use-after-free in _raw_spin_lock+0xac/0x110 Read of size 1 at addr ffff00012bacd028 by task repro/2440 _raw_spin_lock+0xac/0x110 configfs_drop_dentry+0x48/0x158 [configfs] detach_attrs.isra.0+0x18c/0x494 [configfs] configfs_rmdir+0x450/0x71c [configfs] vfs_rmdir+0x170/0x620 ... Freed by task 0: __d_free+0x28/0x34 rcu_do_batch+0x37c/0x1bd0 ... Last potentially related work creation: call_rcu+0x34/0x68 dentry_free+0xe8/0x3e0 __dentry_kill+0x404/0x604 dput+0x14/0x30 lookup_open.isra.0+0x6ac/0xc00 path_openat+0xd18/0x2588 Fix this by tearing down the sd<->dentry linkage in the configfs_create() error path, under configfs_dirent_lock, mirroring what configfs_d_iput() would have done for a positive dentry. Reported-by: Farhad Alemi Signed-off-by: Breno Leitao diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 362b6ff9b908..68d857dcb2d9 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -486,6 +486,22 @@ static struct dentry * configfs_lookup(struct inode *dir, inode = configfs_create(dentry, mode); if (IS_ERR(inode)) { + /* + * configfs_create() failed (e.g. -ENOMEM + * from new_inode()). The dentry will be + * dput()ed by the caller and freed via RCU; + * because it never gained an inode, + * configfs_d_iput() will not run to clear + * sd->s_dentry. Drop the linkage here so a + * later detach_attrs() walking the parent's + * s_children list does not dereference a + * freed dentry in configfs_drop_dentry(). + */ + spin_lock(&configfs_dirent_lock); + if (sd->s_dentry == dentry) + sd->s_dentry = NULL; + dentry->d_fsdata = NULL; + spin_unlock(&configfs_dirent_lock); configfs_put(sd); return ERR_CAST(inode); }