All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>,
	Sasha Levin <sashal@kernel.org>,
	ntfs3@lists.linux.dev
Subject: [PATCH AUTOSEL 6.18-5.15] fs/ntfs3: Support timestamps prior to epoch
Date: Sat,  6 Dec 2025 09:02:25 -0500	[thread overview]
Message-ID: <20251206140252.645973-20-sashal@kernel.org> (raw)
In-Reply-To: <20251206140252.645973-1-sashal@kernel.org>

From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>

[ Upstream commit 5180138604323895b5c291eca6aa7c20be494ade ]

Before it used an unsigned 64-bit type, which prevented proper handling
of timestamps earlier than 1970-01-01. Switch to a signed 64-bit type to
support pre-epoch timestamps. The issue was caught by xfstests.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Now I have a complete understanding. Let me write the detailed analysis:

## Detailed Analysis

### 1. COMMIT MESSAGE ANALYSIS

**Subject:** `fs/ntfs3: Support timestamps prior to epoch`

**Commit Body:**
- The commit explains that before this fix, the code used an **unsigned
  64-bit type** (`u64`), which prevented proper handling of timestamps
  earlier than 1970-01-01 (the Unix epoch).
- The fix switches to a **signed 64-bit type** (`s64`) to support pre-
  epoch timestamps.
- The issue was caught by **xfstests test 258**, which specifically
  tests for timestamps prior to the epoch.

**Tags:**
- **No `Cc: stable@vger.kernel.org` tag** is present.
- **No `Fixes:` tag** is present.

### 2. CODE CHANGE ANALYSIS

#### The Bug:

In the current code (before the patch):

```980:987:fs/ntfs3/ntfs_fs.h
static inline void nt2kernel(const __le64 tm, struct timespec64 *ts)
{
        u64 t = le64_to_cpu(tm) - _100ns2seconds * SecondsToStartOf1970;

        // WARNING: do_div changes its first argument(!)
        ts->tv_nsec = do_div(t, _100ns2seconds) * 100;
        ts->tv_sec = t;
}
```

The variable `t` is declared as `u64` (unsigned 64-bit integer). NTFS
timestamps are stored as the number of 100-nanosecond intervals since
January 1, 1601. After subtracting `SecondsToStartOf1970`
(0x00000002B6109100), which represents the number of seconds between
1601 and 1970, `t` represents a Unix timestamp.

**Problem:** When the NTFS timestamp represents a date before January 1,
1970, the subtraction produces a **negative** result. But since `t` is
unsigned (`u64`), the negative value wraps around to a very large
positive value, resulting in a wrong (future) timestamp.

**The `do_div` macro** operates on unsigned integers and uses unsigned
division, which doesn't handle negative values correctly.

#### The Fix:

The patch changes:
1. `u64 t` → `s64 t` (signed 64-bit integer)
2. `do_div(t, _100ns2seconds)` → `div_s64_rem(t, _100ns2seconds, &t32)`
   (signed division)
3. Introduces `s32 t32` to hold the remainder

The new code:
```c
static inline void nt2kernel(const __le64 tm, struct timespec64 *ts)
{
        s32 t32;
        /* use signed 64 bit to support timestamps prior to epoch.
xfstest 258. */
        s64 t = le64_to_cpu(tm) - _100ns2seconds * SecondsToStartOf1970;

        ts->tv_sec = div_s64_rem(t, _100ns2seconds, &t32);
        ts->tv_nsec = t32 * 100;
}
```

`div_s64_rem()` is designed for signed 64-bit division with a 32-bit
divisor, properly handling negative values and returning the remainder
through a pointer.

**Root Cause:** Using unsigned arithmetic for a value that can be
negative (pre-epoch timestamps).

### 3. CLASSIFICATION

- **Bug fix:** YES - This is fixing incorrect behavior with timestamps
  before 1970.
- **New feature:** NO - It doesn't add new functionality, only fixes
  existing functionality.
