tools/testing/selftests/filesystems/move_mount/move_mount_test.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/filesystems/move_mount/move_mount_test.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/filesystems/move_mount/move_mount_test.c
Extension
.c
Size
12234 bytes
Lines
493
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2026 Christian Brauner <brauner@kernel.org>

#define _GNU_SOURCE

#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <unistd.h>
#include <sys/syscall.h>

#include "../wrappers.h"
#include "../utils.h"
#include "../statmount/statmount.h"
#include "../../kselftest_harness.h"

#include <linux/stat.h>

#ifndef MOVE_MOUNT_BENEATH
#define MOVE_MOUNT_BENEATH 0x00000200
#endif

static uint64_t get_unique_mnt_id_fd(int fd)
{
	struct statx sx;
	int ret;

	ret = statx(fd, "", AT_EMPTY_PATH, STATX_MNT_ID_UNIQUE, &sx);
	if (ret)
		return 0;

	if (!(sx.stx_mask & STATX_MNT_ID_UNIQUE))
		return 0;

	return sx.stx_mnt_id;
}

/*
 * Create a locked overmount stack at /mnt_dir for testing MNT_LOCKED
 * transfer on non-rootfs mounts.
 *
 * Mounts tmpfs A at /mnt_dir, overmounts with tmpfs B, then enters a
 * new user+mount namespace where both become locked. Returns the exit
 * code to use on failure, or 0 on success.
 */
static int setup_locked_overmount(void)
{
	/* Isolate so mounts don't leak. */
	if (unshare(CLONE_NEWNS))
		return 1;
	if (mount("", "/", NULL, MS_REC | MS_PRIVATE, NULL))
		return 2;

	/*
	 * Create mounts while still in the initial user namespace so
	 * they become locked after the subsequent user namespace
	 * unshare.
	 */
	rmdir("/mnt_dir");
	if (mkdir("/mnt_dir", 0755))
		return 3;

	/* Mount tmpfs A */
	if (mount("tmpfs", "/mnt_dir", "tmpfs", 0, NULL))
		return 4;

	/* Overmount with tmpfs B */
	if (mount("tmpfs", "/mnt_dir", "tmpfs", 0, NULL))
		return 5;

	/*
	 * Create user+mount namespace. Mounts A and B become locked
	 * because they might be covering something that is not supposed
	 * to be revealed.
	 */
	if (setup_userns())
		return 6;

	/* Sanity check: B must be locked */
	if (!umount2("/mnt_dir", MNT_DETACH) || errno != EINVAL)
		return 7;

	return 0;
}

/*

Annotation

Implementation Notes