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