- **Security fix:** NO - No security implications.
- **Exception category:** NO - Not a device ID, quirk, DT update, build
  fix, or documentation fix.

### 4. SCOPE AND RISK ASSESSMENT

**Lines Changed:** Very minimal - changes ~8 lines of code within a
single inline function.

**Files Touched:** 1 file (`fs/ntfs3/ntfs_fs.h`)

**Subsystem Complexity:**
- NTFS3 is a relatively new filesystem (added in 5.15)
- The change is in a core time conversion function `nt2kernel()` that is
  called whenever reading timestamps from disk
- All file timestamps (creation, modification, access times) use this
  function

**Risk Assessment:**
- **LOW RISK** - The change is small, surgical, and uses a well-
  established kernel API (`div_s64_rem`)
- The new code is mathematically equivalent to the old code for
  timestamps after 1970
- For timestamps before 1970, the new code produces correct results
  (negative `tv_sec` values)
- The `timespec64` structure's `tv_sec` field is `time64_t` which is
  signed (`__s64`), so it can properly represent negative timestamps

### 5. USER IMPACT

**Who is affected?**
- Users of NTFS3 filesystem
- Users with NTFS volumes containing files with pre-1970 timestamps

**How severe?**
- The bug causes **data corruption** (incorrect timestamp
  display/storage) for pre-epoch files
- Without this fix, timestamps like January 1, 1960 would appear as some
  date far in the future
- This breaks file management tools and any software relying on correct
  timestamps

**Test Coverage:**
- The fix was identified by **xfstests generic/258**, a standard
  filesystem test that specifically validates pre-epoch timestamp
  handling
- This is a well-known and commonly run test suite

### 6. STABILITY INDICATORS

- **No `Tested-by:` tag** - However, xfstests is mentioned, implying the
  fix was tested against this test suite
- **No `Reviewed-by:` tag**
- The commit is from the ntfs3 maintainer (Konstantin Komarov from
  Paragon Software)

### 7. DEPENDENCY CHECK

- **No dependencies** - This is a standalone fix
- Uses existing kernel APIs (`div_s64_rem`, `s64`, `s32`) that have been
  available for a long time
- The affected code (`nt2kernel` function) has existed since ntfs3 was
  introduced in kernel 5.15

### Summary

**YES signals:**
1. ✅ Fixes a **real bug** (incorrect timestamps for pre-epoch dates)
2. ✅ **Small and surgical** change - only 8 lines changed in one
   function
3. ✅ **Obviously correct** - uses proper signed arithmetic for values
   that can be negative
4. ✅ No new features, no new APIs
5. ✅ Caught by **xfstests**, a standard fs test suite (test 258)
6. ✅ Applies to all stable kernels that have ntfs3 (5.15+)
7. ✅ Zero risk of regression for post-epoch timestamps (mathematically
   equivalent)
8. ✅ Fixes **data integrity issue** (timestamp corruption)

**NO signals:**
1. ⚠️ No explicit `Cc: stable@vger.kernel.org` tag
2. ⚠️ No `Fixes:` tag
3. ⚠️ No `Tested-by:` or `Reviewed-by:` tags

**Verdict:**

This is a clear bug fix that addresses a real issue (incorrect pre-epoch
timestamp handling) that affects NTFS3 users. The fix is small,
surgical, uses well-tested kernel APIs, and is mathematically correct.
While the commit lacks stable tags, the nature of the fix - correcting
data integrity issues with timestamps - makes it appropriate for
backporting. The bug has existed since ntfs3 was introduced (5.15), so
all stable trees with ntfs3 would benefit from this fix.

The lack of `Cc: stable` tag is likely an oversight since the fix
clearly meets stable kernel criteria: it's a bug fix, small in scope,
obviously correct, and fixes a real user-visible issue (incorrect file
timestamps).

