• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NVIDIA / nvrc / 20381075488

19 Dec 2025 07:59PM UTC coverage: 89.348% (+8.9%) from 80.415%
20381075488

Pull #85

github

web-flow
Merge 40e9e3e58 into 2295d6b0d
Pull Request #85: Update coverage.yaml to use cargo-llvm-cov

1233 of 1380 relevant lines covered (89.35%)

4.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.57
/src/mount.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// Copyright (c) NVIDIA CORPORATION
3

4
//! Filesystem setup for the minimal init environment.
5
//!
6
//! Coverage note: ~80% is the safe maximum. `setup()` mounts filesystems
7
//! and can only be tested in ephemeral VMs.
8

9
use crate::coreutils::{ln, mknod};
10
use anyhow::{Context, Result};
11
use nix::mount::{self, MsFlags};
12
use nix::sys::stat;
13
use std::fs;
14
use std::path::Path;
15

16
/// Check if path is mounted (exact match on mountpoint, not substring).
17
/// Uses exact field matching to avoid false positives like "/dev" matching "/dev/pts".
18
fn is_mounted_in(mounts: &str, path: &str) -> bool {
10✔
19
    mounts
10✔
20
        .lines()
10✔
21
        .any(|line| line.split_whitespace().nth(1) == Some(path))
32✔
22
}
10✔
23

24
/// Check if a filesystem type is available in the kernel.
25
/// Some filesystems (securityfs, efivarfs) may not be present in all kernels.
26
fn fs_available_in(filesystems: &str, fs: &str) -> bool {
7✔
27
    filesystems.lines().any(|line| line.contains(fs))
41✔
28
}
7✔
29

30
/// Mount filesystem only if not already mounted.
31
/// Idempotent: safe to call multiple times. Uses pre-read mounts snapshot
32
/// to avoid TOCTOU races between check and mount.
33
fn mount_cached(
3✔
34
    mounts: &str,
3✔
35
    source: &str,
3✔
36
    target: &str,
3✔
37
    fstype: &str,
3✔
38
    flags: MsFlags,
3✔
39
    data: Option<&str>,
3✔
40
) -> Result<()> {
3✔
41
    if !is_mounted_in(mounts, target) {
3✔
42
        mount::mount(Some(source), target, Some(fstype), flags, data)
1✔
43
            .with_context(|| format!("Failed to mount {source} on {target}"))?;
1✔
44
    }
2✔
45
    Ok(())
2✔
46
}
3✔
47

48
/// Remount a filesystem as read-only.
49
/// Security hardening: prevents writes to the root filesystem after init,
50
/// reducing attack surface in the confidential VM.
51
pub fn readonly(target: &str) -> Result<()> {
1✔
52
    let flags = MsFlags::MS_NOSUID | MsFlags::MS_NODEV | MsFlags::MS_RDONLY | MsFlags::MS_REMOUNT;
1✔
53
    mount::mount(None::<&str>, target, None::<&str>, flags, None::<&str>)
1✔
54
        .with_context(|| format!("Failed to remount {target} readonly"))
1✔
55
}
1✔
56

57
/// Mount filesystem only if the fstype is available AND the target exists.
58
/// Used for optional filesystems like securityfs and efivarfs that may not
59
/// be present on all systems or kernel configurations.
60
fn mount_if_cached(
3✔
61
    mounts: &str,
3✔
62
    filesystems: &str,
3✔
63
    fstype: &str,
3✔
64
    source: &str,
3✔
65
    target: &str,
3✔
66
    flags: MsFlags,
3✔
67
    data: Option<&str>,
3✔
68
) -> Result<()> {
3✔
69
    if fs_available_in(filesystems, fstype) && Path::new(target).exists() {
3✔
70
        mount_cached(mounts, source, target, fstype, flags, data)?;
1✔
71
    }
2✔
72
    Ok(())
3✔
73
}
3✔
74

75
/// Create /dev symlinks pointing to /proc entries.
76
/// Standard Unix convention: /dev/stdin, /dev/stdout, /dev/stderr should
77
/// exist for programs that expect them. /dev/fd provides access to open
78
/// file descriptors via /proc/self/fd.
79
fn proc_symlinks() -> Result<()> {
1✔
80
    for (src, dst) in [
5✔
81
        ("/proc/kcore", "/dev/core"),
1✔
82
        ("/proc/self/fd", "/dev/fd"),
1✔
83
        ("/proc/self/fd/0", "/dev/stdin"),
1✔
84
        ("/proc/self/fd/1", "/dev/stdout"),
1✔
85
        ("/proc/self/fd/2", "/dev/stderr"),
1✔
86
    ] {
87
        ln(src, dst)?;
5✔
88
    }
89
    Ok(())
1✔
90
}
1✔
91

