Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
63c98fd
nomount: implement whiteouts
maxsteeel Jun 26, 2026
70e3fae
verify parent_inode->i_sb to avoid NULL pointer dereference
maxsteeel Jun 26, 2026
8222b3e
omit sandboxed/isolated processes
maxsteeel Jun 26, 2026
2ce12c9
remove whiteout logic of handle_getname, optimizations
maxsteeel Jun 26, 2026
09541f1
kernel: optimize memory layout and VFS hot path execution
maxsteeel Jun 27, 2026
1799379
test i_op hijacking
maxsteeel Jun 27, 2026
844ebf4
test s_op hijacking, organize code
maxsteeel Jun 28, 2026
84fa23b
test f_op hijacking
maxsteeel Jun 28, 2026
baebab0
refactor this whole thing of hijacking
maxsteeel Jun 29, 2026
b162778
trying to fix bootloops
maxsteeel Jun 29, 2026
ba5e044
remove nocfi
maxsteeel Jun 30, 2026
b32768d
fix bitwise comprobation in parent permissions
maxsteeel Jun 30, 2026
557c0c9
restore permission hook, test d_op hijacking
maxsteeel Jun 30, 2026
a564c54
optimize getname hook
maxsteeel Jul 1, 2026
89186ac
optimize spoof mmap metadata hook, remove unused helper
maxsteeel Jul 1, 2026
14a4329
skip whiteout comprobation in nomount_actor_proxy if no whiteout
maxsteeel Jul 1, 2026
262e8fe
remove hijacking permission hooks, hijack i_op of parent dirs
maxsteeel Jul 1, 2026
c5aca51
remove deprecated hooks
maxsteeel Jul 1, 2026
b757a87
organize code, fix compilation on >5.12 kernels
maxsteeel Jul 1, 2026
7dacb49
spoof entire kstatfs
maxsteeel Jul 1, 2026
11793d2
convert NOMOUNT_VERSION in a string
maxsteeel Jul 1, 2026
0c0dd70
fix add / delete bug in userspace
maxsteeel Jul 1, 2026
0e52f47
refactor: delete nomount_inodes_ht, nomount_inode_node
maxsteeel Jul 1, 2026
6dd08a0
retrying hijacking permissions again, organize code
maxsteeel Jul 2, 2026
fe34c64
fix compilation errors
maxsteeel Jul 2, 2026
923aced
trying to bypass selinux
maxsteeel Jul 2, 2026
a614d06
remove deprecated `nomount_handle_permission` hook
maxsteeel Jul 3, 2026
90c0937
restore comprobations in `nomount_handle_getname`
maxsteeel Jul 3, 2026
2a22610
hookless
maxsteeel Jul 5, 2026
57f1a06
remove alias engine
maxsteeel Jul 5, 2026
e50dd53
eliminate whiteout comprobation in `nomount_actor_proxy`
maxsteeel Jul 5, 2026
b61b8cc
fs: nomount: add missing #include <linux/module.h>
cvnertnc Jul 6, 2026
44c4ca2
convert NOMOUNT_VERSION again in a number
maxsteeel Jul 8, 2026
f9cdc7d
refactor
maxsteeel Jul 18, 2026
7f6e910
replace children list to idr tree, refactor iterate_dir
maxsteeel Jul 23, 2026
178524b
refactor uid exclusions
maxsteeel Jul 23, 2026
d3b2f0c
remove `nomount_all_dirs_list`
maxsteeel Jul 23, 2026
a35519e
fix some kernel panics, memory leaks, and optimice netlink dump rules
maxsteeel Jul 23, 2026
b797cea
remove `nm_symlink_iops`, improve symlink handling
maxsteeel Jul 23, 2026
f580398
fix more bugs
maxsteeel Jul 23, 2026
f253203
kernel/src: add linux/file header for fput()
Neebe3289 Jul 24, 2026
a8a8b5c
userspace: fix ack bug and prevent overflow
maxsteeel Jul 24, 2026
d4535a8
userspace: replace bss buffer for stack-based buffer
maxsteeel Jul 24, 2026
0905925
replace `nomount_invalidate_cache` for a lazy invalidation in `nm_d_r…
maxsteeel Jul 24, 2026
cfd1262
kernel/src: fix declaration-after-statement in nomount_hijacked_itera…
Neebe3289 Jul 25, 2026
88379d6
kernel: reestructuring and refactoring...
maxsteeel Jul 25, 2026
5796359
kernel: implement unlink and rename support with COW rule operations
maxsteeel Jul 25, 2026
b8d397d
add multi-uid support
maxsteeel Jul 25, 2026
ee56b82
rename internal dir flag to virtual dir, show virtual dir flag in use…
maxsteeel Jul 25, 2026
617c662
implement uid exclusion list, adapt webui to the new uid exclusion list
maxsteeel Jul 25, 2026
58d579b
fix "format %llu expects unsigned long long, but inode->i_ino is unsi…
maxsteeel Jul 25, 2026
2c96934
kernel: remove stat size/blocks spoofing
maxsteeel Jul 27, 2026
c422152
kernel: GKI-wide compile compat + dcache fixes (#31)
Bouteillepleine Jul 28, 2026
847e8bd
kernel: fix UAF risks, implement a lazy cleanup of dir_node
maxsteeel Jul 29, 2026
b85be15
kernel: DCACHE_DONTCACHE the blocked reader's shadow dentry (#32)
Bouteillepleine Jul 29, 2026
647593c
kernel: implement correct cleanup of hijacked structures in nomount_r…
maxsteeel Jul 29, 2026
9f8eeba
kernel: remove unneeded unlink and rename functions
maxsteeel Jul 30, 2026
16f44c2
kernel: remove nm_root_cred
maxsteeel Jul 30, 2026
d860afe
kernel: some changes in nomount_hijacked_lookup
maxsteeel Jul 30, 2026
88dedae
kernel: implement statfs support
maxsteeel Jul 31, 2026
b541650
kernel: replace direct asignation of d_op with a hijacking of origina…
maxsteeel Jul 31, 2026
659567b
change vfs_getxattr / vfs_setxattr to __vfs_getxattr / __vfs_setattr
maxsteeel Aug 1, 2026
4443d7f
kernel: add dentry comprobation in nomount_create_new_inode
maxsteeel Aug 2, 2026
9b0f949
kernel: fix -EOPNOTSUPP in xattr handlers
maxsteeel Aug 3, 2026
ca21a4b
kernel: add S_PRIVATE flag to the real file to bypass LSM checks (dir…
maxsteeel Aug 3, 2026
e8a783d
kernel: remove S_PRIVATE flag after mapping the file (dirty fix)
maxsteeel Aug 3, 2026
b893eed
Revert "kernel: implement statfs support"
maxsteeel Aug 5, 2026
a86aaa2
kernel: remove unneeded `idr_preload()`
maxsteeel Aug 5, 2026
f819793
nomount: replace Generic Netlink API with IPC+Keyring API (#35)
maxsteeel Aug 6, 2026
1872cc0
kernel: use aligned pointer in idr_alloc to avoid Radix Tree collision
maxsteeel Aug 6, 2026
5f6c175
webui: correct exclusions toast
maxsteeel Aug 7, 2026
740ed47
workflow: update
maxsteeel Aug 7, 2026
c77c4c2
workflow: use TopTal minifier API for minify webui files
maxsteeel Aug 7, 2026
8e26737
kernel: add CAP_SYS_ADMIN check to keyring instantiate hook
maxsteeel Aug 7, 2026
ced40d4
workflow: use standalone esbuild binary + shell to minify webui files
maxsteeel Aug 7, 2026
62b97e9
kernel: remove `nomount_get_rule_locked`
maxsteeel Aug 7, 2026
1ae92ee
kernel: unify `nm_dops` into `nomount_hijack_dentry_ops`
maxsteeel Aug 7, 2026
eaf903a
kernel: fix RCU memory lifecycle
maxsteeel Aug 7, 2026
37886ee
kernel: remove redundancy in `nm_alloc_rule`
maxsteeel Aug 7, 2026
be9e926
kernel: improve memory management in `nomount_generate_virtual_topology`
maxsteeel Aug 8, 2026
024601e
kernel: remove unneeded `idr_preload()`
maxsteeel Aug 8, 2026
40e0196
kernel: remove unneeded and problematic iterate check in `nm_dir_iter…
maxsteeel Aug 8, 2026
3c713dd
kernel: improve RCU management in `nm_d_revalidate`
maxsteeel Aug 8, 2026
7a8aec9
kernel: fix use-after-free in dentry ops
maxsteeel Aug 8, 2026
8ac3b01
kernel: do not put S_PRIVATE flag into dir_ops
maxsteeel Aug 8, 2026
dcf2eff
kernel: remove inode->i_lock spinlock from `nomount_cure_sb_inodes`
maxsteeel Aug 8, 2026
2bafaea
kernel: remove unused nm_init_private_list() macro
maxsteeel Aug 8, 2026
5cdaf7b
kernel: use `KMEM_CACHE` macro instead of `kmem_cache_create`
maxsteeel Aug 8, 2026
1dacddf
kernel: refactor nm_process_ipc_payload
maxsteeel Aug 9, 2026
88209d9
kernel: use NOMOUNT_MAGIC_SIG as salt for hash operations
maxsteeel Aug 9, 2026
1a4bca9
kernel: replace magic signature checks with native VFS function valid…
maxsteeel Aug 9, 2026
8bdd8dd
kernel: add checks before overwriting vma->vm_file in mmap/mmap_prepare
maxsteeel Aug 9, 2026
8e42f9b
kernel: implement separated uid and rules cleanup
maxsteeel Aug 10, 2026
9319998
userspace: modernize and expand nm commands
maxsteeel Aug 10, 2026
95e4c8f
module: adapt to the new nm commands
maxsteeel Aug 10, 2026
ce3a991
kernel: simplify child deletion via direct rule pointer matching
maxsteeel Aug 10, 2026
054331e
workflow: reduce binary size adding some build flags
maxsteeel Aug 10, 2026
02365c5
userspace: use stack memory for payload instead of mmap
maxsteeel Aug 12, 2026
8ce6aca
kernel: remove unneeded memset in `nm_process_ipc_payload`
maxsteeel Aug 12, 2026
fc1a55f
userspace: use KEY_SPEC_THREAD_KEYRING ring in add_key()
maxsteeel Aug 12, 2026
c362abe
Return isolated process UIDs as blocked
sarreos Aug 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 20 additions & 23 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: build module

