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 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 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 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