xref: /freebsd/contrib/xz/src/common/my_landlock.h (revision 128836d304d93f2d00eb14069c27089ab46c38d4)
1 // SPDX-License-Identifier: 0BSD
2 
3 ///////////////////////////////////////////////////////////////////////////////
4 //
5 /// \file       my_landlock.h
6 /// \brief      Linux Landlock sandbox helper functions
7 //
8 //  Author:     Lasse Collin
9 //
10 ///////////////////////////////////////////////////////////////////////////////
11 
12 #ifndef MY_LANDLOCK_H
13 #define MY_LANDLOCK_H
14 
15 #include "sysdefs.h"
16 
17 #include <linux/landlock.h>
18 #include <sys/syscall.h>
19 #include <sys/prctl.h>
20 
21 
22 /// \brief      Initialize Landlock ruleset attributes to forbid everything
23 ///
24 /// The supported Landlock ABI is checked at runtime and only the supported
25 /// actions are forbidden in the attributes. Thus, if the attributes are
26 /// used with my_landlock_create_ruleset(), it shouldn't fail.
27 ///
28 /// \return     On success, the Landlock ABI version is returned (a positive
29 ///             integer). If Landlock isn't supported, -1 is returned.
30 static int
my_landlock_ruleset_attr_forbid_all(struct landlock_ruleset_attr * attr)31 my_landlock_ruleset_attr_forbid_all(struct landlock_ruleset_attr *attr)
32 {
33 	memzero(attr, sizeof(*attr));
34 
35 	const int abi_version = syscall(SYS_landlock_create_ruleset,
36 			(void *)NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
37 	if (abi_version <= 0)
38 		return -1;
39 
40 	// ABI 1 except the few at the end
41 	attr->handled_access_fs
42 			= LANDLOCK_ACCESS_FS_EXECUTE
43 			| LANDLOCK_ACCESS_FS_WRITE_FILE
44 			| LANDLOCK_ACCESS_FS_READ_FILE
45 			| LANDLOCK_ACCESS_FS_READ_DIR
46 			| LANDLOCK_ACCESS_FS_REMOVE_DIR
47 			| LANDLOCK_ACCESS_FS_REMOVE_FILE
48 			| LANDLOCK_ACCESS_FS_MAKE_CHAR
49 			| LANDLOCK_ACCESS_FS_MAKE_DIR
50 			| LANDLOCK_ACCESS_FS_MAKE_REG
51 			| LANDLOCK_ACCESS_FS_MAKE_SOCK
52 			| LANDLOCK_ACCESS_FS_MAKE_FIFO
53 			| LANDLOCK_ACCESS_FS_MAKE_BLOCK
54 			| LANDLOCK_ACCESS_FS_MAKE_SYM
55 #ifdef LANDLOCK_ACCESS_FS_REFER
56 			| LANDLOCK_ACCESS_FS_REFER // ABI 2
57 #endif
58 #ifdef LANDLOCK_ACCESS_FS_TRUNCATE
59 			| LANDLOCK_ACCESS_FS_TRUNCATE // ABI 3
60 #endif
61 #ifdef LANDLOCK_ACCESS_FS_IOCTL_DEV
62 			| LANDLOCK_ACCESS_FS_IOCTL_DEV // ABI 5
63 #endif
64 			;
65 
66 #ifdef LANDLOCK_ACCESS_NET_BIND_TCP
67 	// ABI 4
68 	attr->handled_access_net
69 			= LANDLOCK_ACCESS_NET_BIND_TCP
70 			| LANDLOCK_ACCESS_NET_CONNECT_TCP;
71 #endif
72 
73 #ifdef LANDLOCK_SCOPE_SIGNAL
74 	 // ABI 6
75 	 attr->scoped
76 			 = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
77 			 | LANDLOCK_SCOPE_SIGNAL;
78 #endif
79 
80 	// Disable flags that require a new ABI version.
81 	switch (abi_version) {
82 	case 1:
83 #ifdef LANDLOCK_ACCESS_FS_REFER
84 		attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_REFER;
85 #endif
86 		FALLTHROUGH;
87 
88 	case 2:
89 #ifdef LANDLOCK_ACCESS_FS_TRUNCATE
90 		attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_TRUNCATE;
91 #endif
92 		FALLTHROUGH;
93 
94 	case 3:
95 #ifdef LANDLOCK_ACCESS_NET_BIND_TCP
96 		attr->handled_access_net = 0;
97 #endif
98 		FALLTHROUGH;
99 
100 	case 4:
101 #ifdef LANDLOCK_ACCESS_FS_IOCTL_DEV
102 		attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV;
103 #endif
104 		FALLTHROUGH;
105 
106 	case 5:
107 #ifdef LANDLOCK_SCOPE_SIGNAL
108 		attr->scoped = 0;
109 #endif
110 		FALLTHROUGH;
111 
112 	default:
113 		// We only know about the features of the ABIs 1-6.
114 		break;
115 	}
116 
117 	return abi_version;
118 }
119 
120 
121 /// \brief      Wrapper for the landlock_create_ruleset(2) syscall
122 ///
123 /// Syscall wrappers provide argument type checking.
124 ///
125 /// \note       Remember to call `prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)` too!
126 static inline int
my_landlock_create_ruleset(const struct landlock_ruleset_attr * attr,size_t size,uint32_t flags)127 my_landlock_create_ruleset(const struct landlock_ruleset_attr *attr,
128 		size_t size, uint32_t flags)
129 {
130 	return syscall(SYS_landlock_create_ruleset, attr, size, flags);
131 }
132 
133 
134 /// \brief      Wrapper for the landlock_restrict_self(2) syscall
135 static inline int
my_landlock_restrict_self(int ruleset_fd,uint32_t flags)136 my_landlock_restrict_self(int ruleset_fd, uint32_t flags)
137 {
138 	return syscall(SYS_landlock_restrict_self, ruleset_fd, flags);
139 }
140 
141 #endif
142