on:
push:
branches: master
branches: [ master, dev ]
paths-ignore:
- '**.md'
- 'kernel/**'
Expand All @@ -13,10 +13,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
ref: ${{ github.ref_name }}

- name: Setup zig
uses: mlugg/setup-zig@v2.2.1
uses: jetsung/setup-zig@v0.0.4
with:
version: master

Expand All @@ -32,11 +34,11 @@ jobs:
run: |
mkdir bin
cd userspace/src
zig cc -target aarch64-linux -Oz -static -nostdlib -ffreestanding -fno-unwind-tables \
zig cc -target aarch64-linux -Oz -mcmodel=tiny -static -nostdlib -ffreestanding -fno-unwind-tables \
-fno-ident -Wno-invalid-noreturn -Wl,--entry=_start nm.c -o ../../bin/nm-arm64

zig cc -target arm-linux -Oz -static -nostdlib -ffreestanding -fno-unwind-tables \
-fno-ident -Wno-invalid-noreturn -Wl,--entry=_start nm.c -o ../../bin/nm-arm
zig cc -target arm-linux -Oz -static -nostdlib -ffreestanding -fno-unwind-tables -fno-ident -Wno-invalid-noreturn \
-ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--entry=_start nm.c -o ../../bin/nm-arm

cd ../../bin
wc -c nm-*
Expand All @@ -54,38 +56,33 @@ jobs:
run: |
NAME=$(sed -n 's/^name=//p' module/module.prop | tr -d '\r' | tr -d ' ')
VERSION=$(sed -n 's/^version=//p' module/module.prop | tr -d '\r' | tr -d ' ')
SHORT_HASH=$(echo "${{ github.sha }}" | cut -c1-7)
SHORT_HASH=$(git rev-parse --short HEAD)
echo "MODULE_NAME=$NAME" >> $GITHUB_ENV
echo "MODULE_VERSION=$VERSION" >> $GITHUB_ENV
echo "COMMIT_HASH=$SHORT_HASH" >> $GITHUB_ENV

