From nobody Sat Jun 27 16:09:47 2026 Received: from mail-pj1-f53.google.com (mail-pj1-f53.google.com [209.85.216.53]) (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 4190D31E820 for ; Mon, 8 Jun 2026 15:49:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780933771; cv=none; b=jas2KaWazLpuESiWKvh0zb/ox9dZfrKGOZwdPZ0ar4CRnncyy14MIKKdpwiSGNd3WaqK/GOacA0GskBW5UR/n6bcbF5vnZHb411LnkzTvGX9Rwd2XLdOuVpYOHeoKdqznFnmd1QGMYq8sLA8ahIXK9fsaaN8xP63ZUDUFLzwdD4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780933771; c=relaxed/simple; bh=UPloW7wCBJ8A+fJCKHYFghT/wlBntz1WJRmB53j9Ttc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U6kpYRFcZVKGbbM/+iNv48QMjnOixhaLL5xN7wXOb96BLuVnHejuGuGhud9+vAL+gOQrX3fIroYM5zoVaESBpFlHZUqAjcKjCW0L+BgQmuVyW2U9qg1z501+IXYlO+a43kYeykuBUFpLyVoqJQofaEqQYMELLrOl3/IzB9JDHM4= 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=MNEr/74n; arc=none smtp.client-ip=209.85.216.53 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="MNEr/74n" Received: by mail-pj1-f53.google.com with SMTP id 98e67ed59e1d1-36dccb2c91bso434550a91.0 for ; Mon, 08 Jun 2026 08:49:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780933770; x=1781538570; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=4AEyICkcxZy1T6IWxG4M+aIj2et6ppgQhv+Dv6SSs9s=; b=MNEr/74n5hjLlgB3wo40ywGOduUmRpxx55GuY9PyBdn7spBCtBNuTYQatwy0wc/QHn 3bbCUM385YcXAmVAh8beXjaCcy1DyjaMcSh01LLQsc38Cas16ChDrWOXggoycTELLVFc B0WK3JAQ1Ak5D5MNjKif28vnjY6M2KYEM6tQzx/2qkw0ZSxI5O9IPQiSJjs42IklY8u1 YtAKjZQpQbDl2e9CVX3ZFexhqwAQBAj+1qa2hSysgfGAVpgoZRptBu4VeR+epndDcMkj IQst2Z4/pgm/llcqEGZ4ooreQLaUFtQ/1aPP85IP+HMSa5d6jOH8XDeY0lOxhbUh+m+J ofOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780933770; x=1781538570; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=4AEyICkcxZy1T6IWxG4M+aIj2et6ppgQhv+Dv6SSs9s=; b=TtKMtAI+Tq2trrJjZZCHcrP11gb7hfYEUMTxe1BXxpmEbS+wTzD9bhA/2AL9ao79SV km42wFQWX3PWIygUuTfs1Ceer/leiKsANv1lnnVG27mh2Aae8zn4YRr/QsB7avLWSrsj hYmZrxov7Df4Ccxt9l6Agw6gbqf+7TZ0lWRlbeJjLotLY1IRDynqkG4TVbKcBX8uBj0N kpAxd9yZ7DxR9IFrjWW9rNnvxTtTmcIKRLaMzZDfSo5xqi7xcstMe7z+87V+fXw2XU/k i8GuHmBVGldsKPPPWahhhgsANmOUbNsVxHLwJdZBwoxLViZZcXncnXphtPd42nHpE6KA eEVQ== X-Forwarded-Encrypted: i=1; AFNElJ8tahpvq7TphCYMAsG8tWpynY3fhGh9yWI4zBoP03R9I+lUIBIBjc0z8113y0T9M3yxQg9r3ynFP7mKTC4=@vger.kernel.org X-Gm-Message-State: AOJu0Yxw1NknxoK7VbdhZTX4jLgaSOaVwGJpD6T21qaoDpoXZANcUQmR 9syJ0EGZjKs/dsrsOBt8PBlrChq+yOS5ziSOM+itm8bWJgTiGEgiQrIdNYeOKYEP X-Gm-Gg: Acq92OEky95PYzbc2BTUCP847BfrPPcVbsy5zihcRMTH5xhfXAmFIQNW2TqUOXyUHKj uMYv3IlQS+42Z+M5wKArwcrOtKzErYsH2wyR5DKgMsLBbEEVpoOjZy4qQ/y74v34+viH0r3l3On Fc9Zk3mRI5J1j1DxouZI3I6I/OcYayaL1KKiCbqtI1jB1VzBSivmzJPM9oHnPOJbumxIH4Zuqbw UL/oq6iF/3A64r4PBKWiGzhoDdPKDk+yh0RFs0M55M/U7HlojLmgsSas2iceXWxwzuqtE8AcrMl ATHA7g/twK9lfXh5Q2xUqezLp0Khwb9nQm1shrxwkXa9kHvp/nDUA8erkL8hIGWrVJVS8cAT9O7 p6suQAgNZCCTxNM/xH6+5Fo4LdUbPEdVrLLsPi8vyx1MkwvzNelJej0G+2n0kPy3atvb4Qn9vas 9SsiPsYfA+nNpGjXjq0Z+xsjgIAD4= X-Received: by 2002:a17:90b:5190:b0:36b:900a:d298 with SMTP id 98e67ed59e1d1-370ee340826mr7752785a91.1.1780933769563; Mon, 08 Jun 2026 08:49:29 -0700 (PDT) Received: from ser8.. ([221.156.231.192]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c85df0a624fsm15937526a12.18.2026.06.08.08.49.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jun 2026 08:49:29 -0700 (PDT) From: DaeMyung Kang To: Namjae Jeon Cc: Hyunchul Lee , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, DaeMyung Kang Subject: [PATCH v6 1/4] ntfs: reject non-resident records for resident-only attributes Date: Tue, 9 Jun 2026 00:49:14 +0900 Message-ID: <20260608154917.2703739-2-charsyam@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260608154917.2703739-1-charsyam@gmail.com> References: <20260608154917.2703739-1-charsyam@gmail.com> 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 shared lookup-time attribute validator rejects non-resident $FILE_NAME and $VOLUME_NAME records because their formats require resident values and callers handle returned records as resident attributes. Other resident-only attribute types still pass through the generic non-resident mapping-pairs checks. That leaves real resident/non-resident union confusion paths. Inode load looks up $STANDARD_INFORMATION and then reads data.resident.value_offset without checking a->non_resident. ntfs_inode_sync_standard_information() does the same when updating the standard information value. ntfs_write_volume_flags() also looks up $VOLUME_INFORMATION and reads data.resident.value_offset directly. $INDEX_ROOT callers in dir.c and index.c depend on the same lookup contract before consuming the resident index root value. Reject non-resident records for all resident-only attribute types in the shared validator. Keep the existing $FILE_NAME and $VOLUME_NAME behavior, but factor it through a helper and extend it to $STANDARD_INFORMATION, $OBJECT_ID, $VOLUME_INFORMATION, $INDEX_ROOT, and $EA_INFORMATION. For $OBJECT_ID and $EA_INFORMATION this is contract hardening for resident-only formats; this patch only rejects the non-resident form and does not add new resident value validation for those types. Signed-off-by: DaeMyung Kang Reviewed-by: Hyunchul Lee --- fs/ntfs/attrib.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 5e1ad1cd0118..1254fbe7666e 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -596,6 +596,22 @@ static u32 ntfs_resident_attr_min_value_length(const _= _le32 type) } } =20 +static bool ntfs_attr_type_is_resident_only(const __le32 type) +{ + switch (type) { + case AT_STANDARD_INFORMATION: + case AT_FILE_NAME: + case AT_OBJECT_ID: + case AT_VOLUME_NAME: + case AT_VOLUME_INFORMATION: + case AT_INDEX_ROOT: + case AT_EA_INFORMATION: + return true; + default: + return false; + } +} + static bool ntfs_file_name_attr_value_is_valid(const u8 *value, const u32 = value_length) { const struct file_name_attr *fn; @@ -666,7 +682,7 @@ static bool ntfs_attr_value_is_valid(struct ntfs_volume= *vol, u32 min_len; =20 if (a->non_resident) { - if (a->type =3D=3D AT_FILE_NAME || a->type =3D=3D AT_VOLUME_NAME) + if (ntfs_attr_type_is_resident_only(a->type)) goto corrupt; if (!ntfs_non_resident_attr_value_is_valid(a)) goto corrupt; --=20 2.43.0 From nobody Sat Jun 27 16:09:47 2026 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (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 C995D31E820 for ; Mon, 8 Jun 2026 15:49:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780933776; cv=none; b=ETu32IlOTx+zJQjuPQ7zGA0sUS6Y2Ui2Scpd5qZb5rIzjwCYmIiZF45jaK1/z8fjsmSdvCFSxIuUXc4aCfXIlQV6stx5IvtF1y6vyOkIgMvxy0I/x/WL8BxTW2GbcS2voCVp29EB/bderXbWTaeo2ZDEgPc+RqVRk2Xs1myqJgU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780933776; c=relaxed/simple; bh=8ibx/uagjRxDQTHvvSKBRxRKs2/CWaFGKepFUGfMVzQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hrAvAvGWBVzj3fp+DBcz31/nufVARg0NmRbN+dwGIWv4pJWCKQiYAcJb1ahgOflFjAAz0IaoWBEbCFelCotQdgv9Ic4Io/u59Et8TUhlSh8RG9Jk1EQkN8mDkzJG8KYzKCUFa5X3MPjFYFFu0u6zUwHuIKJe2NICcAjenixiOCA= 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=T0Eipmz9; arc=none smtp.client-ip=209.85.214.175 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="T0Eipmz9" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-2bf201b93c5so6876545ad.0 for ; Mon, 08 Jun 2026 08:49:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780933774; x=1781538574; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ijOWtnNcZJdG/aazJeUEEW6pNqwgUu8kPGOAev0o5dI=; b=T0Eipmz9CeI5b0IvSRxIsJHd68AqoDbV99SFcGaxe4hibpMN86uMgLeTm6G5RdsVCX 3D6Bykk1UFxmzTlhjRTEQqQ54i3NuHlc02sjF0gOVuMbQ+oNGkTENLfKFymBq8SLEbed kplSSJN3PlLvd7wUFsMK1pfAfDrbxr76DeLRX/j6Uko63ifpEfgtqwGVLCsXO7vebvCw A70L2hTlyYfM3DFjza+8frlr126bwNmS1JYtqTK1bD1X4lVmzgRYImpzPjVdNftjLUVD flIjWEz64OK4zA0Z5+jhtTQPly2eueCz0QtrHimGRH51XPIo5/hNixvvSUL3tWZmZlVS uYfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780933774; x=1781538574; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ijOWtnNcZJdG/aazJeUEEW6pNqwgUu8kPGOAev0o5dI=; b=YW8SPgFh0VR/EjGZEiYFZBr1L6w9WHZNWav6s+fwsEJ8ohHmkWeCb2ubJc1DoQW4qB cHGD5EWzs4vsouOfBkl2zXLOZTHxEkpSJqkzpSIvB9RnKFl01J+x4y6gBAFVIFNgIV/3 dbhWbt+iRiDZksdC3QrJU2P5blEIKvCQv0M14avv2SlrOyNvRQVzVrcrRIctqIeXXVy6 W9wkJ4iPjmhar8m6OAUZ6MzxJC7LPdUz2pJqjemVyaHlWBrz0/s6tQ2eBlJCgTQ4gN0H uMwSz0qLwcFBVrJMVntTDI34hHXVDziEQLltMFd6zDFOfUGIcRzEcIDtom+kDQUgzL4s 7QyQ== X-Forwarded-Encrypted: i=1; AFNElJ+LDxH1e82x28wMIm5jz6misk33G+vFJiwmTQZONjO0k7hcdhsEGBqiSQuyPq4qxtlRWA2BMAQuhyiTL1U=@vger.kernel.org X-Gm-Message-State: AOJu0YwQ4E89GLyqPqMMyVH/8a09GoKGKPHzVXLDci/9nYDuNg5WKD0s mUFHJG575rjoqfSfGS4KZs6vg2v8IPW6MQc+3+WpLuGcUJuqwKEMPJSW9MGuMo3O X-Gm-Gg: Acq92OF0fSoOcaR18MqQmJG/hyjy9aS2E4J5686OFWHV948VXte8Gks6bjh4NDF/TQL w8KT8dI3hu2dFnphh9c5uaVsr6wNYZOOGsb+oS9Tgn71jaHlOEtF9M6XHbqMxY3nvel95TSHAPM tbwB9r6ejlrbvRBtlKgQYpxP0luPLq1Ydq8RgkDafe5poUO47cFS9wsHYG75l1VdFYLODKIKBYH 8uohM6LPFOcjkkgmS/2uw8LIdcz3w70Q6jvVMIyrFTdYHSOGfWZzpEPsCFdjzjI3jXXL4KCw8LC uGSdu/ttm7HDBTntGdzD9ok/DaHBeqNSgQTG7O1lG48Q91PwK5ssepldTpCoZDPYLjgosAfE9QZ BN5EQWWAPl2feWyNpRYJ7rKJRxgCEePWppKXyF41LSxMLg1N0hDdgjx+dJfPwoZduyA8OipYKDg AdPQdUlNo8D2kkcljARlV2z5hLq6Y= X-Received: by 2002:a17:903:1a70:b0:2bf:2256:7335 with SMTP id d9443c01a7336-2c1e823b788mr85175325ad.3.1780933774116; Mon, 08 Jun 2026 08:49:34 -0700 (PDT) Received: from ser8.. ([221.156.231.192]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c85df0a624fsm15937526a12.18.2026.06.08.08.49.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jun 2026 08:49:33 -0700 (PDT) From: DaeMyung Kang To: Namjae Jeon Cc: Hyunchul Lee , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, DaeMyung Kang Subject: [PATCH v6 2/4] ntfs: grow index root value before reparent header update Date: Tue, 9 Jun 2026 00:49:15 +0900 Message-ID: <20260608154917.2703739-3-charsyam@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260608154917.2703739-1-charsyam@gmail.com> References: <20260608154917.2703739-1-charsyam@gmail.com> 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" ntfs_ir_reparent() moves the resident index root entries into an index block and leaves a small root stub containing the child VCN. That root stub can be larger than the existing resident value. For example, an empty root with value_length 48 has an index area of 32 bytes, while the large-index root stub needs index_length and allocated_size of 40 bytes. The current code publishes the larger index.index_length and index.allocated_size before resizing the resident value. If the resize returns -ENOSPC, the recovery path can call ntfs_inode_add_attrlist(), which looks attributes up again while the root header says allocated_size 40 but the resident value still only provides 32 bytes of index area. Lookup-time $INDEX_ROOT validation then correctly rejects that transient layout as corrupt. This reproduces as a generic/013 failure under qemu. In the failing run, the transient root had value_len=3D48, index_size=3D32, index_length=3D40, = and allocated_size=3D40, and ntfsprogs-plus ntfsck reported "Corrupt index root in MFT record 1177". When the root stub grows, resize the resident value before publishing the larger root header. If the resize fails, the old root remains valid for recovery lookups. Keep the existing header-before-resize ordering for shrink or same-size cases so the resident value never temporarily exposes an allocated_size beyond its bounds. Signed-off-by: DaeMyung Kang Reviewed-by: Hyunchul Lee --- fs/ntfs/index.c | 78 ++++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/fs/ntfs/index.c b/fs/ntfs/index.c index 8371ff4303e7..052d80fddbbc 100644 --- a/fs/ntfs/index.c +++ b/fs/ntfs/index.c @@ -1240,6 +1240,8 @@ static int ntfs_ir_reparent(struct ntfs_index_context= *icx) struct index_entry *ie; struct index_block *ib =3D NULL; s64 new_ib_vcn; + u32 index_length; + u32 old_value_length; int ix_root_size; int ret =3D 0; =20 @@ -1287,6 +1289,21 @@ static int ntfs_ir_reparent(struct ntfs_index_contex= t *icx) goto clear_bmp; } =20 + old_value_length =3D le32_to_cpu(ctx->attr->data.resident.value_length); + index_length =3D le32_to_cpu(ir->index.entries_offset) + + sizeof(struct index_entry_header) + sizeof(s64); + ix_root_size =3D offsetof(struct index_root, index) + index_length; + /* Grow the resident value before publishing the larger root header. */ + if (ix_root_size > old_value_length) { + ret =3D ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr, ix_root_si= ze); + if (ret) + goto resize_failed; + + icx->idx_ni->data_size =3D ix_root_size; + icx->idx_ni->initialized_size =3D ix_root_size; + icx->idx_ni->allocated_size =3D (ix_root_size + 7) & ~7; + } + ntfs_ir_nill(ir); =20 ie =3D ntfs_ie_get_first(&ir->index); @@ -1295,48 +1312,49 @@ static int ntfs_ir_reparent(struct ntfs_index_conte= xt *icx) =20 ir->index.flags =3D LARGE_INDEX; NInoSetIndexAllocPresent(icx->idx_ni); - ir->index.index_length =3D cpu_to_le32(le32_to_cpu(ir->index.entries_offs= et) + - le16_to_cpu(ie->length)); + ir->index.index_length =3D cpu_to_le32(index_length); ir->index.allocated_size =3D ir->index.index_length; =20 - ix_root_size =3D sizeof(struct index_root) - sizeof(struct index_header) + - le32_to_cpu(ir->index.allocated_size); - ret =3D ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr, ix_root_si= ze); - if (ret) { - /* - * When there is no space to build a non-resident - * index, we may have to move the root to an extent - */ - if ((ret =3D=3D -ENOSPC) && (ctx->al_entry || !ntfs_inode_add_attrlist(i= cx->idx_ni))) { + if (ix_root_size <=3D old_value_length) { + ret =3D ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr, ix_root_si= ze); + if (ret) + goto resize_failed; + + icx->idx_ni->data_size =3D ix_root_size; + icx->idx_ni->initialized_size =3D ix_root_size; + icx->idx_ni->allocated_size =3D (ix_root_size + 7) & ~7; + } + ntfs_ie_set_vcn(ie, new_ib_vcn); + goto err_out; + +resize_failed: + /* + * When there is no space to build a non-resident + * index, we may have to move the root to an extent + */ + if ((ret =3D=3D -ENOSPC) && (ctx->al_entry || !ntfs_inode_add_attrlist(ic= x->idx_ni))) { + ntfs_attr_put_search_ctx(ctx); + ctx =3D NULL; + ir =3D ntfs_ir_lookup(icx->idx_ni, icx->name, icx->name_len, &ctx); + if (ir && !ntfs_attr_record_move_away(ctx, ix_root_size - + le32_to_cpu(ctx->attr->data.resident.value_length))) { + if (ntfs_attrlist_update(ctx->base_ntfs_ino ? + ctx->base_ntfs_ino : ctx->ntfs_ino)) + goto clear_bmp; ntfs_attr_put_search_ctx(ctx); ctx =3D NULL; - ir =3D ntfs_ir_lookup(icx->idx_ni, icx->name, icx->name_len, &ctx); - if (ir && !ntfs_attr_record_move_away(ctx, ix_root_size - - le32_to_cpu(ctx->attr->data.resident.value_length))) { - if (ntfs_attrlist_update(ctx->base_ntfs_ino ? - ctx->base_ntfs_ino : ctx->ntfs_ino)) - goto clear_bmp; - ntfs_attr_put_search_ctx(ctx); - ctx =3D NULL; - goto retry; - } + goto retry; } - goto clear_bmp; - } else { - icx->idx_ni->data_size =3D icx->idx_ni->initialized_size =3D ix_root_siz= e; - icx->idx_ni->allocated_size =3D (ix_root_size + 7) & ~7; } - ntfs_ie_set_vcn(ie, new_ib_vcn); - +clear_bmp: + ntfs_ibm_clear(icx, new_ib_vcn); + goto err_out; err_out: kvfree(ib); if (ctx) ntfs_attr_put_search_ctx(ctx); out: return ret; -clear_bmp: - ntfs_ibm_clear(icx, new_ib_vcn); - goto err_out; } =20 /* --=20 2.43.0 From nobody Sat Jun 27 16:09:47 2026 Received: from mail-pg1-f176.google.com (mail-pg1-f176.google.com [209.85.215.176]) (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 9A48D33B6DF for ; Mon, 8 Jun 2026 15:49:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780933778; cv=none; b=G9z8hB8aTcw8G66SXlYKBe9yq8F3Zq7vrVzUL3o2lKnn/dFkl6R7IljRnI3q+4fbewSmXRnEPBZhCJRoLJPQ+S86ypVYSWx6S0XIWFAaREFQnZWSdiPwt5e6HVb8U1LbtL46Tl+hGe/xlUzqjtPK6TVgZtlAQGQlnmRa4Y4oToI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780933778; c=relaxed/simple; bh=y8Ah02eZGE5R94LKgKZ0j7p5NoLSTMUMNDU/5kpVwyY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Wtx/1qvyt43aTSb9RuAdvj5TtrdRNZKmm8oBmYOC4wHpT49vmRPrYSNGvQhA2MhI/ydHMTgv0cnMYGxv7FQ0JAHxGmfn9R1MGRmXK8BGCEJrVO2I0RUj1Tw5vOTlq+dC4RiueUgk/b/OWLnFbEQKdsdo8+kCabT9wM+6NBotRAI= 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=ojiuQhcc; arc=none smtp.client-ip=209.85.215.176 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="ojiuQhcc" Received: by mail-pg1-f176.google.com with SMTP id 41be03b00d2f7-c85c9af3b09so137665a12.1 for ; Mon, 08 Jun 2026 08:49:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780933777; x=1781538577; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GMxc0vnL60+nkUbc3gwGXspn/XIsFvlD4dNklu47BYU=; b=ojiuQhccp4Nj1JLDBp2Hk11B8DizrRaogcqqLvH5tTbiqcykTNZniSf0RELD5iSxQF mlCnE1iSv69cmxs1zrcrT8yFvmyXNyFpWS4KthaHQF9RnixPuBcufVaMcKtkwIi7nAmT d5T1snMLQ1EMlBWQ5GnCRjUYwwOvDtDZPXyl/+d8qi08wv50w2FFg9qNFBgE0gh03A4I 22gsZs4o9sCc/Q8s4l8tFNm+mT/McqaHH34Lr8sCFJN6+mGLm7oeJPXPktccJFsSHRvQ EfI1wNP+c0RQF1Ojj9kXsrq5VgLDEdc8EqPprWPaR92VlKiS26sRIV3RV8qhF+z0lw+r hENA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780933777; x=1781538577; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=GMxc0vnL60+nkUbc3gwGXspn/XIsFvlD4dNklu47BYU=; b=Zvbo4OmfQpiT4rTBfPK9LaeznX1DiXxi+WGQ/hICJHXE//Ke+/ZWQxJd8iehCBK/8D Ye6WWjl8W1JSqqbV2KH/TMbgInzw8gZaXHSe5RB7Cyn2ljGQrz2OOdayKBpt0eylA+eh uNz5Ua6OKc7RYgdvOKjkc9kTZcpX+hS5vHanxcDoXJdOD73gtS0GVzpxpN/KKflqYeeQ sSG346voOegcsQYgggmaJMCDS1eQ76SIBLq5k8+8MOkOB9ddl8AljcTJGl2ZdgodPQTb GPGMIeQkonG24Etutcifw5hrZaKExzbvvPeFPhlBiM1MAKLFteW3HOwIJ8KirWORrby+ z56A== X-Forwarded-Encrypted: i=1; AFNElJ9gX2yosPEuhxyDYLpgRIqIpQ7AbNPKdWK8ZwRrbfVNcq2Ot4CgvrfgjY5R5rwjpE+96iuvl7D/KYGPMZQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwiVed3+NDZm0knLnOWGoCFdeLKZFARSKgoZRMhoVu+OTNBvVnT odG24h4rJJlMTSNfD40c4uqdbiF5wDzJvCs37WJO/WhPAnJ2G56wqcKhLKrRHcwt X-Gm-Gg: Acq92OF+BTWsImsWZLAviiFNYE3xFg0QkHY4IwE+KnjTesOVwAnFLBHIxQHqllpVkaJ fvhTADEReD+/oowRzr9KemcCH2r2mYoLjEMhWysGavkEFt1LgfgENiLLxL8nyTa3lPnNd9xIHKX uu6Ksablb5H7qAAi/BQhg4i0rpkkTCXavhndFvIMLkj+tDI7o9V2lzjwjSd+5QbDUALqLo/gmSh avw3Cs6JJCvRB/HIHmOX4Wq1AvkjymuY5whoMck6IY/HnwblgzejL5zvuNQDSX1J+PdMldnVPd6 rTDRMEY87K7FCWWF19KwNj6cTf13BFhRL1kSwGDlo9URtwn0yl19B3Y0t3CrY1XtogFrbAgxwzz /aG2wZVHXUwOWmkcht7gAgEgbcviil03hH8c9tV23Pqv+5DORajWDWUuD9aXLunvh5sjrEBSZYZ 875dAkl/TCR0dASj8sZA0dPDiCzHeacBYcYZA1rg== X-Received: by 2002:a05:6a21:48a:b0:3a3:18d4:2590 with SMTP id adf61e73a8af0-3b4ccf8e757mr9053112637.3.1780933776942; Mon, 08 Jun 2026 08:49:36 -0700 (PDT) Received: from ser8.. ([221.156.231.192]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c85df0a624fsm15937526a12.18.2026.06.08.08.49.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jun 2026 08:49:36 -0700 (PDT) From: DaeMyung Kang To: Namjae Jeon Cc: Hyunchul Lee , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, DaeMyung Kang Subject: [PATCH v6 3/4] ntfs: update index root allocated size before shrink Date: Tue, 9 Jun 2026 00:49:16 +0900 Message-ID: <20260608154917.2703739-4-charsyam@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260608154917.2703739-1-charsyam@gmail.com> References: <20260608154917.2703739-1-charsyam@gmail.com> 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" ntfs_ir_truncate() currently shrinks the resident $INDEX_ROOT value first and only updates index.allocated_size after re-looking up the attribute. During that relookup, the resident value_length can already be smaller while index.allocated_size still contains the old larger size. That leaves a transiently inconsistent $INDEX_ROOT layout and prevents lookup-time $INDEX_ROOT validation from being enabled: validation can correctly reject allocated_size extending past the newly shrunk resident value. When shrinking, lower index.allocated_size before shrinking value_length. If the truncate fails, restore the old allocated_size. Keep the existing grow ordering because the old allocated_size remains within the enlarged resident value until it is updated after the relookup. The shrink path is safe because the new value_length still covers struct index_root, so the index.allocated_size field remains present while it is updated first. Signed-off-by: DaeMyung Kang Reviewed-by: Hyunchul Lee --- fs/ntfs/index.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/fs/ntfs/index.c b/fs/ntfs/index.c index 052d80fddbbc..c5f2cf75b750 100644 --- a/fs/ntfs/index.c +++ b/fs/ntfs/index.c @@ -1365,9 +1365,16 @@ static int ntfs_ir_reparent(struct ntfs_index_contex= t *icx) static int ntfs_ir_truncate(struct ntfs_index_context *icx, int data_size) { int ret; + u32 old_allocated_size; + bool shrink; =20 ntfs_debug("Entering\n"); =20 + old_allocated_size =3D le32_to_cpu(icx->ir->index.allocated_size); + shrink =3D data_size < old_allocated_size; + if (shrink) + icx->ir->index.allocated_size =3D cpu_to_le32(data_size); + /* * INDEX_ROOT must be resident and its entries can be moved to * struct index_block, so ENOSPC isn't a real error. @@ -1379,9 +1386,14 @@ static int ntfs_ir_truncate(struct ntfs_index_contex= t *icx, int data_size) if (!icx->ir) return -ENOENT; =20 - icx->ir->index.allocated_size =3D cpu_to_le32(data_size); - } else if (ret !=3D -ENOSPC) - ntfs_error(icx->idx_ni->vol->sb, "Failed to truncate INDEX_ROOT"); + if (!shrink) + icx->ir->index.allocated_size =3D cpu_to_le32(data_size); + } else { + if (shrink) + icx->ir->index.allocated_size =3D cpu_to_le32(old_allocated_size); + if (ret !=3D -ENOSPC) + ntfs_error(icx->idx_ni->vol->sb, "Failed to truncate INDEX_ROOT"); + } =20 return ret; } --=20 2.43.0 From nobody Sat Jun 27 16:09:47 2026 Received: from mail-pf1-f175.google.com (mail-pf1-f175.google.com [209.85.210.175]) (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 1BA773403FC for ; Mon, 8 Jun 2026 15:49:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780933781; cv=none; b=bjD46n1fjZnQvKkOV392V7l62OJBDq2NFm1bMg2dhHFi+HZz7HttlxFO4JQsMQcCL5Z30GUEb1jUp+m43Y50cZYNTmS9Q9EXmKs4oD6rGVeXY7G0Uqug57M1rXdY+0hZN5c44ot9UvklVvmvskU9svXqOIt/fBaQ2Ri7Grd4178= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780933781; c=relaxed/simple; bh=J8uga1NMLeLuTW0Ga/UbrI8RuV+5khdm3fHTSqOApmU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PHHwrXKlUrqaOhJapSCbF6aQ92vMXYo+i9h9NnriQuypI+cwT8GtRopAwWr5HZX9oq5ml6aC9UEPhGRFrnLWhjTjb4NYT/0Wbv6IzayY8vuP3ED4I7oNBfw+VWsJGsXXhbomEVwUGds7vWC4QnYzaJfpmo8Hr4YUKGAVvdUVG0w= 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=DWp1+JG9; arc=none smtp.client-ip=209.85.210.175 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="DWp1+JG9" Received: by mail-pf1-f175.google.com with SMTP id d2e1a72fcca58-8426e2eff71so429292b3a.1 for ; Mon, 08 Jun 2026 08:49:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780933779; x=1781538579; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=62HcDbguGiGWBfESIpGMa4jmu+LyX4+s9ZYxbBD4ZI8=; b=DWp1+JG9DadAw23EvspEMGVjw8B2RHJKKPIPpkq5BKV/mwIT+yX07Yd5K+Hk3OHqHb epFkBL02uxj6p4gcyQyesuNX+KxIYeJJ2n2PhpzBttmwpQwvl78HGVx9ARvKKqj1DM30 E6mG2Via4KvixBGkbf5C+9BBg2Nza8MuXxdZQrq+/VURXP3foDUoMBuJlSJyZK8JqO1e soVN+vSW2vI783cTZVdnKg6v/1lTJeBVP2K/5aLeHgCZpfqceGqHHm09hEIvQMAx64Mj BbqFZl72LgHxQMgS0jotkcbA0sRvQUxw7LGK7n6Gei+VOWvKX4EwqTI37BDInDa4ghSd 7Egg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780933779; x=1781538579; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=62HcDbguGiGWBfESIpGMa4jmu+LyX4+s9ZYxbBD4ZI8=; b=CuvYdCQWAACLntAqSDjigQjwo5L5NsJGt6RqAdgsBcIi9raO9ulU6AVPSaUgBd4Kix 5eE+FYQSTr4+KnKCZYcwLXR3ywzRx6qRJvBBxJoxVS4hgyH4RJd//d4CFm1Hm9YssRF2 VDlmCkULNnuQRpVahBE5yKC1W32/0KRgDgQwXZ0LSCgJUnngCspyLt3wAkBpn/yGwhvb lGMSVgHWVIwoHsOqvdJ7a5xLOQzUnnBFi2xwz9MuTHvOPICjIHSx5nktEqsqn3gDOlM6 AZb/wF/Xxo8ZXKsTU7K24YI6MRs5sEI8P9m1zekjUyXGVCKfZ6XvxObH1RtRf8a934KR 9qHQ== X-Forwarded-Encrypted: i=1; AFNElJ+mipkd2ctmWcQs1AY7OfcIG/4G5KUXgcKfjXluMfXpHc313f9zZmbWSOiyYDuvcN0NfBJZZVb5PsVsK7s=@vger.kernel.org X-Gm-Message-State: AOJu0YzcawXGegTix2/GeUiL0NvB81QiBl7Z2BAw4C9ETUroTbgahiEQ H2NPGYWam+iGVJVaaCPI2I0NINzxQn0XGk2pCxPB3ClEKM3Rf3xGFDgQ9vYJPniZ X-Gm-Gg: Acq92OF+fXE08cL5nash9Jn5LeIVx1J4RPqPJgvjvFIFUXdEGFxQCsRLh6PvgrGGWvd zsPO1czdHwdnEFg9lXQ8Xo8o3Pv4ENi8sgXdWADrL6dKD5vaHhLg+4ZoYzKPbXBGn81Xv7Ac4GE qaCLRQxf2A2U9nwYwL/NxRutDEtJNDTC5nlwbY1NcrIcN0jH79mpzC+GpsREHgi/lDXDG6UJeKa 6qsPn7L2XFXSnHRIg1InH5qpC/8NH/YBtFXiBjpSxNV2stSHEXPMgi1rRp/1ISczYGq9IRurXkk CcokN4BuyWxkekteSWA8r891u92rSbqTjrrxKKhx2qzA4ZwxoI/SRcV+PBUH4qy+wI1pSMbqxRB jLlxj/zSIDXQOG+9E8IstPvUcldfXGpR94NWhZOGgDYQZSj9koynv4PHEMi7JHj111DwGLUHgKC rJxMVinxro2EEeEL4yYtoFhgN97ME= X-Received: by 2002:a05:6300:67ca:b0:39e:df5e:edc2 with SMTP id adf61e73a8af0-3b4cd17fadamr9344971637.2.1780933779336; Mon, 08 Jun 2026 08:49:39 -0700 (PDT) Received: from ser8.. ([221.156.231.192]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c85df0a624fsm15937526a12.18.2026.06.08.08.49.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jun 2026 08:49:39 -0700 (PDT) From: DaeMyung Kang To: Namjae Jeon Cc: Hyunchul Lee , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, DaeMyung Kang Subject: [PATCH v6 4/4] ntfs: validate resident index root values on lookup Date: Tue, 9 Jun 2026 00:49:17 +0900 Message-ID: <20260608154917.2703739-5-charsyam@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260608154917.2703739-1-charsyam@gmail.com> References: <20260608154917.2703739-1-charsyam@gmail.com> 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" Resident $INDEX_ROOT values carry index header fields that callers consume after lookup. Some callers already validate parts of the layout before walking entries, but those checks are scattered and do not cover all root header invariants, such as entries_offset alignment and lower bound, index_length, and allocated_size consistency. The resident root resize paths now keep these header fields consistent while the value size changes: ntfs_ir_truncate() lowers index.allocated_size before shrinking the resident value, and ntfs_ir_reparent() grows the resident value before publishing a larger root header. Lookup-time validation can therefore cover these invariants without tripping over the driver's own resize paths. Add $INDEX_ROOT to the minimum resident value size table and validate the resident index header fields before returning the attribute from lookup. Require 8-byte aligned index header fields, a sane entries_offset, an index_length within allocated_size, allocated_size within the resident value, and enough entry space for at least an index entry header. The shared validator already rejects non-resident records for resident-only attribute types, including $INDEX_ROOT. Signed-off-by: DaeMyung Kang Reviewed-by: Hyunchul Lee --- fs/ntfs/attrib.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 1254fbe7666e..8f10688a17df 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -589,6 +589,8 @@ static u32 ntfs_resident_attr_min_value_length(const __= le32 type) sizeof(__le16) * 1; case AT_VOLUME_INFORMATION: return sizeof(struct volume_information); + case AT_INDEX_ROOT: + return sizeof(struct index_root); case AT_EA_INFORMATION: return sizeof(struct ea_information); default: @@ -632,6 +634,31 @@ static bool ntfs_volume_name_attr_value_is_valid(const= u32 value_length) return value_length <=3D NTFS_MAX_LABEL_LEN * sizeof(__le16); } =20 +static bool ntfs_index_root_attr_value_is_valid(const u8 *value, const u32= value_length) +{ + const struct index_root *ir; + u32 index_size; + u32 entries_offset; + u32 index_length; + u32 allocated_size; + + ir =3D (const struct index_root *)value; + index_size =3D value_length - offsetof(struct index_root, index); + entries_offset =3D le32_to_cpu(ir->index.entries_offset); + index_length =3D le32_to_cpu(ir->index.index_length); + allocated_size =3D le32_to_cpu(ir->index.allocated_size); + + if ((entries_offset | index_length | allocated_size) & 7 || + entries_offset < sizeof(struct index_header) || + entries_offset > index_length || + index_length > allocated_size || + allocated_size > index_size || + index_length - entries_offset < sizeof(struct index_entry_header)) + return false; + + return true; +} + struct ntfs_resident_attr_value { const u8 *data; u32 len; @@ -705,6 +732,10 @@ static bool ntfs_attr_value_is_valid(struct ntfs_volum= e *vol, if (!ntfs_volume_name_attr_value_is_valid(value.len)) goto corrupt; break; + case AT_INDEX_ROOT: + if (!ntfs_index_root_attr_value_is_valid(value.data, value.len)) + goto corrupt; + break; } return true; =20 --=20 2.43.0