summaryrefslogtreecommitdiff
path: root/src/landlock.c
blob: d3ddb4edb0445b185cd4327ad0c0ac9b6e6bf31e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
 * Copyright (c) 2021 Eugene Syromyatnikov <evgsyr@gmail.com>
 * All rights reserved.
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 */

#include "defs.h"

#include <linux/landlock.h>

#include "xlat/landlock_create_ruleset_flags.h"
#include "xlat/landlock_rule_types.h"
#include "xlat/landlock_ruleset_access_fs.h"

static void
print_landlock_ruleset_attr(struct tcb *tcp, const kernel_ulong_t addr,
			    const kernel_ulong_t size)
{
	struct landlock_ruleset_attr attr;

	if (size < offsetofend(typeof(attr), handled_access_fs)) {
		printaddr(addr);
		return;
	}

	if (umoven_or_printaddr(tcp, addr, MIN(size, sizeof(attr)), &attr))
		return;

	tprint_struct_begin();
	PRINT_FIELD_FLAGS(attr, handled_access_fs, landlock_ruleset_access_fs,
			  "LANDLOCK_ACCESS_FS_???");

	if (size > offsetofend(typeof(attr), handled_access_fs)) {
		tprint_arg_next();
		tprint_more_data_follows();
	}

	tprint_struct_end();
}

SYS_FUNC(landlock_create_ruleset)
{
	kernel_ulong_t attr = tcp->u_arg[0];
	kernel_ulong_t size = tcp->u_arg[1];
	unsigned int flags = tcp->u_arg[2];
	int fd_flag = flags & LANDLOCK_CREATE_RULESET_VERSION ? 0 : RVAL_FD;

	/* attr */
	print_landlock_ruleset_attr(tcp, attr, size);
	tprint_arg_next();

	/* size */
	PRINT_VAL_U(size);
	tprint_arg_next();

	/* flags */
	printflags(landlock_create_ruleset_flags, flags,
		   "LANDLOCK_CREATE_RULESET_???");

	return RVAL_DECODED | fd_flag;
}

static void
print_landlock_path_beneath_attr(struct tcb *tcp, const kernel_ulong_t addr)
{
	struct landlock_path_beneath_attr attr;

	if (umove_or_printaddr(tcp, addr, &attr))
		return;

	tprint_struct_begin();
	PRINT_FIELD_FLAGS(attr, allowed_access, landlock_ruleset_access_fs,
			  "LANDLOCK_ACCESS_FS_???");
	tprint_struct_next();
	PRINT_FIELD_FD(attr, parent_fd, tcp);
	tprint_struct_end();
}

SYS_FUNC(landlock_add_rule)
{
	unsigned int rule_type = tcp->u_arg[1];

	/* ruleset_fd */
	printfd(tcp, tcp->u_arg[0]);
	tprint_arg_next();

	/* rule_type */
	printxval(landlock_rule_types, rule_type, "LANDLOCK_RULE_???");
	tprint_arg_next();

	/* rule_attr */
	switch (rule_type) {
	case LANDLOCK_RULE_PATH_BENEATH:
		print_landlock_path_beneath_attr(tcp, tcp->u_arg[2]);
		break;

	default:
		printaddr(tcp->u_arg[2]);
	}
	tprint_arg_next();

	/* flags */
	PRINT_VAL_X((unsigned int) tcp->u_arg[3]);

	return RVAL_DECODED;
}

SYS_FUNC(landlock_restrict_self)
{
	/* ruleset_fd */
	printfd(tcp, tcp->u_arg[0]);
	tprint_arg_next();

	/* flags */
	PRINT_VAL_X((unsigned int) tcp->u_arg[1]);

	return RVAL_DECODED;
}