- name: Optimize release module
- name: Optimize release module (via standalone esbuild)
run: |
MODULE_BUILD="$RUNNER_TEMP/nomount-module-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT"
WEBUI_BUILD="$RUNNER_TEMP/nomount-webui-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT"

cp -a module "$MODULE_BUILD"
mkdir -p "$WEBUI_BUILD"
sed '/@import ".\/theme.css";/d' module/webroot/styles.css > "$WEBUI_BUILD/temp.css"
cat "$WEBUI_BUILD/temp.css" module/webroot/theme.css > "$WEBUI_BUILD/combined.css"

npx --yes esbuild@0.28.1 module/webroot/index.js \
--bundle --format=esm --minify \
--outfile="$WEBUI_BUILD/index.js"
npx --yes esbuild@0.28.1 module/webroot/styles.css \
--bundle --minify '--external:/internal/*' \
--outfile="$WEBUI_BUILD/styles.css"
curl -sL "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz" -o /tmp/esbuild.tgz
tar -xzf /tmp/esbuild.tgz -C /tmp && mv /tmp/package/bin/esbuild /tmp/esbuild && chmod +x /tmp/esbuild
/tmp/esbuild module/webroot/index.js --bundle --format=esm --minify --outfile="$WEBUI_BUILD/index.js"
/tmp/esbuild "$WEBUI_BUILD/combined.css" --minify --outfile="$WEBUI_BUILD/styles.css"
tr '\n' ' ' < module/webroot/index.html | sed 's/ */ /g' | sed 's/> </></g' > "$WEBUI_BUILD/index.html"

