Azure / Azure/AzFilesSmbMIClient

SmbRefreshTimerCallback: 32-bit integer overflow causes refresh timer to fire every ~7 minutes instead of at ticket expiration

Open
#37 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
C++
Stars
0
Forks
7
Avg merge
6d 7h
Merged PRs (30d)
1

Description

## Summary
In `SmbRefreshTimerCallback`, the calculation of the next refresh due time suffers from a 32-bit integer overflow, causing the timer to re-fire approximately every ~429 seconds (~7 minutes 9 seconds), regardless of the actual Kerberos ticket expiration time.

## Affected Code
`Windows/dll/src/AzFilesSmbMI.cpp`, inside `SmbRefreshTimerCallback`:

```cpp
LARGE_INTEGER liDueTime;
liDueTime.QuadPart = -(static_cast(dwCredentialExpiresInSeconds * 1000 * 1000 * 10));
```

## Root Cause
`static_cast` is applied **after** the multiplication has already been evaluated. `dwCredentialExpiresInSeconds` is a `DWORD` (unsigned 32-bit), and the literals `1000 * 1000 * 10` are evaluated as `int` (32-bit), so the entire multiplication is performed as a 32-bit unsigned integer operation before being cast to 64-bit.

Once `dwCredentialExpiresInSeconds` exceeds roughly 430 seconds (`2^32 / 10,000,000 ≈ 429.4967296`), the multiplication result (in 100-nanosecond units) exceeds `2^32` and wraps around, producing an unintended short due time instead of the correct one.

## Reproduction Logs
Even though the Kerberos ticket expiration is more than 84,000 seconds (over 23 hours) in the future, `SmbSetCredentialInternal` is re-executed only ~7 minutes later.

```
2026-08-27 07:19:32 [INFO] ExpirationTime: '2026-08-28T06:49:42'
2026-08-27 07:19:32 [INFO] Expires in: '84610' seconds from now (2026-08-27T07:19:32)
2026-08-27 07:26:41 [VERB] SmbSetCredentialInternal(1580) BEGIN <- re-fired after ~7m9s

2026-08-27 07:26:41 [INFO] ExpirationTime: '2026-08-28T06:49:42'
2026-08-27 07:26:41 [INFO] Expires in: '84181' seconds from now (2026-08-27T07:26:41)
2026-08-27 07:33:50 [VERB] SmbSetCredentialInternal(1580) BEGIN <- re-fired after ~7m9s again
```

### Overflow calculation verification (1st occurrence: 84610 seconds)
```
84610 × 10,000,000 = 846,100,000,000 (100ns units)
846,100,000,000 mod 4,294,967,296 = 4,286,409,984
4,286,409,984 ÷ 10,000,000 = 428.64 seconds ≈ matches observed 429s
```

### Overflow calculation verification (2nd occurrence: 84181 seconds)
```
84181 × 10,000,000 = 841,810,000,000 (100ns units)
841,810,000,000 mod 4,294,967,296 = 4,291,377,280
4,291,377,280 ÷ 10,000,000 = 429.14 seconds ≈ matches observed 429s
```

In both cases, the predicted value from the overflow calculation closely matches the observed log timing, strongly confirming the root cause.

## Impact
This affects the automatic refresh functionality driven by `SmbRefreshCredential` (the `REFRESH` command). Whenever `dwCredentialExpiresInSeconds` exceeds ~430 seconds (which is essentially always the case for normal Kerberos ticket lifetimes), the timer fires at an incorrect ~7-minute interval instead of respecting the actual expiration time.

This results in:
- Unnecessary repeated requests to the IMDS endpoint and Azure Files Service
- Increased risk of throttling / rate limiting
- Processing that should occur once every several hours (or once a day) instead running every few minutes

## Suggested Fix
Cast `dwCredentialExpiresInSeconds` to `LONGLONG` **before** performing the multiplication, so that the entire calculation is done in 64-bit arithmetic:

```cpp
liDueTime.QuadPart = -(static_cast(dwCredentialExpiresInSeconds) * 1000 * 1000 * 10);
```

## Affected File
- `Windows/dll/src/AzFilesSmbMI.cpp` (`SmbRefreshTimerCallback` function)

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.