netatalk 4.5.0
Free and Open Source Apple Filing Protocol (AFP) Server
Loading...
Searching...
No Matches
T2_Dircache_attack.c File Reference

Test the following: More...

`#include "afpcmd.h"`
`#include "afphelper.h"`
`#include "testhelper.h"`

## Functions
STATIC void | test500 ()
STATIC void | test501 ()
STATIC void | test502 ()
STATIC void | test503 ()
STATIC void | test504 ()
STATIC void | test505 ()
STATIC void | test506 ()
STATIC void | test508 ()
| test508: Dircache stress test with cache filling and evictions
static int | access_working_set (uint16_t vol, int start_idx, int end_idx, int passes, const char *prefix)
| Helper: Access a working set of directories multiple times.
static int | sequential_scan (uint16_t vol, int start_idx, int end_idx, const char *prefix)
| Helper: Perform sequential scan of directories.
STATIC void | test509 ()
| test509: Scan resistance test with realistic workload pattern
void | Dircache_attack_test ()

## Detailed Description

Test the following:

test500()
=========
client 1:
mkdir dir1
mkdir dir2
client 2:
mv dir1 dir2/renamed
client 1:
ls dir2
stat dir2/renamed
Check: CNID must not change
Targets: enumerate()
test501()
=========
client 1:
mkdir dir1
mkdir dir2
client 2:
mv dir1 dir2/renamed
client 1:
stat renamed
Check: CNID must not change
Targets: getfildirparms()
test502()
=========
client 1:
mkdir dir1
mkdir dir2
client 2:
mv dir1 dir2/renamed
client 1:
ls renamed
Check: CNID must not change
Targets: enumerate()
test503()
=========
client 1:
mkdir dir1
mkdir dir2
client 2:
mv dir1 dir2/renamed
client 1:
stat renamed
Check: CNID must not change
Targets: getfildirparms()
test504()
=========
client 1:
mkdir -p dir1/dir2
touch dir1/dir2/file
client 2:
mv dir1 renamed1
client 1:
stat file
Check: CNID must not change
Targets: getfildirparms()
test505()
=========
client 1:
mkdir -p dir1/dir2
client 2:
mv dir1 renamed1
client 1:
stat dir2
Check: CNID must not change
Targets: getfildirparms()
test506()
=========
client 1:
mkdir -p dir1/dir2
client 2:
mv dir1 renamed1
mkdir dir1
client 1:
stat dir2
test503
STATIC void test503()
Definition T2_Dircache_attack.c:363
test502
STATIC void test502()
Definition T2_Dircache_attack.c:281
test500
STATIC void test500()
Definition T2_Dircache_attack.c:126
test504
STATIC void test504()
Definition T2_Dircache_attack.c:439
test505
STATIC void test505()
Definition T2_Dircache_attack.c:514
test501
STATIC void test501()
Definition T2_Dircache_attack.c:205
test506
STATIC void test506()
Definition T2_Dircache_attack.c:591
p
size_t p
Definition dircache.c:256
enumerate
static int enumerate(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen, int ext)
Definition enumerate.c:173
CNID
#define CNID(a, b)
Definition etc/afpd/directory.h:96

## Function Documentation

## ◆ access_working_set()

int access_working_set | ( | uint16_t | vol,
|  | int | start_idx,
|  | int | end_idx,
|  | int | passes,
|  | const char * | prefix )
| static

Helper: Access a working set of directories multiple times.

Accesses directories in the specified range multiple times to establish them as "frequently accessed" which should promote them to T2 in ARC.

Parameters

  [in] | vol | Volume ID
  [in] | start_idx | Starting directory index
  [in] | end_idx | Ending directory index (exclusive)
  [in] | passes | Number of times to access each directory
  [in] | prefix | Directory name prefix

Returns
  Number of successful accesses

## ◆ Dircache_attack_test()

void Dircache_attack_test | ( |  | ) |

## ◆ sequential_scan()

int sequential_scan | ( | uint16_t | vol,
|  | int | start_idx,
|  | int | end_idx,
|  | const char * | prefix )
| static

