From nobody Thu Nov 04 05:09:44 2021 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id AD19818278BA; Thu, 4 Nov 2021 05:09:44 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4HlBX84WX6z4VYg; Thu, 4 Nov 2021 05:09:44 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 7AC7726482; Thu, 4 Nov 2021 05:09:44 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 1A459i9x026577; Thu, 4 Nov 2021 05:09:44 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 1A459ilB026576; Thu, 4 Nov 2021 05:09:44 GMT (envelope-from git) Date: Thu, 4 Nov 2021 05:09:44 GMT Message-Id: <202111040509.1A459ilB026576@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Xin LI Subject: git: 890cae197737 - main - fsck_msdosfs: truncate directory entry when the head pointer is invalid. List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: delphij X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 890cae197737b463e56d1cc5a3f61f84cb49c807 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by delphij: URL: https://cgit.FreeBSD.org/src/commit/?id=890cae197737b463e56d1cc5a3f61f84cb49c807 commit 890cae197737b463e56d1cc5a3f61f84cb49c807 Author: Xin LI AuthorDate: 2021-11-04 05:09:32 +0000 Commit: Xin LI CommitDate: 2021-11-04 05:09:32 +0000 fsck_msdosfs: truncate directory entry when the head pointer is invalid. As far as we know, there is no FAT implementation that supported hard links, and our msdosfs driver assumed one cluster chain is only referenced by one directory entry and clears it out when the file is deleted. On the other hand, the current code would proceed with checkchain() when the directory entry's head cluster is a valid numbered cluster without checking if it was a valid head node of a cluster chain. So if the cluster do not being a chain (e.g. CLUST_FREE, CLUST_BAD), or was already referenced by another directory entry, this would trigger an assertion in check_chain() at a later time. Fix this by giving the user an option to truncate the directory entry when the head cluster is an invalid cluster, an visited head node, or not a head node. Reported by: NetApp (kevans@) Reviewed by: kevans, emaste (no objection) MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D32699 --- sbin/fsck_msdosfs/dir.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sbin/fsck_msdosfs/dir.c b/sbin/fsck_msdosfs/dir.c index 471f6cc0335e..dbe4e0c7db2f 100644 --- a/sbin/fsck_msdosfs/dir.c +++ b/sbin/fsck_msdosfs/dir.c @@ -400,8 +400,21 @@ checksize(struct fat_descriptor *fat, u_char *p, struct dosDirEntry *dir) if (dir->head == CLUST_FREE) { physicalSize = 0; } else { - if (!fat_is_valid_cl(fat, dir->head)) - return FSERROR; + if (!fat_is_valid_cl(fat, dir->head) || !fat_is_cl_head(fat, dir->head)) { + pwarn("Directory entry %s of size %u referencing invalid cluster %u\n", + fullpath(dir), dir->size, dir->head); + if (ask(1, "Truncate")) { + p[28] = p[29] = p[30] = p[31] = 0; + p[26] = p[27] = 0; + if (boot->ClustMask == CLUST32_MASK) + p[20] = p[21] = 0; + dir->size = 0; + dir->head = CLUST_FREE; + return FSDIRMOD; + } else { + return FSERROR; + } + } ret = checkchain(fat, dir->head, &chainsize); /* * Upon return, chainsize would hold the chain length