From 71ecccf279d3660812b18803a75f368d2f76eea6 Mon Sep 17 00:00:00 2001
From: Sam James <sam@gentoo.org>
Date: Thu, 22 Sep 2022 04:00:45 +0100
Subject: [PATCH 1/8] configure.ac: fix bashism in fuse check

configure scripts need to be runnable with a POSIX-compliant /bin/sh.

On many (but not all!) systems, /bin/sh is provided by Bash, so errors
like this aren't spotted. Notably Debian defaults to /bin/sh provided
by dash which doesn't tolerate such bashisms as '=='.

This retains compatibility with bash.

Fixes configure warnings/errors like:
```
checking Windows OS... no
./configure: 13360: test: xinternal: unexpected operator
checking for pthread_create in -lpthread... yes
checking Solaris OS... no
```

Signed-off-by: Sam James <sam@gentoo.org>
---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 3e0c5c50..5d788bff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -228,7 +228,7 @@ esac
 
 if test "x${enable_ntfs_3g}" != "xyes"; then
 	with_fuse="none"
-elif test "x${with_fuse}" == "x"; then
+elif test "x${with_fuse}" = "x"; then
 	AC_MSG_CHECKING([fuse compatibility])
 	case "${target_os}" in
 	linux*|solaris*)
-- 
2.49.0


From e73d481a76a5814076ff78a1c3a70e9b7da7c0e9 Mon Sep 17 00:00:00 2001
From: Erik Larsson <erik@tuxera.com>
Date: Mon, 12 Dec 2022 18:51:12 +0200
Subject: [PATCH 2/8] mkntfs.c: Enable microsecond-precision volume creation
 time.

Previously the creation time was filled in with seconds (obtained using
time(NULL)) but the microsecond part was left zeroed. Fixed by using
gettimeofday when available.
---
 ntfsprogs/mkntfs.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/ntfsprogs/mkntfs.c b/ntfsprogs/mkntfs.c
index 3e127a3d..5c3a367b 100644
--- a/ntfsprogs/mkntfs.c
+++ b/ntfsprogs/mkntfs.c
@@ -776,8 +776,20 @@ static ntfs_time mkntfs_time(void)
 
 	ts.tv_sec = 0;
 	ts.tv_nsec = 0;
-	if (!opts.use_epoch_time)
-		ts.tv_sec = time(NULL);
+	if (!opts.use_epoch_time) {
+#ifdef HAVE_GETTIMEOFDAY
+		struct timeval tv = { 0, 0, };
+
+		if (!gettimeofday(&tv, NULL)) {
+			ts.tv_sec = tv.tv_sec;
+			ts.tv_nsec = tv.tv_usec * 1000L;
+		}
+		else
+#endif
+		{
+			ts.tv_sec = time(NULL);
+		}
+	}
 	return timespec2ntfs(ts);
 }
 
-- 
2.49.0


From 01b9bddc0c2165baa46abe7562550ef4e8c2752b Mon Sep 17 00:00:00 2001
From: Erik Larsson <erik@tuxera.com>
Date: Wed, 3 May 2023 09:57:34 +0200
Subject: [PATCH 3/8] attrib.c: Fix errno not being set on NULL character in
 attribute name.

This is an error condition as we jump to err_out, but there's no errno
value set to accompany it. Fixed by setting EIO.
---
 libntfs-3g/attrib.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libntfs-3g/attrib.c b/libntfs-3g/attrib.c
index efb91943..652a60f8 100644
--- a/libntfs-3g/attrib.c
+++ b/libntfs-3g/attrib.c
@@ -433,6 +433,7 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
 		if (ntfs_ucsnlen(name, name_len) != name_len) {
 			ntfs_log_error("Null character in attribute name"
 				" of inode %lld\n",(long long)ni->mft_no);
+			errno = EIO;
 			goto err_out;
 		}
 		name = ntfs_ucsndup(name, name_len);
-- 
2.49.0


From 241ddb38605b6b298174e6f1019e8e2502a45558 Mon Sep 17 00:00:00 2001
From: Erik Larsson <erik@tuxera.com>
Date: Wed, 3 May 2023 10:44:57 +0200
Subject: [PATCH 4/8] index.c: Fix crash when a reparse tag cannot be found in
 the index.

When 'remove_reparse_index', called by 'ntfs_delete_reparse_index',
fails to look up a reparse key in the index, it leaves the
'ntfs_index_context' without a populated 'INDEX_BLOCK *ib' field.

This causes 'remove_reparse_index' to fail but the index entry is then
marked dirty unconditionally in 'ntfs_index_entry_mark_dirty', called by
'ntfs_delete_reparse_index', even though 'ib' may be NULL.

The following 'ntfs_index_ctx_put' call then starts to write out the
dirty 'INDEX_BLOCK', which causes a crash.

