From nobody Fri Jul 24 22:17:38 2026 Received: from mail-ot1-f46.google.com (mail-ot1-f46.google.com [209.85.210.46]) (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 23889524F for ; Thu, 23 Jul 2026 01:02:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784768579; cv=none; b=b4xVg1m+DVElAkS2Kzv2SNOWsebqPdiOBB2JA7BeNg9j8nUUkwydCSXlW5CV1mppXiM4cOQg/wZRYo1XjzQJ2m6CeOVSHRaxVC0uwVD2qJrkZg3R6t+MurMAUCKIQO+OVdWuReAFbVEmTaOvaIGHawkTmnHBNtc//VVh2kT5llQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784768579; c=relaxed/simple; bh=B7p/Yr6KIUXHY9xeKP6wCZcbcmTeppPjtg4Fzq/9ZtM=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=C1rhQnx5BshBlCN4surMLNiqIQJ7dmfjCb4D7efrO0jLjoqXoSAYU0XNFk4a2DjJgm3OB90NoJNV7lgzLzcnl8R0gSLkl28Z+dZim+ZbqEJNy8Pgt8ukEm8AIurn6sDXbvrgpb64AbTtTm57e/F8FcIc/jTcyecsIUEikIPz3y8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=KxPSsAr0; arc=none smtp.client-ip=209.85.210.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KxPSsAr0" Received: by mail-ot1-f46.google.com with SMTP id 46e09a7af769-7eb61bbeb25so50713a34.1 for ; Wed, 22 Jul 2026 18:02:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784768577; x=1785373377; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=dL5sSve182iKi7PGGdT5iIYPlCpUxk3FPMQ0kRAvoaQ=; b=KxPSsAr0TM3pnpflTeqCrQC0CdUieGyaRqnUpG9psc7ZmlFpJlEFQHD7J7AvV8J7P4 wkCMjygyz4Mb17t2AXJMJLAiEiHR4u6vsKvGtCXwkG+qAY8VVQRv5RBM5yo91L12aDvi EJlw6HR6jPcEg63DKLTdMjFJOuGjt6j1VuCwHqAQ9yylh3YknUGq2I7b+oyXptKQj9Dj Dmf+KbJ5isAVhjGcUwBlToO9wHIWQvIjUOLcGr65unEeJVOraSMolxqwykXYxJpLm6Zd UjigYmaariSlci2pYa+krglVl9u56+issno+R8rvMN4+ca8OUmDKIcFDDAg8B2o5Bkfd TyFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784768577; x=1785373377; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=dL5sSve182iKi7PGGdT5iIYPlCpUxk3FPMQ0kRAvoaQ=; b=cTIbHNa4N6EB8nXD9PJH/sYPlQw9By49li2WRkwVZ2x7CkGskU1xfxHu3ks0b42Aot lkQ5rtYo2XzcbGaz1XmPrSRrB9doldczDKc/BBY5m7ejbyJlfQdONJtCM7HHtojYnTt6 94/JxYdK9ebf1JZ0K4mhzNVU8zzlDdfSsp2RyPcXYNOg+PI8EZ92qx36OgWcG4NnnPj0 vwERrnyTrzCSIl/LSIGgVTfXWWrRh7BbE5E6o4WRjITwR6zY6xUlvao3tZQyTQ+VRITM h5j5exUBu0uImLZoHADoz6Ppy3pjL367bJEHgqrMOgyZ92i2Ro/wwKS1sWsGBhD0IAPp 5MJg== X-Forwarded-Encrypted: i=1; AHgh+Rpho+zaWNZpq8+lufnhscM0d4UAlaQ10YzkPq4Bb6SAGLy8niVifkdZKDxwt5R2EYlse5oE3y16rQ6Ssdc=@vger.kernel.org X-Gm-Message-State: AOJu0YzNpFzySr8g+dMTlcLvtiLQKogfDEbMNjVP6We7RFoiya1niXRZ QIRqRD/1XBedIoStd9/L+WYfCb+tYUqQSDkzfhtp0p8JaYruMvvraZLeFqLEPl55 X-Gm-Gg: AR+sD106vLf8XL74/UZ3WhijB10z4bN07xMpTjDkZfe6HIqBmwstTiA3CukbAYeNfzt ic2YrbUrV8sGYOKFxxA9m90zUbWtCdql82EoWg5pq8nWmvLkHJC/RGRW/4SxCIPI9l0EbwjRcqi KGvgMqg3K/E3RL8MzHp4y1HGCOvkFLBNEaHXZ19dpVkgRYHmnInFAp/HKO3Fov+i9ub5Ec3kvQM cIwfosaULCm/P6kDaboIxoqggxajGeaqp67TAh8I00XsgUUKJH9Z9PQLABaKnTki9BecN+kVLHt 1chrKZb9IvwczoWVaVINefSquRYpaircfk0zxOyhTvHC+6yQw4RKPNNDLvE49qLkBtGRE8qsKw5 guDs/wM4sfpM0p0QWtyPeGOIMWo5iwAAN+VT1dhdM4g6fQiBJY/raAntRngRbggmpcWyOncCd X-Received: by 2002:a4a:e84b:0:b0:6a3:94bc:bdcf with SMTP id 006d021491bc7-6aad41758d3mr381511eaf.57.1784768576918; Wed, 22 Jul 2026 18:02:56 -0700 (PDT) Received: from fedora ([187.142.231.66]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-45766f16dfcsm3312320fac.7.2026.07.22.18.02.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Jul 2026 18:02:55 -0700 (PDT) From: Cihan Karadag To: OGAWA Hirofumi , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Cc: Cihan Karadag , Shuah Khan Subject: [PATCH] fat: preserve reserved lcase bits across rename Date: Wed, 22 Jul 2026 19:02:25 -0600 Message-ID: <20260723010227.88190-1-cihan.cihan@gmail.com> X-Mailer: git-send-email 2.54.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The lcase field of struct msdos_dir_entry (include/uapi/linux/msdos_fs.h) has only two bits the kernel interprets, CASE_LOWER_BASE and CASE_LOWER_EXT; the rest are reserved and other implementations may use them to carry their own metadata (e.g. the Windows EFS "encrypted file" bit pattern). vfat_rename() currently loses those reserved bits in both of its paths: when the destination name doesn't already exist, a brand new directory entry is built from scratch with a freshly computed lcase byte, zeroing anything outside the two known bits; when the rename overwrites an existing destination, the destination's own (unrelated) reserved bits are left in place instead of the source file's. Add vfat_overwrite_lcase_reserved_bits() and call it once new_i_pos is established inside vfat_rename(), overwriting the surviving entry's reserved lcase bits with the original file's, so the metadata is carried over across the rename instead of being lost. Tested by booting the patched kernel under QEMU and replaying the bug report's own before/after FAT32 images: the renamed entry's lcase byte now matches the source's reserved bits instead of being zeroed. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=3D215093 Signed-off-by: Cihan Karadag --- fs/fat/namei_vfat.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index e909447873e36..d4677c1eaabc3 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -931,6 +931,38 @@ static void vfat_update_dir_metadata(struct inode *dir= , struct timespec64 *ts) mark_inode_dirty(dir); } =20 +/* + * Overwrite the reserved lcase bits (those not used by the + * kernel) of the entry at i_pos with those from the source + * lcase byte. + */ +static int vfat_overwrite_lcase_reserved_bits(struct inode *dir, loff_t i_= pos, + unsigned char src_lcase) +{ + /* lcase bits the kernel actually assigns meaning to */ + const unsigned char lcase_unreserved_bits =3D CASE_LOWER_BASE | CASE_LOWE= R_EXT; + struct super_block *sb =3D dir->i_sb; + struct buffer_head *bh; + struct msdos_dir_entry *de; + sector_t blocknr; + int offset, err =3D 0; + + fat_get_blknr_offset(MSDOS_SB(sb), i_pos, &blocknr, &offset); + bh =3D sb_bread(sb, blocknr); + if (!bh) + return -EIO; + + de =3D &((struct msdos_dir_entry *)bh->b_data)[offset]; + de->lcase =3D (de->lcase & lcase_unreserved_bits) | + (src_lcase & ~lcase_unreserved_bits); + + mmb_mark_buffer_dirty(bh, &MSDOS_I(dir)->i_metadata_bhs); + if (IS_DIRSYNC(dir)) + err =3D sync_dirty_buffer(bh); + brelse(bh); + return err; +} + static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { @@ -974,6 +1006,17 @@ static int vfat_rename(struct inode *old_dir, struct = dentry *old_dentry, goto out; new_i_pos =3D sinfo.i_pos; } + + /* + * The kernel only interprets some of the lcase bits; make + * sure the rest carry over from old_dentry's lcase instead + * of being silently clobbered. + */ + err =3D vfat_overwrite_lcase_reserved_bits(new_dir, new_i_pos, + old_sinfo.de->lcase); + if (err) + goto error_inode; + inode_inc_iversion(new_dir); =20 fat_detach(old_inode); --=20 2.54.0