File Index
Files and directories
Sign in
FILE

wait-pipe-sandbox.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/landlock/wait-pipe-sandbox.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Write in a pipe, wait, sandbox itself, test sandboxing, and wait again.
  4 *
  5 * Used by audit_exec.flags from audit_test.c
  6 *
  7 * Copyright © 2024-2025 Microsoft Corporation
  8 */
  9
 10#define _GNU_SOURCE
 11#include <fcntl.h>
 12#include <linux/landlock.h>
 13#include <linux/prctl.h>
 14#include <signal.h>
 15#include <stdio.h>
 16#include <stdlib.h>
 17#include <sys/prctl.h>
 18#include <unistd.h>
 19
 20#include "wrappers.h"
 21
 22static int sync_with(int pipe_child, int pipe_parent)
 23{
 24	char buf;
 25
 26	/* Signals that we are waiting. */
 27	if (write(pipe_child, ".", 1) != 1) {
 28		perror("Failed to write to first argument");
 29		return 1;
 30	}
 31
 32	/* Waits for the parent do its test. */
 33	if (read(pipe_parent, &buf, 1) != 1) {
 34		perror("Failed to write to the second argument");
 35		return 1;
 36	}
 37
 38	return 0;
 39}
 40
 41int main(int argc, char *argv[])
 42{
 43	const struct landlock_ruleset_attr layer2 = {
 44		.handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR,
 45	};
 46	const struct landlock_ruleset_attr layer3 = {
 47		.scoped = LANDLOCK_SCOPE_SIGNAL,
 48	};
 49	int err, pipe_child, pipe_parent, ruleset_fd;
 50
 51	/* The first argument must be the file descriptor number of a pipe. */
 52	if (argc != 3) {
 53		fprintf(stderr, "Wrong number of arguments (not two)\n");
 54		return 1;
 55	}
 56
 57	pipe_child = atoi(argv[1]);
 58	pipe_parent = atoi(argv[2]);
 59	/* PR_SET_NO_NEW_PRIVS already set by parent. */
 60
 61	/* First step to test parent's layer1. */
 62	err = sync_with(pipe_child, pipe_parent);
 63	if (err)
 64		return err;
 65
 66	/* Tries to send a signal, denied by layer1. */
 67	if (!kill(getppid(), 0)) {
 68		fprintf(stderr, "Successfully sent a signal to the parent");
 69		return 1;
 70	}
 71
 72	/* Second step to test parent's layer1 and our layer2. */
 73	err = sync_with(pipe_child, pipe_parent);
 74	if (err)
 75		return err;
 76
 77	ruleset_fd = landlock_create_ruleset(&layer2, sizeof(layer2), 0);
 78	if (ruleset_fd < 0) {
 79		perror("Failed to create the layer2 ruleset");
 80		return 1;
 81	}
 82
 83	if (landlock_restrict_self(ruleset_fd, 0)) {
 84		perror("Failed to restrict self");
 85		return 1;
 86	}
 87	close(ruleset_fd);
 88
 89	/* Tries to send a signal, denied by layer1. */
 90	if (!kill(getppid(), 0)) {
 91		fprintf(stderr, "Successfully sent a signal to the parent");
 92		return 1;
 93	}
 94
 95	/* Tries to open ., denied by layer2. */
 96	if (open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC) >= 0) {
 97		fprintf(stderr, "Successfully opened /");
 98		return 1;
 99	}
100
101	/* Third step to test our layer2 and layer3. */
102	err = sync_with(pipe_child, pipe_parent);
103	if (err)
104		return err;
105
106	ruleset_fd = landlock_create_ruleset(&layer3, sizeof(layer3), 0);
107	if (ruleset_fd < 0) {
108		perror("Failed to create the layer3 ruleset");
109		return 1;
110	}
111
112	if (landlock_restrict_self(ruleset_fd, 0)) {
113		perror("Failed to restrict self");
114		return 1;
115	}
116	close(ruleset_fd);
117
118	/* Tries to open ., denied by layer2. */
119	if (open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC) >= 0) {
120		fprintf(stderr, "Successfully opened /");
121		return 1;
122	}
123
124	/* Tries to send a signal, denied by layer3. */
125	if (!kill(getppid(), 0)) {
126		fprintf(stderr, "Successfully sent a signal to the parent");
127		return 1;
128	}
129
130	return 0;
131}
~/ Read-only file preview.