92
/// Create essential /dev device nodes for basic I/O.
93
/// These character devices are fundamental Unix primitives:
94
/// - /dev/null: discard output, read returns EOF
95
/// - /dev/zero: infinite stream of zeros
96
/// - /dev/random, /dev/urandom: cryptographic randomness
97
fn device_nodes() -> Result<()> {
1✔
98
    for (path, minor) in [
4✔
99
        ("/dev/null", 3u64),
1✔
100
        ("/dev/zero", 5u64),
1✔
101
        ("/dev/random", 8u64),
1✔
102
        ("/dev/urandom", 9u64),
1✔
103
    ] {
104
        mknod(path, stat::SFlag::S_IFCHR, 1, minor)?; // major 1 = memory devices
4✔
105
    }
106
    Ok(())
1✔
107
}
1✔
108

109
/// Set up the minimal filesystem hierarchy required for GPU initialization.
110
/// Creates /proc, /dev, /sys, /run, /tmp mounts and essential device nodes.
111
/// Snapshot-based: reads mount state once to avoid TOCTOU races.
112
pub fn setup() -> Result<()> {
×
113
    // Snapshot mount state once - consistent view, no TOCTOU
114
    let mounts = fs::read_to_string("/proc/mounts").unwrap_or_default();
×
115
    let filesystems = fs::read_to_string("/proc/filesystems").unwrap_or_default();
×
116

117
    let common = MsFlags::MS_NOSUID | MsFlags::MS_NOEXEC | MsFlags::MS_NODEV | MsFlags::MS_RELATIME;
×
118
    mount_cached(&mounts, "proc", "/proc", "proc", common, None)?;
×
119
    let dev_flags = MsFlags::MS_NOSUID | MsFlags::MS_NOEXEC | MsFlags::MS_RELATIME;
×
120
    mount_cached(
×
121
        &mounts,
×
122
        "dev",
×
123
        "/dev",
×
124
        "devtmpfs",
×
125
        dev_flags,
×
126
        Some("mode=0755"),
×
127
    )?;
×
128
    mount_cached(&mounts, "sysfs", "/sys", "sysfs", common, None)?;
×
129
    mount_cached(&mounts, "run", "/run", "tmpfs", common, Some("mode=0755"))?;
×
130
    let tmp_flags = MsFlags::MS_NOSUID | MsFlags::MS_NODEV | MsFlags::MS_RELATIME;
×
131
    mount_cached(&mounts, "tmpfs", "/tmp", "tmpfs", tmp_flags, None)?;
×
132
    mount_if_cached(
×
133
        &mounts,
×
134
        &filesystems,
×
135
        "securityfs",
×
136
        "securityfs",
×
137
        "/sys/kernel/security",
×
138
        common,
×
139
        None,
×
140
    )?;
×
141
    mount_if_cached(
×
142
        &mounts,
×
143
        &filesystems,
×
144
        "efivarfs",
×
145
        "efivarfs",
×
146
        "/sys/firmware/efi/efivars",
×
147
        common,
×
148
        None,
×
149
    )?;
×
150
    proc_symlinks()?;
×
151
    device_nodes()?;
×
152
    Ok(())
×
153
}
×
154

