34 #ifndef HAVE_LINUX_LANDLOCK_H
42 #include <linux/landlock.h>
44 #ifndef landlock_create_ruleset
45 static inline int landlock_create_ruleset(
46 const struct landlock_ruleset_attr *
const attr,
const size_t size,
const __u32
flags)
48 long r = syscall(__NR_landlock_create_ruleset, attr, size,
flags);
54 #ifndef landlock_add_rule
55 static inline int landlock_add_rule(
const int ruleset_fd,
const enum landlock_rule_type rule_type,
56 const void *
const rule_attr,
const __u32
flags)
58 long r = syscall(__NR_landlock_add_rule, ruleset_fd, rule_type, rule_attr,
flags);
64 #ifndef landlock_restrict_self
65 static inline int landlock_restrict_self(
const int ruleset_fd,
const __u32
flags)
67 long r = syscall(__NR_landlock_restrict_self, ruleset_fd,
flags);
73 #ifndef LANDLOCK_ACCESS_FS_REFER
74 #define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)
77 #define _LANDLOCK_ACCESS_FS_WRITE \
78 (LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | \
79 LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_MAKE_CHAR | \
80 LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | \
81 LANDLOCK_ACCESS_FS_MAKE_SOCK | LANDLOCK_ACCESS_FS_MAKE_FIFO | \
82 LANDLOCK_ACCESS_FS_MAKE_BLOCK | LANDLOCK_ACCESS_FS_MAKE_SYM | \
83 LANDLOCK_ACCESS_FS_REFER)
85 #define _LANDLOCK_ACCESS_FS_READ (LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR)
87 #define _LANDLOCK_SURI_ACCESS_FS_WRITE \
88 (LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | \
89 LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_MAKE_SOCK)
91 struct landlock_ruleset {
93 struct landlock_ruleset_attr attr;
96 static inline struct landlock_ruleset *LandlockCreateRuleset(
void)
98 struct landlock_ruleset *ruleset =
SCCalloc(1,
sizeof(
struct landlock_ruleset));
99 if (ruleset == NULL) {
104 ruleset->attr.handled_access_fs =
105 _LANDLOCK_ACCESS_FS_READ | _LANDLOCK_ACCESS_FS_WRITE | LANDLOCK_ACCESS_FS_EXECUTE;
107 int abi = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
114 SCLogError(
"Landlock disabled: need Linux 5.19+ for file store support");
118 ruleset->attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_REFER;
122 ruleset->fd = landlock_create_ruleset(&ruleset->attr,
sizeof(ruleset->attr), 0);
123 if (ruleset->fd < 0) {
131 static inline void LandlockEnforceRuleset(
struct landlock_ruleset *ruleset)
133 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) {
134 SCLogError(
"Can't self restrict (prctl phase): %s", strerror(errno));
137 if (landlock_restrict_self(ruleset->fd, 0)) {
138 SCLogError(
"Can't self restrict (landlock phase): %s", strerror(errno));
142 static int LandlockSandboxingAddRule(
143 struct landlock_ruleset *ruleset,
const char *directory, uint64_t permission)
145 struct landlock_path_beneath_attr path_beneath = {
146 .allowed_access = permission & ruleset->attr.handled_access_fs,
149 int dir_fd = open(directory, O_PATH | O_CLOEXEC | O_DIRECTORY);
154 path_beneath.parent_fd = dir_fd;
156 if (landlock_add_rule(ruleset->fd, LANDLOCK_RULE_PATH_BENEATH, &path_beneath, 0)) {
157 SCLogError(
"Can't add write rule: %s", strerror(errno));
166 static inline void LandlockSandboxingWritePath(
167 struct landlock_ruleset *ruleset,
const char *directory)
169 if (LandlockSandboxingAddRule(ruleset, directory, _LANDLOCK_SURI_ACCESS_FS_WRITE) == 0) {
170 SCLogConfig(
"Added write permission to '%s'", directory);
174 static inline void LandlockSandboxingReadPath(
175 struct landlock_ruleset *ruleset,
const char *directory)
177 if (LandlockSandboxingAddRule(ruleset, directory, _LANDLOCK_ACCESS_FS_READ) == 0) {
178 SCLogConfig(
"Added read permission to '%s'", directory);
186 if (
ConfGetBool(
"security.landlock.enabled", &conf_status) == 0) {
190 SCLogConfig(
"Landlock is not enabled in configuration");
193 struct landlock_ruleset *ruleset = LandlockCreateRuleset();
194 if (ruleset == NULL) {
195 SCLogError(
"Kernel does not support Landlock");
203 _LANDLOCK_SURI_ACCESS_FS_WRITE | _LANDLOCK_ACCESS_FS_READ);
207 _LANDLOCK_SURI_ACCESS_FS_WRITE | _LANDLOCK_ACCESS_FS_READ);
210 const char *pcap_file;
211 if (
ConfGet(
"pcap-file.file", &pcap_file) == 1) {
212 char *file_name =
SCStrdup(pcap_file);
213 if (file_name != NULL) {
215 if (stat(file_name, &statbuf) != -1) {
216 if (S_ISDIR(statbuf.st_mode)) {
217 LandlockSandboxingReadPath(ruleset, file_name);
219 LandlockSandboxingReadPath(ruleset, dirname(file_name));
230 if (file_name != NULL) {
231 LandlockSandboxingReadPath(ruleset, dirname(file_name));
237 if (file_name != NULL) {
238 LandlockSandboxingWritePath(ruleset, dirname(file_name));
243 const char *socketname;
244 if (
ConfGet(
"unix-command.filename", &socketname) == 1) {
246 char *file_name =
SCStrdup(socketname);
247 if (file_name != NULL) {
248 LandlockSandboxingWritePath(ruleset, dirname(file_name));
252 LandlockSandboxingWritePath(ruleset, LOCAL_STATE_DIR
"/run/suricata/");
255 LandlockSandboxingWritePath(ruleset, LOCAL_STATE_DIR
"/run/suricata/");
259 const char *rule_path;
260 if (
ConfGet(
"default-rule-path", &rule_path) == 1 && rule_path) {
261 LandlockSandboxingReadPath(ruleset, rule_path);
268 SCLogWarning(
"Invalid security.landlock.directories.read configuration section: "
269 "expected a list of directory names.");
273 LandlockSandboxingReadPath(ruleset, directory->
val);
280 SCLogWarning(
"Invalid security.landlock.directories.write configuration section: "
281 "expected a list of directory names.");
285 LandlockSandboxingWritePath(ruleset, directory->
val);
289 LandlockEnforceRuleset(ruleset);