Helper: Perform sequential scan of directories.

Sequentially accesses a range of directories once, simulating a scan operation that should pass through ARC's T1 without evicting T2 entries, but would evict LRU cache entries.

Parameters

  [in] | vol | Volume ID
  [in] | start_idx | Starting directory index
  [in] | end_idx | Ending directory index (exclusive)
  [in] | prefix | Directory name prefix

Returns
  Number of successful accesses

## ◆ test500()

STATIC void test500 | ( |  | ) |

move and rename dir, enumerate new parent, stat renamed dir

## ◆ test501()

STATIC void test501 | ( |  | ) |

move and rename dir, then stat it

## ◆ test502()

STATIC void test502 | ( |  | ) |

move and rename dir, enumerate renamed dir

## ◆ test503()

STATIC void test503 | ( |  | ) |

move and rename dir, stat renamed dir

## ◆ test504()

STATIC void test504 | ( |  | ) |

rename topdir, stat file in subdir of renamed topdir

## ◆ test505()

STATIC void test505 | ( |  | ) |

rename dir, stat subdir in renamed dir

## ◆ test506()

STATIC void test506 | ( |  | ) |

stat subdir in poisened path

## ◆ test508()

STATIC void test508 | ( |  | ) |

test508: Dircache stress test with cache filling and evictions

Test Requirements:

- Configure AFP_DIRCACHESIZE=1024 (small cache for reasonable test time)
- Works with both LRU and ARC modes

This test exercises core dircache behaviors by creating more directories than can fit in cache, forcing evictions and re-access patterns to test cache management under stress.

Test Pattern:

1. Create 2100 directories (2x cache size)
   - During creation: periodically re-access early dirs to establish frequency patterns
2. Multiple re-access passes over different ranges
   - Pass 1-3: Repeatedly access dirs 500-900 (tests frequent access handling)
   - Pass 4: Access dirs 800-1100 (overlapping range)
   - Pass 5: Access dirs 1000-1200 (different range for pattern adaptation)

Expected Behavior:

- LRU: Simple eviction of least recently used entries, all re-accesses are cache hits if not evicted
- ARC: Evictions to ghost lists (B1/B2), ghost hits on re-access, parameter adaptation

Verification: Check logs for evictions, cache hits, and (in ARC) ghost hits and adaptations

## ◆ test509()

STATIC void test509 | ( |  | ) |

test509: Scan resistance test with realistic workload pattern

Test Requirements:

- Configure AFP_DIRCACHESIZE=1024 (small cache, working set fits)
- Works with both LRU and ARC modes for performance comparison

This test provides a realistic workload pattern that simulates common AFP usage: frequently accessed directories (hot working set) mixed with sequential scans (one-time directory traversals). This pattern is optimized for ARC's frequency detection, but also exposes LRU's limitations for comparison purposes.

Realistic Workload Pattern:

- Hot working set (300 dirs): User's active projects/folders (accessed 5x)
- Warm working set (200 dirs): Recently used folders (accessed 2x)
- Sequential scans (1500 dirs): Spotlight indexing, backups, virus scans

Test Pattern (5 cycles of working set + scan):

1. Create 2100 directories (cache=1024)
2. Build hot working set: Access 300 directories 5x (very frequent)
3. Build warm working set: Access 200 directories 2x (moderately frequent) 4-13. Five cycles of:
   - Sequential scan: Access 1500 directories once (1.5x cache size)
   - Verify hot set: Access 300 hot directories 2x
   - Verify warm set: Access 200 warm directories 1x

Expected Behavior:

- LRU: Each scan evicts all working sets → Re-access = misses every cycle
- ARC: Hot/warm sets stay in T2 → Re-access = hits every cycle

Key Differences from test508:

- Separate hot (5x) and warm (2x) working sets to test frequency detection
- Multiple scan/verify cycles (5×) to show sustained advantage
- Larger scans (1500 dirs = 1.5x cache) to stress scan resistance
- Realistic workload pattern amplifies LRU vs ARC performance differences