33 #ifndef HAVE_LINUX_LANDLOCK_H
41 #include <linux/landlock.h>
43 #ifndef landlock_create_ruleset
44 static inline int landlock_create_ruleset(
45 const struct landlock_ruleset_attr *
const attr,
const size_t size,
const __u32
flags)
47 long r = syscall(__NR_landlock_create_ruleset, attr, size,
flags);
53 #ifndef landlock_add_rule
54 static inline int landlock_add_rule(
const int ruleset_fd,
const enum landlock_rule_type rule_type,
55 const void *
const rule_attr,
const __u32
flags)
57 long r = syscall(__NR_landlock_add_rule, ruleset_fd, rule_type, rule_attr,
flags);
63 #ifndef landlock_restrict_self
64 static inline int landlock_restrict_self(
const int ruleset_fd,
const __u32
flags)
66 long r = syscall(__NR_landlock_restrict_self, ruleset_fd,
flags);
72 #ifndef LANDLOCK_ACCESS_FS_REFER
73 #define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)
76 #define _LANDLOCK_ACCESS_FS_WRITE \
77 (LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | \
78 LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_MAKE_CHAR | \
79 LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | \
80 LANDLOCK_ACCESS_FS_MAKE_SOCK | LANDLOCK_ACCESS_FS_MAKE_FIFO | \
81 LANDLOCK_ACCESS_FS_MAKE_BLOCK | LANDLOCK_ACCESS_FS_MAKE_SYM | \
82 LANDLOCK_ACCESS_FS_REFER)
84 #define _LANDLOCK_ACCESS_FS_READ (LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR)
86 #define _LANDLOCK_SURI_ACCESS_FS_WRITE \
87 (LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | \
88 LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_MAKE_SOCK)
90 struct landlock_ruleset {
92 struct landlock_ruleset_attr attr;
95 static inline struct landlock_ruleset *LandlockCreateRuleset(
void)
97 struct landlock_ruleset *ruleset =
SCCalloc(1,
sizeof(
struct landlock_ruleset));
98 if (ruleset == NULL) {
103 ruleset->attr.handled_access_fs =
104 _LANDLOCK_ACCESS_FS_READ | _LANDLOCK_ACCESS_FS_WRITE | LANDLOCK_ACCESS_FS_EXECUTE;
106 int abi = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
113 SCLogError(
"Landlock disabled: need Linux 5.19+ for file store support");
117 ruleset->attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_REFER;
121 ruleset->fd = landlock_create_ruleset(&ruleset->attr,
sizeof(ruleset->attr), 0);
122 if (ruleset->fd < 0) {
130 static inline void LandlockEnforceRuleset(
struct landlock_ruleset *ruleset)
132 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) {
133 SCLogError(
"Can't self restrict (prctl phase): %s", strerror(errno));
136 if (landlock_restrict_self(ruleset->fd, 0)) {
137 SCLogError(
"Can't self restrict (landlock phase): %s", strerror(errno));
141 static int LandlockSandboxingAddRule(
142 struct landlock_ruleset *ruleset,
const char *directory, uint64_t permission)
144 struct landlock_path_beneath_attr path_beneath = {
145 .allowed_access = permission & ruleset->attr.handled_access_fs,
148 int dir_fd = open(directory, O_PATH | O_CLOEXEC | O_DIRECTORY);
153 path_beneath.parent_fd = dir_fd;
155 if (landlock_add_rule(ruleset->fd, LANDLOCK_RULE_PATH_BENEATH, &path_beneath, 0)) {
156 SCLogError(
"Can't add write rule: %s", strerror(errno));
165 static inline void LandlockSandboxingWritePath(
166 struct landlock_ruleset *ruleset,
const char *directory)
168 if (LandlockSandboxingAddRule(ruleset, directory, _LANDLOCK_SURI_ACCESS_FS_WRITE) == 0) {
169 SCLogConfig(
"Added write permission to '%s'", directory);
173 static inline void LandlockSandboxingReadPath(
174 struct landlock_ruleset *ruleset,
const char *directory)
176 if (LandlockSandboxingAddRule(ruleset, directory, _LANDLOCK_ACCESS_FS_READ) == 0) {
177 SCLogConfig(
"Added read permission to '%s'", directory);
185 if (
SCConfGetBool(
"security.landlock.enabled", &conf_status) == 0) {
189 SCLogConfig(
"Landlock is not enabled in configuration");
192 struct landlock_ruleset *ruleset = LandlockCreateRuleset();
193 if (ruleset == NULL) {
194 SCLogError(
"Kernel does not support Landlock");
202 _LANDLOCK_SURI_ACCESS_FS_WRITE | _LANDLOCK_ACCESS_FS_READ);
206 _LANDLOCK_SURI_ACCESS_FS_WRITE | _LANDLOCK_ACCESS_FS_READ);
209 const char *pcap_file;
211 char *file_name =
SCStrdup(pcap_file);
212 if (file_name != NULL) {
214 if (stat(file_name, &statbuf) != -1) {
215 if (S_ISDIR(statbuf.st_mode)) {
216 LandlockSandboxingReadPath(ruleset, file_name);
218 LandlockSandboxingReadPath(ruleset, dirname(file_name));
229 if (file_name != NULL) {
230 LandlockSandboxingReadPath(ruleset, dirname(file_name));
236 if (file_name != NULL) {
237 LandlockSandboxingWritePath(ruleset, dirname(file_name));
242 const char *socketname;
245 char *file_name =
SCStrdup(socketname);
246 if (file_name != NULL) {
247 LandlockSandboxingWritePath(ruleset, dirname(file_name));
251 LandlockSandboxingWritePath(ruleset, LOCAL_STATE_DIR
"/run/suricata/");
254 LandlockSandboxingWritePath(ruleset, LOCAL_STATE_DIR
"/run/suricata/");
258 const char *rule_path;
260 LandlockSandboxingReadPath(ruleset, rule_path);
267 SCLogWarning(
"Invalid security.landlock.directories.read configuration section: "
268 "expected a list of directory names.");
272 LandlockSandboxingReadPath(ruleset, directory->
val);
279 SCLogWarning(
"Invalid security.landlock.directories.write configuration section: "
280 "expected a list of directory names.");
284 LandlockSandboxingWritePath(ruleset, directory->
val);
288 LandlockEnforceRuleset(ruleset);