Fixed by only marking the index block dirty in if it's non-NULL.

Thanks to Stephen Greenham <sg@solarisfire.com> for reporting this issue
and providing debug information.
---
 libntfs-3g/index.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libntfs-3g/index.c b/libntfs-3g/index.c
index e48d6aaf..efe18d89 100644
--- a/libntfs-3g/index.c
+++ b/libntfs-3g/index.c
@@ -66,8 +66,9 @@ void ntfs_index_entry_mark_dirty(ntfs_index_context *ictx)
 {
 	if (ictx->is_in_root)
 		ntfs_inode_mark_dirty(ictx->actx->ntfs_ino);
-	else
+	else if (ictx->ib != NULL) {
 		ictx->ib_dirty = TRUE;
+	}
 }
 
 static s64 ntfs_ib_vcn_to_pos(ntfs_index_context *icx, VCN vcn)
-- 
2.49.0


From 1565b01e215c74e5c5f83f3ecde1ed682637dc5a Mon Sep 17 00:00:00 2001
From: Erik Larsson <erik@tuxera.com>
Date: Tue, 9 May 2023 11:25:10 +0300
Subject: [PATCH 5/8] mft.c: Fix broken free MFT records accounting during
 bitmap extension.

When the bitmap needs extending, 'vol->free_mft_records' is incremented
by 8*8=64 records. This is due to the bitmap's initialized area being
extended 8 bytes at a time.
However the way 'vol->free_mft_records' is being initialized is that all
the bits that are currently allocated to the MFT bitmap are already
taken into account at initialization time. This leads to a value for
'vol->free_mft_records' that is larger than the actual available number
of MFT records.

For example if there are 20 used MFT records and the bitmap has a 4096
byte allocation where 16 bytes are initialized, the number of free MFT
records are ((8 * 16) - 20) + (8 * (4096 - 16)) = 32748 records
available.
If we now expand the bitmap by 8 initialized bytes, we'd be adding 64
MFT entries according to the logic in the function
'ntfs_mft_bitmap_extend_initialized'.
However we are expanding it within the bounds of the existing allocation
where there is (4096 - 16) bytes free, so they shouldn't be added at all
at this stage.

The result is that our internal accounting is that we have 32748 + 64 =
32812 available MFT records, but in reality we will have 32748 records
available all the time until we expand the allocation beyond 4096 bytes.

Fixed by incrementing 'vol->free_mft_records' when the allocation is
expanded, not when the initialized size is.
---
 libntfs-3g/mft.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libntfs-3g/mft.c b/libntfs-3g/mft.c
index aefbb5f1..cd2b4157 100644
--- a/libntfs-3g/mft.c
+++ b/libntfs-3g/mft.c
@@ -978,7 +978,6 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol)
 	ll = ntfs_attr_pwrite(mftbmp_na, old_initialized_size, 8, &ll);
 	if (ll == 8) {
 		ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n");
-		vol->free_mft_records += (8 * 8); 
 		ret = 0;
 		goto out;
 	}
@@ -1776,6 +1775,7 @@ retry:
 			(long long)mftbmp_na->initialized_size);
 	if (mftbmp_na->initialized_size + 8 > mftbmp_na->allocated_size) {
 
+		const s64 old_allocated_size = mftbmp_na->allocated_size;
 		int ret = ntfs_mft_bitmap_extend_allocation(vol);
 
 		if (ret == STATUS_ERROR)
@@ -1792,6 +1792,9 @@ retry:
 				(long long)mftbmp_na->allocated_size,
 				(long long)mftbmp_na->data_size,
 				(long long)mftbmp_na->initialized_size);