install -m 0644 "$WEBUI_BUILD/index.js" "$MODULE_BUILD/webroot/index.js"
install -m 0644 "$WEBUI_BUILD/styles.css" "$MODULE_BUILD/webroot/styles.css"
rm "$MODULE_BUILD/webroot/theme.css"
install -m 0644 "$WEBUI_BUILD/index.html" "$MODULE_BUILD/webroot/index.html"

node --check "$MODULE_BUILD/webroot/index.js"
test -s "$MODULE_BUILD/webroot/styles.css"
test -s "$MODULE_BUILD/webroot/locales/zh.json"
test ! -e "$MODULE_BUILD/webroot/theme.css"
grep -Fq '@import"/internal/insets.css"' "$MODULE_BUILD/webroot/styles.css"
grep -Fq '@import"/internal/colors.css"' "$MODULE_BUILD/webroot/styles.css"

du -sb module "$MODULE_BUILD"
rm "$MODULE_BUILD/webroot/theme.css"
du -sh module/webroot "$MODULE_BUILD/webroot"

- name: Upload artifact
uses: actions/upload-artifact@v7
Expand Down
273 changes: 0 additions & 273 deletions kernel/INTEGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

This document details the hook architecture used by NoMount within the Linux Virtual File System (VFS).


## 1. Initialization and Configuration (`Kconfig` & `Makefile`)
* **Files:** `fs/Kconfig`, `fs/Makefile`
* **Purpose:** Register NoMount in kernel.
Expand Down Expand Up @@ -43,275 +42,3 @@ diff --git a/fs/Makefile b/fs/Makefile
```

---

## 2. Path Lookup, Access Control, and Permissions.
* **Files:** `fs/namei.c`
* **Hooks:** `getname_flags`, `getname_kernel`, `generic_permission` and `inode_permission`
* **Purpose:** Intercept text strings (paths) originating from both Userspace and Kernelspace before the VFS converts them into physical structures (`dentry`/`inode`). Additionally, ensure that injected files can be traversed and read while correctly simulating the typical attributes of system partitions.
* **Mechanism:**
* In `namei.c`, `nomount_getname_hook` is executed immediately after the path string is allocated in the kernel. `getname_flags` intercepts standard application traffic, while `getname_kernel` catches internal system requests (e.g., `request_firmware`). If the path matches an active rule, the original string is replaced with the actual path of the redirected file. The rest of the kernel processes the call without knowing that it was tricked.
* In `namei.c`, the `nomount_allow_access` hook forces a return of `0` (Success) to prevent native DAC/MAC checks (like SELinux) from blocking access to our injected folders.
* **Integration:**

#### `fs/namei.c`:

```diff
diff --git a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -xxx,xx +xxx,xx @@

#define EMBEDDED_NAME_MAX (PATH_MAX - offsetof(struct filename, iname))

