tools/testing/selftests/clone3/clone3_cap_checkpoint_restore.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/clone3/clone3_cap_checkpoint_restore.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/clone3/clone3_cap_checkpoint_restore.c
Extension
.c
Size
3647 bytes
Lines
165
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

/*
 * Based on Christian Brauner's clone3() example.
 * These tests are assuming to be running in the host's
 * PID namespace.
 */

/* capabilities related code based on selftests/bpf/test_verifier.c */

#define _GNU_SOURCE
#include <errno.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/capability.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sched.h>

#include "kselftest_harness.h"
#include "clone3_selftests.h"

static void child_exit(int ret)
{
	fflush(stdout);
	fflush(stderr);
	_exit(ret);
}

static int call_clone3_set_tid(struct __test_metadata *_metadata,
			       pid_t *set_tid, size_t set_tid_size)
{
	int status;
	pid_t pid = -1;

	struct __clone_args args = {
		.exit_signal = SIGCHLD,
		.set_tid = ptr_to_u64(set_tid),
		.set_tid_size = set_tid_size,
	};

	pid = sys_clone3(&args, sizeof(args));
	if (pid < 0) {
		TH_LOG("%s - Failed to create new process", strerror(errno));
		return -errno;
	}

	if (pid == 0) {
		TH_LOG("I am the child, my PID is %d (expected %d)", getpid(), set_tid[0]);

		if (set_tid[0] != getpid())
			child_exit(EXIT_FAILURE);
		child_exit(EXIT_SUCCESS);
	}

	TH_LOG("I am the parent (%d). My child's pid is %d", getpid(), pid);

	if (waitpid(pid, &status, 0) < 0) {
		TH_LOG("Child returned %s", strerror(errno));
		return -errno;
	}

	if (!WIFEXITED(status))
		return -1;

	return WEXITSTATUS(status);
}

static int test_clone3_set_tid(struct __test_metadata *_metadata,
			       pid_t *set_tid, size_t set_tid_size)
{
	int ret;

	TH_LOG("[%d] Trying clone3() with CLONE_SET_TID to %d", getpid(), set_tid[0]);
	ret = call_clone3_set_tid(_metadata, set_tid, set_tid_size);
	TH_LOG("[%d] clone3() with CLONE_SET_TID %d says:%d", getpid(), set_tid[0], ret);
	return ret;
}

static int set_capability(void)
{
	cap_value_t cap_values[] = {
		CAP_SETUID, CAP_SETGID, CAP_CHECKPOINT_RESTORE

Annotation

Implementation Notes