From 71ecccf279d3660812b18803a75f368d2f76eea6 Mon Sep 17 00:00:00 2001 From: Sam James 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 --- 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 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 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 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 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 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 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 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 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