+#ifdef CONFIG_NOMOUNT
+extern struct filename *nomount_handle_getname(struct filename *name);
+extern int nomount_handle_permission(struct inode *inode, int mask);
+#endif
+
struct filename *
getname_flags(const char __user *filename, int flags, int *empty)
{
@@ -xxx,xx +xxx,xx @@ getname_flags(const char __user *filename, int flags, int *empty)

result->uptr = filename;
result->aname = NULL;
+#ifdef CONFIG_NOMOUNT
+ if (!IS_ERR(result)) {
+ result = nomount_handle_getname(result);
+ }
+#endif
audit_getname(result);
return result;
}
@@ -xxx,xx +xxx,xx @@ getname_kernel(const char * filename)
result->uptr = NULL;
result->aname = NULL;
result->refcnt = 1;
+#ifdef CONFIG_NOMOUNT
+ if (!IS_ERR(result)) {
+ result = nomount_handle_getname(result);
+ }
+#endif
audit_getname(result);

return result;
@@ -xxx,xx +xxx,xx @@ int generic_permission(struct inode *inode, int mask)
{
int ret;

+#ifdef CONFIG_NOMOUNT
+ int nm_perm = nomount_handle_permission(inode, mask);
+ if (unlikely(nm_perm < 0)) return nm_perm;
+ if (unlikely(nm_perm > 0)) return 0;
+#endif
+
/*
* Do the basic permission checks.
*/
@@ -xxx,xx +xxx,xx @@ int inode_permission(struct inode *inode, int mask)
{
int retval;

+#ifdef CONFIG_NOMOUNT
+ int nm_perm = nomount_handle_permission(inode, mask);
+ if (unlikely(nm_perm < 0)) return nm_perm;
+ if (unlikely(nm_perm > 0)) return 0;
+#endif
+
retval = sb_permission(inode->i_sb, inode, mask);
if (retval)
return retval;
```

---

## 3. Inverse Resolution and Visibility
* **File:** `fs/d_path.c`
* **Hook:** `d_path`
* **Purpose:** Avoid information leaks and falsify real paths through virtual paths.
* **Mechanism:** If the kernel tries to resolve the path of a file that was injected by us, `nomount_handle_dpath` intercepts the output and returns the "Virtual Path" instead of the actual physical location (e.g. returning `/system/bin/su` instead of `/data/adb/modules/test/su`).
* **Integration:**

#### `fs/d_path.c`:

```diff
diff --git a/fs/d_path.c b/fs/d_path.c
--- a/fs/d_path.c
+++ b/fs/d_path.c
@@ -xxx,xx +xxx,xx @@ static void get_fs_root_rcu(struct fs_struct *fs, struct path *root)
} while (read_seqcount_retry(&fs->seq, seq));
}