+
+		vol->free_mft_records +=
+			(mftbmp_na->allocated_size - old_allocated_size) << 3;
 	}
 	/*
 	 * We now have sufficient allocated space, extend the initialized_size
-- 
2.49.0


From 233658e5a1599e40bbd8211e64bb98a12751b1ea Mon Sep 17 00:00:00 2001
From: Erik Larsson <erik@tuxera.com>
Date: Fri, 19 May 2023 12:20:54 +0300
Subject: [PATCH 6/8] attrib.c: Fix another instance of errno not being set on
 error.

---
 libntfs-3g/attrib.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libntfs-3g/attrib.c b/libntfs-3g/attrib.c
index 652a60f8..6bee808b 100644
--- a/libntfs-3g/attrib.c
+++ b/libntfs-3g/attrib.c
@@ -463,6 +463,7 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
 				ntfs_log_error("Null character in attribute"
 					" name in inode %lld\n",
 					(long long)ni->mft_no);
+				errno = EIO;
 				goto put_err_out;
 			}
 			name = ntfs_ucsndup(attr_name, a->name_length);
-- 
2.49.0


From 6b3f0960690ec6f4f157815adad532dc4cea1dbe Mon Sep 17 00:00:00 2001
From: Erik Larsson <erik@tuxera.com>
Date: Sun, 28 May 2023 08:21:34 +0300
Subject: [PATCH 7/8] ntfsprogs/Makefile.am: Only install manpages for 'extras'
 when enabled.

We used to always install all the manpages, but some are specific to the
'extras' enabled with the configure option '--enable-extras'.
Fixed by only installing the 'extras' manpages when '--enable-extras' is
active.

Also since this commit touches the list of manpages a bit of cleanup was
done to make sure there's only one manpage per line (helps to minimize
diffs) and also that the manpages are sorted in alphabetical order in
ntfsprogs/Makefile.am to avoid future confusion.

Thanks to user 'opty77' for reporting this issue:
https://github.com/tuxera/ntfs-3g/issues/82
---
 ntfsprogs/Makefile.am | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/ntfsprogs/Makefile.am b/ntfsprogs/Makefile.am
index 08228322..babaf341 100644
--- a/ntfsprogs/Makefile.am
+++ b/ntfsprogs/Makefile.am
@@ -23,13 +23,27 @@ EXTRA_PROGRAM_NAMES	= ntfswipe ntfstruncate ntfsrecover \
 QUARANTINED_PROGRAM_NAMES = ntfsdump_logfile ntfsmftalloc ntfsmove ntfsck \
 			   ntfsfallocate
 
-man_MANS		= mkntfs.8 ntfsfix.8 ntfslabel.8 ntfsinfo.8 \
-			  ntfsundelete.8 ntfsresize.8 ntfsprogs.8 ntfsls.8 \
-			  ntfsclone.8 ntfscluster.8 ntfscat.8 ntfscp.8 \
-			  ntfscmp.8 ntfswipe.8 ntfstruncate.8 \
-			  ntfsdecrypt.8 ntfsfallocate.8 ntfsrecover.8 \
-			  ntfsusermap.8 ntfssecaudit.8
-EXTRA_MANS		=
+man_MANS		= mkntfs.8 \
+			  ntfscat.8 \
+			  ntfsclone.8 \
+			  ntfscluster.8 \
+			  ntfscmp.8 \
+			  ntfscp.8 \
+			  ntfsdecrypt.8 \
+			  ntfsfallocate.8 \
+			  ntfsfix.8 \
+			  ntfsinfo.8 \
+			  ntfslabel.8 \
+			  ntfsls.8 \
+			  ntfsprogs.8 \
+			  ntfsresize.8 \
+			  ntfsundelete.8
+
+EXTRA_MANS		= ntfsrecover.8 \
+			  ntfssecaudit.8 \
+			  ntfstruncate.8 \
+			  ntfsusermap.8 \
+			  ntfswipe.8
 
 CLEANFILES		= $(EXTRA_PROGRAMS)
 
@@ -44,6 +58,7 @@ bin_PROGRAMS		+= $(EXTRA_PROGRAM_NAMES)
 if ENABLE_QUARANTINED
 bin_PROGRAMS		+= $(QUARANTINED_PROGRAM_NAMES)
 endif
+man_MANS		+= $(EXTRA_MANS)
 else
 EXTRA_PROGRAMS		= $(EXTRA_PROGRAM_NAMES)
 endif
-- 
2.49.0


From 75dcdc2cf37478fad6c0e3427403d198b554951d Mon Sep 17 00:00:00 2001
From: Erik Larsson <erik@tuxera.com>
Date: Tue, 13 Jun 2023 17:47:15 +0300
Subject: [PATCH 8/8] unistr.c: Fix use-after-free in 'ntfs_uppercase_mbs'.

If 'utf8_to_unicode' throws an error due to an invalid UTF-8 sequence,
then 'n' will be less than 0 and the loop will terminate without storing
anything in '*t'. After the loop the uppercase string's allocation is
freed, however after it is freed it is unconditionally accessed through
'*t', which points into the freed allocation, for the purpose of NULL-
terminating the string. This leads to a use-after-free.
Fixed by only NULL-terminating the string when no error has been thrown.

Thanks for Jeffrey Bencteux for reporting this issue:
https://github.com/tuxera/ntfs-3g/issues/84
---
 libntfs-3g/unistr.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libntfs-3g/unistr.c b/libntfs-3g/unistr.c
index 5854b3b7..db8ddf42 100644
--- a/libntfs-3g/unistr.c
+++ b/libntfs-3g/unistr.c
@@ -1189,8 +1189,9 @@ char *ntfs_uppercase_mbs(const char *low,
 			free(upp);
 			upp = (char*)NULL;
 			errno = EILSEQ;
+		} else {
+			*t = 0;
 		}
-		*t = 0;
 	}
 	return (upp);
 }
-- 
2.49.0