**YES**

 fs/ntfs3/ntfs_fs.h | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index 630128716ea73..2649fbe16669d 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -979,11 +979,12 @@ static inline __le64 kernel2nt(const struct timespec64 *ts)
  */
 static inline void nt2kernel(const __le64 tm, struct timespec64 *ts)
 {
-	u64 t = le64_to_cpu(tm) - _100ns2seconds * SecondsToStartOf1970;
+	s32 t32;
+	/* use signed 64 bit to support timestamps prior to epoch. xfstest 258. */
+	s64 t = le64_to_cpu(tm) - _100ns2seconds * SecondsToStartOf1970;
 
-	// WARNING: do_div changes its first argument(!)
-	ts->tv_nsec = do_div(t, _100ns2seconds) * 100;
-	ts->tv_sec = t;
+	ts->tv_sec = div_s64_rem(t, _100ns2seconds, &t32);
+	ts->tv_nsec = t32 * 100;
 }
 
 static inline struct ntfs_sb_info *ntfs_sb(struct super_block *sb)
-- 
2.51.0


  parent reply	other threads:[~2025-12-06 14:03 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-06 14:02 [PATCH AUTOSEL 6.18-6.1] ksmbd: fix use-after-free in ksmbd_tree_connect_put under concurrency Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.12] fs/ntfs3: check for shutdown in fsync Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.1] smb/server: fix return value of smb2_ioctl() Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.1] gfs2: Fix use of bio_chain Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-5.10] Bluetooth: btusb: Add new VID/PID 13d3/3533 for RTL8821CE Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.12] Bluetooth: btusb: Add new VID/PID 0x0489/0xE12F for RTL8852BE-VT Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-5.10] btrfs: scrub: always update btrfs_scrub_progress::last_physical Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.12] wifi: rtl8xxxu: Fix HT40 channel config for RTL8192CU, RTL8723AU Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.12] Bluetooth: btusb: MT7920: Add VID/PID 0489/e135 Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.12] Bluetooth: btusb: MT7922: Add VID/PID 0489/e170 Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.12] wifi: cfg80211: use cfg80211_leave() in iftype change Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.1] kbuild: Use objtree for module signing key path Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.1] wifi: brcmfmac: Add DMI nvram filename quirk for Acer A1 840 tablet Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-5.10] hfsplus: Verify inode mode when loading from disk Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.6] gfs2: fix remote evict for read-only filesystems Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.17] Bluetooth: btusb: add new custom firmwares Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18] hfsplus: fix volume corruption issue for generic/101 Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-5.10] hfsplus: fix missing hfs_bnode_get() in __hfs_bnode_create Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-5.10] hfsplus: fix volume corruption issue for generic/070 Sasha Levin
2025-12-06 14:02 ` Sasha Levin [this message]
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.6] Bluetooth: btusb: Add new VID/PID 2b89/6275 for RTL8761BUV Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.6] ntfs: set dummy blocksize to read boot_block when mounting Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-5.10] hfsplus: fix volume corruption issue for generic/073 Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.12] wifi: mt76: mt792x: fix wifi init fail by setting MCU_RUNNING after CLC load Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.12] gfs2: Fix "gfs2: Switch to wait_event in gfs2_quotad" Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.12] wifi: cfg80211: stop radar detection in cfg80211_leave() Sasha Levin
2025-12-06 14:55   ` Johannes Berg
2025-12-06 22:49     ` Sasha Levin
2025-12-06 14:02 ` [PATCH AUTOSEL 6.18-6.6] ksmbd: vfs: fix race on m_flags in vfs_cache Sasha Levin
  -- strict thread matches above, loose matches on Subject: below --
2025-12-09  0:14 [PATCH AUTOSEL 6.18-6.1] ksmbd: fix use-after-free in ksmbd_tree_connect_put under concurrency Sasha Levin
2025-12-09  0:15 ` [PATCH AUTOSEL 6.18-5.15] fs/ntfs3: Support timestamps prior to epoch Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251206140252.645973-20-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=almaz.alexandrovich@paragon-software.com \
    --cc=ntfs3@lists.linux.dev \
    --cc=patches@lists.linux.dev \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.