0 /* See LICENSE for license details. */

1 #include "sandbox.h"

2 #include <unistd.h>

3 #include <stdio.h>

4

5 #ifndef NO_SANDBOX

6

7 #ifdef __OpenBSD__

8 #define SANDBOXED

9 int

10 sandbox_start()

11 {

12 unveil("download", "rwc");

13 unveil(NULL, NULL);

14 pledge("stdio inet rpath wpath cpath", NULL);

15 return 0;

16 }

17 #endif

18

19 #ifdef __linux__

20 #define SANDBOXED

21 #include <sys/syscall.h>

22 #include <unistd.h>

23 #include <stdio.h>

24 #include <fcntl.h>

25 #include <string.h>

26 #include <errno.h>

27 #include <stddef.h>

28 #include <stdint.h>

29 #include <sys/prctl.h>

30 #include <linux/seccomp.h>

31 #include <linux/filter.h>

32 #include <linux/unistd.h>

33 long syscall(long number, ...); /* fix warning */

34

35 #if ENABLE_LANDLOCK || \

36 (!defined(DISABLE_LANDLOCK) && __has_include(<linux/landlock.h>))

37 #include <linux/landlock.h>

38 #define ENABLE_LANDLOCK

39 #endif

40

41 #define SC_ALLOW_(nr) \

42 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, nr, 0, 1), \

43 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)

44 #define SC_ALLOW(nr) \

45 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_##nr, 0, 1), \

46 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)

47 #define SC_ALLOW_ARG(_nr, _arg, _val) \

48 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (_nr), 0, 6), \

49 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \

50 offsetof(struct seccomp_data, args[(_arg)]) + SC_ARG_LO), \

51 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, \

52 ((_val) & 0xffffffff), 0, 3), \

53 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \

54 offsetof(struct seccomp_data, args[(_arg)]) + SC_ARG_HI), \

55 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, \

56 (((uint32_t)((uint64_t)(_val) >> 32)) & 0xffffffff), 0, 1), \

57 BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW), \

58 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \

59 offsetof(struct seccomp_data, nr))

60

61 struct sock_filter filter[] = {

62 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,

63 (offsetof(struct seccomp_data, arch))),

64 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,

65 (offsetof(struct seccomp_data, nr))),

66 SC_ALLOW(fstat),

67 SC_ALLOW(stat),

68 SC_ALLOW(setsockopt),

69 SC_ALLOW(accept),

70 SC_ALLOW(listen),

71 SC_ALLOW(bind),

72 SC_ALLOW(mkdir),

73 SC_ALLOW(read),

74 SC_ALLOW(write),

75 SC_ALLOW(readv),

76 SC_ALLOW(writev),

77 SC_ALLOW(creat),

78 SC_ALLOW(sendfile),

79 SC_ALLOW(open),

80 SC_ALLOW(openat),

81 SC_ALLOW(ioctl),

82 SC_ALLOW(close),

83 SC_ALLOW(exit),

84 SC_ALLOW(exit_group),

85 SC_ALLOW(futex),

86 SC_ALLOW(newfstatat),

87 SC_ALLOW(fcntl),

88 SC_ALLOW(lseek),

89 SC_ALLOW(mprotect),

90 SC_ALLOW(pread64),

91 SC_ALLOW(sendto),

92 SC_ALLOW(recvfrom),

93 SC_ALLOW(socket),

94 SC_ALLOW(getsockopt),

95 SC_ALLOW(poll),

96 SC_ALLOW(mmap),

97 SC_ALLOW(munmap),

98 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),

99 };

100

101 #ifdef ENABLE_LANDLOCK

102

103 static int

104 landlock_create_ruleset(const struct landlock_ruleset_attr *attr,

105 size_t size, uint32_t flags)

106 {

107 return syscall(__NR_landlock_create_ruleset, attr, size, flags);

108 }

109

110 static int

111 landlock_add_rule(int ruleset_fd, enum landlock_rule_type type,

112 const void *attr, uint32_t flags)

113 {

114 return syscall(__NR_landlock_add_rule, ruleset_fd, type, attr, flags);

115 }

116

117 static int

118 landlock_restrict_self(int ruleset_fd, __u32 flags)

119 {

120 return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);

121 }

122

123 int

124 landlock_unveil(int landlock_fd, int fd, int perms)

125 {

126 int ret, err;

127 struct landlock_path_beneath_attr attr = {0};

128 attr.allowed_access = perms;

129 attr.parent_fd = fd;

130

131 ret = landlock_add_rule(landlock_fd,

132 LANDLOCK_RULE_PATH_BENEATH, &attr, 0);

133 err = errno;

134 close(attr.parent_fd);

135 errno = err;

136 return ret;

137 }

138

139 #include <fcntl.h>

140 int

141 landlock_unveil_path(int landlock_fd, const char* path, int perms)

142 {

143 int fd = open(path, 0);

144 if (fd < 0) return -1;

145 return landlock_unveil(landlock_fd, fd, perms);

146 }

147

148 int

149 landlock_init()

150 {

151 struct landlock_ruleset_attr attr = {0};

152 attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |

153 LANDLOCK_ACCESS_FS_WRITE_FILE;

154 return landlock_create_ruleset(&attr, sizeof(attr), 0);

155 }

156

157 int

158 landlock_apply(int fd)

159 {

160 int ret = landlock_restrict_self(fd, 0);

161 int err = errno;

162 close(fd);

163 errno = err;

164 return ret;

165 }

166 #endif

167

168 int

169 sandbox_start()

170 {

171 struct sock_fprog prog = {0};

172 int llfd, download;

173

174 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {

175 printf("PR_SET_NO_NEW_PRIVS failed\n");

176 return -1;

177 }

178 #ifdef ENABLE_LANDLOCK

179 llfd = landlock_init();

180 if (llfd < 0) {

181 printf("Failed to initialize landlock : %s\n",

182 strerror(errno));

183 printf("The filesystem won't be hidden from the program\n");

184 goto skip_landlock;

185 }

186 download = landlock_unveil_path(llfd, "download",

187 LANDLOCK_ACCESS_FS_READ_FILE |

188 LANDLOCK_ACCESS_FS_WRITE_FILE);

189 if (download) {

190 printf("landlock, failed to unveil : %s\n", strerror(errno));

191 return -1;

192 }

193 if (landlock_apply(llfd)) {

194 printf("landlock, failed to restrict process : %s\n",

195 strerror(errno));

196 return -1;

197 }

198 skip_landlock:;

199 #endif

200 prog.len = (unsigned short)(sizeof(filter) / sizeof (filter[0])),

201 prog.filter = filter;

202 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0)) {

203 printf("Failed to enable seccomp\n");

204 return -1;

205 }

206 return 0;

207 }

208 #endif

209 #endif

210

211 #ifndef SANDBOXED

212 int

213 sandbox_start()

214 {

215 printf("No sandbox available on your system\n");

216 return 0;

217 }

218 #endif

219