155
#[cfg(test)]
156
mod tests {
157
    use super::*;
158
    use crate::test_utils::require_root;
159
    use std::fs;
160

161
    // === Safe parsing function tests ===
162

163
    #[test]
164
    fn test_is_mounted_in() {
1✔
165
        let mounts = fs::read_to_string("/proc/mounts").unwrap();
1✔
166
        assert!(is_mounted_in(&mounts, "/"));
1✔
167
        assert!(!is_mounted_in(&mounts, "/nonexistent"));
1✔
168
    }
1✔
169

170
    #[test]
171
    fn test_is_mounted_exact_match() {
1✔
172
        // /dev/pts mounted should NOT match /dev (substring matching bug fix)
173
        let mounts = "devpts /dev/pts devpts rw 0 0\ntmpfs /tmp tmpfs rw 0 0\n";
1✔
174
        assert!(!is_mounted_in(mounts, "/dev"));
1✔
175
        assert!(is_mounted_in(mounts, "/dev/pts"));
1✔
176
        assert!(is_mounted_in(mounts, "/tmp"));
1✔
177
    }
1✔
178

179
    #[test]
180
    fn test_is_mounted_empty() {
1✔
181
        assert!(!is_mounted_in("", "/"));
1✔
182
        assert!(!is_mounted_in("", "/dev"));
1✔
183
    }
1✔
184

185
    #[test]
186
    fn test_fs_available_in() {
1✔
187
        let filesystems = fs::read_to_string("/proc/filesystems").unwrap();
1✔
188
        assert!(fs_available_in(&filesystems, "proc"));
1✔
189
        assert!(fs_available_in(&filesystems, "sysfs"));
1✔
190
        assert!(!fs_available_in(&filesystems, "nonexistent_fs"));
1✔
191
    }
1✔
192

193
    #[test]
194
    fn test_fs_available_empty() {
1✔
195
        assert!(!fs_available_in("", "proc"));
1✔
196
    }
1✔
197

198
    // === mount_cached tests (safe: no-op when already mounted) ===
199

200
    #[test]
201
    fn test_mount_cached_already_mounted() {
1✔
202
        // When target is already in mounts, mount_cached is a no-op
203
        let mounts = "proc /proc proc rw 0 0\n";
1✔
204
        let result = mount_cached(mounts, "proc", "/proc", "proc", MsFlags::empty(), None);
1✔
205
        assert!(result.is_ok());
1✔
206
    }
1✔
207

208
    // === mount_if_cached tests (safe: no-op when conditions not met) ===
209

210
    #[test]
211
    fn test_mount_if_cached_fs_not_available() {
1✔
212
        // When filesystem is not available, should be no-op
213
        let mounts = "";
1✔
214
        let filesystems = "nodev tmpfs\n";
1✔
215
        let result = mount_if_cached(
1✔
216
            mounts,
1✔
217
            filesystems,
1✔
218
            "nonexistent_fs",
1✔
219
            "src",
1✔
220
            "/tmp", // exists but fs not available
1✔
221
            MsFlags::empty(),
1✔
222
            None,
1✔
223
        );
224
        assert!(result.is_ok());
1✔
225
    }
1✔
226

227
    #[test]
228
    fn test_mount_if_cached_target_not_exists() {
1✔
229
        // When target path doesn't exist, should be no-op
230
        let mounts = "";
1✔
231
        let filesystems = "nodev tmpfs\n";
1✔
232
        let result = mount_if_cached(
1✔
233
            mounts,
1✔
234
            filesystems,
1✔
235
            "tmpfs",
1✔
236
            "src",
1✔
237
            "/nonexistent/path",
1✔
238
            MsFlags::empty(),
1✔
239
            None,
1✔
240
        );
241
        assert!(result.is_ok());
1✔
242
    }
1✔
243

244
    #[test]
245
    fn test_mount_if_cached_already_mounted() {
1✔
246
        // When already mounted, should be no-op
247
        let mounts = "tmpfs /tmp tmpfs rw 0 0\n";
1✔
248
        let filesystems = "nodev tmpfs\n";
1✔
249
        let result = mount_if_cached(
1✔
250
            mounts,
1✔
251
            filesystems,
1✔
252
            "tmpfs",
1✔
253
            "tmpfs",
1✔
254
            "/tmp",
1✔
255
            MsFlags::empty(),
1✔
256
            None,
1✔
257
        );
258
        assert!(result.is_ok());
1✔
259
    }
1✔
260

261
    // === Error path tests (safe: mount fails, no changes made) ===
262

263
    #[test]
264
    fn test_mount_cached_fails_nonexistent_target() {
1✔
265
        let mounts = "";
1✔
266
        let err = mount_cached(
1✔
267
            mounts,
1✔
268
            "tmpfs",
1✔
269
            "/nonexistent/mount/point",
1✔
270
            "tmpfs",
1✔
271
            MsFlags::empty(),
1✔
272
            None,
1✔
273
        )
274
        .unwrap_err();
1✔
275
        // Should contain the mount target in error context
276
        assert!(
1✔
277
            err.to_string().contains("/nonexistent/mount/point"),
1✔
278
            "error should mention the path: {}",
×
279
            err
280
        );
281
    }
1✔
282

283
    #[test]
284
    fn test_readonly_fails_nonexistent() {
1✔
285
        let err = readonly("/nonexistent/path").unwrap_err();
1✔
286
        // Should contain the path in error context
287
        assert!(
1✔
288
            err.to_string().contains("/nonexistent/path"),
1✔
289
            "error should mention the path: {}",
×
290
            err
291
        );
292
    }
1✔
293

294
    // === Functions that need root but are safe ===
295

296
    #[test]
297
    fn test_proc_symlinks() {
1✔
298
        // These symlinks already exist on any Linux system.
299
        // ln() is idempotent - returns Ok if already correct.
300
        require_root();
1✔
301
        assert!(proc_symlinks().is_ok());
1✔
302
    }
1✔
303

304
    #[test]
305
    fn test_device_nodes() {
1✔
306
        // mknod() removes existing nodes first, then recreates.
307
        // Safe: just recreates /dev/null, /dev/zero, etc. with same params.
308
        require_root();
1✔
309
        assert!(device_nodes().is_ok());
1✔
310
    }
1✔
311

312
    // === setup() is dangerous - mounts filesystems ===
313
    // Only test in ephemeral VMs, not on development machines.
314
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc