32 #ifndef HAVE_LINUX_LANDLOCK_H
40 #include <linux/landlock.h>
42 #ifndef landlock_create_ruleset
43 static inline int landlock_create_ruleset(
44 const struct landlock_ruleset_attr *
const attr,
const size_t size,
const __u32
flags)
46 return syscall(__NR_landlock_create_ruleset, attr, size,
flags);
50 #ifndef landlock_add_rule
51 static inline int landlock_add_rule(
const int ruleset_fd,
const enum landlock_rule_type rule_type,
52 const void *
const rule_attr,
const __u32
flags)
54 return syscall(__NR_landlock_add_rule, ruleset_fd, rule_type, rule_attr,
flags);
58 #ifndef landlock_restrict_self
59 static inline int landlock_restrict_self(
const int ruleset_fd,
const __u32
flags)
61 return syscall(__NR_landlock_restrict_self, ruleset_fd,
flags);
65 #ifndef LANDLOCK_ACCESS_FS_REFER
66 #define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)
69 #define _LANDLOCK_ACCESS_FS_WRITE \
70 (LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | \
71 LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_MAKE_CHAR | \
72 LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | \
73 LANDLOCK_ACCESS_FS_MAKE_SOCK | LANDLOCK_ACCESS_FS_MAKE_FIFO | \
74 LANDLOCK_ACCESS_FS_MAKE_BLOCK | LANDLOCK_ACCESS_FS_MAKE_SYM | \
75 LANDLOCK_ACCESS_FS_REFER)
77 #define _LANDLOCK_ACCESS_FS_READ (LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR)
79 #define _LANDLOCK_SURI_ACCESS_FS_WRITE \
80 (LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | \
81 LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_MAKE_SOCK)
83 struct landlock_ruleset {
85 struct landlock_ruleset_attr attr;
88 static inline struct landlock_ruleset *LandlockCreateRuleset(
void)
90 struct landlock_ruleset *ruleset =
SCCalloc(1,
sizeof(
struct landlock_ruleset));
91 if (ruleset == NULL) {
96 ruleset->attr.handled_access_fs =
97 _LANDLOCK_ACCESS_FS_READ | _LANDLOCK_ACCESS_FS_WRITE | LANDLOCK_ACCESS_FS_EXECUTE;
99 int abi = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
106 SCLogError(
"Landlock disabled: need Linux 5.19+ for file store support");
110 ruleset->attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_REFER;
114 ruleset->fd = landlock_create_ruleset(&ruleset->attr,
sizeof(ruleset->attr), 0);
115 if (ruleset->fd < 0) {
123 static inline void LandlockEnforceRuleset(
struct landlock_ruleset *ruleset)
125 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) {
126 SCLogError(
"Can't self restrict (prctl phase): %s", strerror(errno));
129 if (landlock_restrict_self(ruleset->fd, 0)) {
130 SCLogError(
"Can't self restrict (landlock phase): %s", strerror(errno));
134 static int LandlockSandboxingAddRule(
135 struct landlock_ruleset *ruleset,
const char *directory, uint64_t permission)
137 struct landlock_path_beneath_attr path_beneath = {
138 .allowed_access = permission & ruleset->attr.handled_access_fs,
141 int dir_fd = open(directory, O_PATH | O_CLOEXEC | O_DIRECTORY);
146 path_beneath.parent_fd = dir_fd;
148 if (landlock_add_rule(ruleset->fd, LANDLOCK_RULE_PATH_BENEATH, &path_beneath, 0)) {
149 SCLogError(
"Can't add write rule: %s", strerror(errno));
158 static inline void LandlockSandboxingWritePath(
159 struct landlock_ruleset *ruleset,
const char *directory)
161 if (LandlockSandboxingAddRule(ruleset, directory, _LANDLOCK_SURI_ACCESS_FS_WRITE) == 0) {
162 SCLogConfig(
"Added write permission to '%s'", directory);
166 static inline void LandlockSandboxingReadPath(
167 struct landlock_ruleset *ruleset,
const char *directory)
169 if (LandlockSandboxingAddRule(ruleset, directory, _LANDLOCK_ACCESS_FS_READ) == 0) {
170 SCLogConfig(
"Added read permission to '%s'", directory);
178 if (
ConfGetBool(
"security.landlock.enabled", &conf_status) == 0) {
182 SCLogConfig(
"Landlock is not enabled in configuration");
185 struct landlock_ruleset *ruleset = LandlockCreateRuleset();
186 if (ruleset == NULL) {
187 SCLogError(
"Kernel does not support Landlock");
195 _LANDLOCK_SURI_ACCESS_FS_WRITE | _LANDLOCK_ACCESS_FS_READ);
198 const char *pcap_file;
199 if (
ConfGet(
"pcap-file.file", &pcap_file) == 1) {
200 char *file_name =
SCStrdup(pcap_file);
201 if (file_name != NULL) {
203 if (stat(file_name, &statbuf) != -1) {
204 if (S_ISDIR(statbuf.st_mode)) {
205 LandlockSandboxingReadPath(ruleset, file_name);
207 LandlockSandboxingReadPath(ruleset, dirname(file_name));
218 if (file_name != NULL) {
219 LandlockSandboxingReadPath(ruleset, dirname(file_name));
225 if (file_name != NULL) {
226 LandlockSandboxingWritePath(ruleset, dirname(file_name));
231 const char *socketname;
232 if (
ConfGet(
"unix-command.filename", &socketname) == 1) {
234 char *file_name =
SCStrdup(socketname);
235 if (file_name != NULL) {
236 LandlockSandboxingWritePath(ruleset, dirname(file_name));
240 LandlockSandboxingWritePath(ruleset, LOCAL_STATE_DIR
"/run/suricata/");
243 LandlockSandboxingWritePath(ruleset, LOCAL_STATE_DIR
"/run/suricata/");
247 const char *rule_path;
248 if (
ConfGet(
"default-rule-path", &rule_path) == 1 && rule_path) {
249 LandlockSandboxingReadPath(ruleset, rule_path);
256 SCLogWarning(
"Invalid security.landlock.directories.read configuration section: "
257 "expected a list of directory names.");
261 LandlockSandboxingReadPath(ruleset, directory->
val);
268 SCLogWarning(
"Invalid security.landlock.directories.write configuration section: "
269 "expected a list of directory names.");
273 LandlockSandboxingWritePath(ruleset, directory->
val);
277 LandlockEnforceRuleset(ruleset);