+#ifdef CONFIG_NOMOUNT
+extern char *nomount_handle_dpath(const struct path *path, char *buf, int buflen);
+#endif
+
/**
* d_path - return the path of a dentry
* @path: path to report
@@ -xxx,x +xxx,xx @@ char *d_path(const struct path *path, char *buf, int buflen)

+#ifdef CONFIG_NOMOUNT
+ char *nm_path = nomount_handle_dpath(path, buf, buflen);
+ if (unlikely(nm_path)) {
+ return nm_path;
+ }
+#endif
+
/*
* We have various synthetic filesystems that never get mounted. On
* these filesystems dentries are never used for lookup purposes, and
```

---

## 4. Directory Listing
* **File:** `fs/readdir.c`
* **Hooks:** `iterate_dir`
* **Purpose:** Allow commands like `ls` or listing APIs to seamlessly see virtual files injected into legitimate system directories.
* **Mechanism:** Instead of manually manipulating userspace buffers in the `getdents` syscalls, NoMount now hooks directly into the directory iteration engine (`iterate_dir`). The wrapper acts as a smart proxy: it first allows the native filesystem to read the physical disk without interference. By tracking the directory offset (`ctx->pos`), NoMount detects when the native iteration reaches the End of File (EOF) or pauses. Once the physical files are fully processed, it seamlessly inject virtual entries using the kernel's native `dir_emit()` function.
* **Integration:**

#### `fs/readdir.c`:

```diff
diff --git a/fs/readdir.c b/fs/readdir.c
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -xx,xx +xx,xx @@
unsafe_copy_to_user(dst, src, len, label); \
} while (0)

+#ifdef CONFIG_NOMOUNT
+extern int nomount_handle_iterate_dir(struct file *file, struct dir_context *ctx);
+#endif

int iterate_dir(struct file *file, struct dir_context *ctx)
{
@@ -xx,xx +xx,xx @@ int iterate_dir(struct file *file, struct dir_context *ctx)
res = -ENOENT;
if (!IS_DEADDIR(inode)) {
ctx->pos = file->f_pos;
+#ifdef CONFIG_NOMOUNT
+ res = nomount_handle_iterate_dir(file, ctx);
+#else
if (shared)
res = file->f_op->iterate_shared(file, ctx);
else
res = file->f_op->iterate(file, ctx);
+#endif
file->f_pos = ctx->pos;
fsnotify_access(file);
file_accessed(file);
```

---

## 5. Metadata Spoofing (Stat & Mmap)
To be undetectable, the metadata of the files and file systems must match their virtual location.

* **File Attributes (`fs/stat.c`):**
* **Hook:** `vfs_getattr`
* **Mechanism:** A *Wrapper* pattern is used. The `nomount_handle_getattr` hook captures the native output of `vfs_getattr_nosec`. If the original read was successful, it overwrites the `inode` and `device id` (dev) in the `kstat` structure before returning it to the user.
* **Integration:**

#### `fs/stat.c`

```diff
diff --git a/fs/stat.c b/fs/stat.c
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -xxx,xx +xxx,xx @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
}
EXPORT_SYMBOL(vfs_getattr_nosec);

+#ifdef CONFIG_NOMOUNT
+extern int nomount_handle_getattr(int ret, const struct path *path, struct kstat *stat);
+#endif
+
/*
* vfs_getattr - Get the enhanced basic attributes of a file
* @path: The file of interest
@@ -xxx,xx +xxx,xx @@ int vfs_getattr(const struct path *path, struct kstat *stat,
retval = security_inode_getattr(path);
if (retval)
return retval;
+#ifdef CONFIG_NOMOUNT
+ return nomount_handle_getattr(vfs_getattr_nosec(path, stat, request_mask, query_flags), path, stat);
+#else
return vfs_getattr_nosec(path, stat, request_mask, query_flags);
+#endif
}
EXPORT_SYMBOL(vfs_getattr);

```

* **Memory Maps (`fs/proc/task_mmu.c`):**
* **Hook:** `show_map_vma`
* **Mechanism:** When a process reads `/proc/self/maps`, the kernel prints the loaded libraries into memory. The `nomount_spoof_mmap_metadata` hook replaces the raw device and inode just before they are printed to the `seq_file`.
* **Integration:**

#### `fs/proc/task_mmu.c`:

```diff
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -xxx,xx +xxx,xx @@ static void show_vma_header_prefix(struct seq_file *m,
seq_putc(m, ' ');
}

+#ifdef CONFIG_NOMOUNT
+extern bool nomount_spoof_mmap_metadata(struct inode *inode, dev_t *dev, unsigned long *ino);
+#endif
+
static void
show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
{
@@ -xxx,xx +xxx,xx @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
struct inode *inode = file_inode(vma->vm_file);
dev = inode->i_sb->s_dev;
ino = inode->i_ino;
+#ifdef CONFIG_NOMOUNT
+ nomount_spoof_mmap_metadata(inode, &dev, &ino);
+#endif
pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
}

```

* **Filesystem Attributes (`fs/statfs.c`):**
* **Hook:** `vfs_statfs`
* **Mechanism:** Alter the `kstatfs` structure. If an application requests partition metadata (e.g. to check if the file is on an `ext4` or `erofs` volume), the `nomount_spoof_statfs` hook injects the "Magic Number" (FS type) corresponding to the desired virtual partition.
* **Integration:**

#### `fs/statfs.c`:

```diff
diff --git a/fs/statfs.c b/fs/statfs.c
--- a/fs/statfs.c
+++ b/fs/statfs.c
@@ -xx,xx +xx,xx @@
#include <linux/compat.h>
#include "internal.h"

+#ifdef CONFIG_NOMOUNT
+extern void nomount_spoof_statfs(const struct path *path, struct kstatfs *buf);
+#endif
+
static int flags_by_mnt(int mnt_flags)
{
int flags = 0;
@@ -xxx,xx +xxx,xx @@ int vfs_statfs(const struct path *path, struct kstatfs *buf)
error = statfs_by_dentry(path->dentry, buf);
if (!error)
buf->f_flags = calculate_f_flags(path->mnt);
+#ifdef CONFIG_NOMOUNT
+ nomount_spoof_statfs(path, buf);
+#endif
return error;
}
EXPORT_SYMBOL(vfs_statfs);

```
---
Loading