💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › ca6311df99c0df2e5231e36b3e152… captured on 2022-07-16 at 17:12:36. Gemini links have been rewritten to link to archived content

View Raw

More Information

➡️ Next capture (2023-01-29)

-=-=-=-=-=-=-

0 /* See LICENSE file for copyright and license details. */

1 #ifndef DISABLE_XDG

2 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__)

3

4 int xdg_pipe[2];

5 int xdg_open(char*);

6

7 #include <string.h>

8 #include <stdio.h>

9 #include <stdlib.h>

10 #include <unistd.h>

11 #include <signal.h>

12 #include <sys/wait.h>

13 #include <errno.h>

14 #ifdef __linux__

15 #include <sys/prctl.h>

16 #endif

17 #include <termbox.h>

18

19 int xdg_request(char* str) {

20 int len = strnlen(str, 1024)+1;

21 return write(xdg_pipe[1], str, len) != len;

22 }

23

24 void xdg_listener() {

25 char buf[4096];

26 while (1) {

27 int len = read(xdg_pipe[0], buf, sizeof(buf));

28 if (len <= 0)

29 break;

30 xdg_open(buf);

31 }

32 }

33

34 int xdg_init() {

35 if (pipe(xdg_pipe)) {

36 printf("pipe failed\n");

37 return -1;

38 }

39 int pid = fork();

40 if (pid != 0) {

41 close(xdg_pipe[0]);

42 return 0;

43 }

44 close(xdg_pipe[1]);

45 #ifdef __OpenBSD__

46 if (unveil("/bin/sh", "x") ||

47 unveil("/usr/bin/which", "x") ||

48 unveil("/usr/local/bin/xdg-open", "x") ||

49 unveil(NULL, NULL)) {

50 close(xdg_pipe[1]);

51 exit(0);

52 }

53 if (pledge("stdio rpath exec proc", NULL)) {

54 close(xdg_pipe[1]);

55 exit(0);

56 }

57 #endif

58 #ifdef __linux__

59 prctl(PR_SET_NAME, "vgmi [xdg]", 0, 0, 0);

60 #endif

61 xdg_listener();

62 exit(0);

63 }

64

65 int sandbox_close() {

66 close(xdg_pipe[0]);

67 close(xdg_pipe[1]);

68 return 0;

69 }

70

71 #endif

72 #endif

73

74 #ifdef __FreeBSD__

75 #include <stdio.h>

76 #include <sys/capsicum.h>

77 #include <sys/socket.h>

78 #include <netinet/in.h>

79 #include <netdb.h>

80 #include <strings.h>

81 #define WITH_CASPER

82 #include <sys/nv.h>

83 #include <libcasper.h>

84 #include <casper/cap_net.h>

85 #include <capsicum_helpers.h>

86

87 cap_channel_t *_capnet;

88 cap_net_limit_t* limit;

89

90 int sandbox_connect(int s, const struct sockaddr *name, socklen_t namelen) {

91 return cap_connect(_capnet, s, name, namelen);

92 }

93

94 int sandbox_getaddrinfo(const char *hostname, const char *servname,

95 const struct addrinfo *hints, struct addrinfo **res) {

96 return cap_getaddrinfo(_capnet, hostname, servname, hints, res);

97 }

98

99 #include "cert.h"

100 int sandbox_init() {

101 #ifndef DISABLE_XDG

102 if (xdg_init()) {

103 printf("xdg failure\n");

104 return -1;

105 }

106 #endif

107 if (getconfigfd() < 0) {

108 printf("Unable to open/create config folder\n");

109 return -1;

110 }

111 if (chdir("/var/empty")) {

112 printf("chdir failure\n");

113 return -1;

114 }

115

116 cap_rights_t rights;

117 cap_rights_init(&rights, CAP_WRITE, CAP_LOOKUP, CAP_READ,

118 CAP_SEEK, CAP_CREATE, CAP_FCNTL);

119 if (cap_rights_limit(config_fd, &rights)) {

120 printf("cap_rights_limit failed\n");

121 return -1;

122 }

123

124 cap_channel_t *capcas;

125 capcas = cap_init();

126 if (capcas == NULL) {

127 printf("cap_init failed\n");

128 return -1;

129 }

130 caph_cache_catpages();

131 if (caph_enter()) {

132 printf("cap_enter failed\n");

133 return -1;

134 }

135 _capnet = cap_service_open(capcas, "system.net");

136 cap_close(capcas);

137 if (_capnet == NULL) {

138 printf("failed to open system.net service\n");

139 return -1;

140 }

141 limit = cap_net_limit_init(_capnet,

142 CAPNET_NAME2ADDR | CAPNET_CONNECTDNS | CAPNET_CONNECT);

143 if (limit == NULL) {

144 printf("Unable to create limits.\n");

145 return -1;

146 }

147 int families[] = {AF_INET, AF_INET6};

148 cap_net_limit_name2addr_family(limit, families, 2);

149 if (cap_net_limit(limit) < 0) {

150 printf("Unable to apply limits.\n");

151 return -1;

152 }

153 return 0;

154 }

155

156 int makefd_readonly(int fd) {

157 cap_rights_t rights;

158 cap_rights_init(&rights, CAP_SEEK, CAP_READ);

159 if (cap_rights_limit(fd, &rights))

160 return -1;

161 return 0;

162 }

163

164 int make_readonly(FILE* f) {

165 return makefd_readonly(fileno(f));

166 }

167

168 int makefd_writeonly(int fd) {

169 cap_rights_t rights;

170 cap_rights_init(&rights, CAP_WRITE);

171 if (cap_rights_limit(fd, &rights))

172 return -1;

173 return 0;

174 }

175

176 int makefd_writeseek(int fd) {

177 cap_rights_t rights;

178 cap_rights_init(&rights, CAP_WRITE, CAP_SEEK);

179 if (cap_rights_limit(fd, &rights))

180 return -1;

181 return 0;

182 }

183

184 int make_writeonly(FILE* f) {

185 return makefd_writeonly(fileno(f));

186 }

187 #elif __OpenBSD__

188 #include <stdio.h>

189 #include <stdlib.h>

190 #include <unistd.h>

191 #include "cert.h"

192

193 extern char home_path[1024];

194 extern char config_path[1024];

195

196 int sandbox_init() {

197 #ifndef DISABLE_XDG

198 if (xdg_init()) {

199 printf("xdg failure\n");

200 return -1;

201 }

202 #endif

203 #ifndef HIDE_HOME

204 if (gethomefd() < 1) {

205 printf("Failed to get home folder\n");

206 return -1;

207 }

208 #endif

209 if (getconfigfd() < 0) {

210 printf("Failed to get cache folder\n");

211 return -1;

212 }

213 if (getdownloadfd() < 0) {

214 printf("Failed to get download folder\n");

215 return -1;

216 }

217 if (

218 #ifndef HIDE_HOME

219 unveil(home_path, "r") ||

220 #endif

221 unveil(config_path, "rwc") ||

222 unveil(download_path, "rwc") ||

223 unveil("/etc/resolv.conf", "r") ||

224 unveil(NULL, NULL)) {

225 printf("Failed to unveil\n");

226 return -1;

227 }

228 if (pledge("stdio rpath wpath cpath inet dns tty", NULL)) {

229 printf("Failed to pledge\n");

230 return -1;

231 }

232 return 0;

233 }

234

235 #elif __linux__

236 #include <stdio.h>

237 #include <fcntl.h>

238 #include <unistd.h>

239 #include <stddef.h>

240 #include <linux/seccomp.h>

241 #include <linux/filter.h>

242 #include <linux/unistd.h>

243 #if ENABLE_LANDLOCK || (!defined(DISABLE_LANDLOCK) && __has_include(<linux/landlock.h>))

244 #include <linux/landlock.h>

245 #define ENABLE_LANDLOCK

246 #endif

247 #include "cert.h"

248

249 // --------------

250 // copied from : https://roy.marples.name/git/dhcpcd/blob/HEAD:/src/privsep-linux.c

251 #define SC_ALLOW_(nr) \

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

253 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)

254

255 #define SC_ALLOW(nr) \

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

257 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)

258

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

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

261 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \

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

263 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, \

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

265 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \

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

267 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, \

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

269 BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW), \

270 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \

271 offsetof(struct seccomp_data, nr))

272 // --------------

273

274 struct sock_filter filter[] = {

275 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,

276 (offsetof(struct seccomp_data, arch))),

277 BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),

278 //#ifdef __MUSL__

279 SC_ALLOW(readv),

280 SC_ALLOW(writev),

281 SC_ALLOW(open),

282 SC_ALLOW(dup2), // required by getaddrinfo

283 //#else

284 SC_ALLOW(pipe2), // tb_init

285 SC_ALLOW(recvmsg), // getaddrinfo_a

286 SC_ALLOW(getsockname), // getaddrinfo_a

287 //#endif

288 SC_ALLOW(fstat), // older glibc and musl

289 SC_ALLOW(stat), // older glibc

290 SC_ALLOW(pipe), // older glibc and musl

291 SC_ALLOW(setsockopt),

292 SC_ALLOW(read),

293 SC_ALLOW(write),

294 SC_ALLOW(openat),

295 SC_ALLOW(close),

296 SC_ALLOW(exit),

297 SC_ALLOW(ioctl),

298 SC_ALLOW(exit_group),

299 SC_ALLOW(futex),

300 SC_ALLOW(sysinfo),

301 SC_ALLOW(brk),

302 SC_ALLOW(newfstatat),

303 SC_ALLOW(getpid),

304 SC_ALLOW(getrandom),

305 SC_ALLOW(mmap),

306 SC_ALLOW(fcntl),

307 SC_ALLOW(lseek),

308 SC_ALLOW(rt_sigaction),

309 SC_ALLOW(rt_sigprocmask),

310 SC_ALLOW(rt_sigreturn), // resizing

311 SC_ALLOW(mprotect),

312 SC_ALLOW(pread64),

313 SC_ALLOW(uname), // getaddrinfo

314 SC_ALLOW(ppoll), // getaddrinfo

315 SC_ALLOW(bind), // getaddrinfo

316 SC_ALLOW(sendto),

317 SC_ALLOW(recvfrom),

318 SC_ALLOW(socket),

319 SC_ALLOW(socketpair),

320 SC_ALLOW(connect),

321 SC_ALLOW(getsockopt),

322 SC_ALLOW(poll),

323 SC_ALLOW(clone),

324 #ifdef __NR_clone3

325 SC_ALLOW(clone3),

326 #endif

327 SC_ALLOW(clock_nanosleep),

328 SC_ALLOW(nanosleep),

329 SC_ALLOW(rseq), // pthread_create

330 SC_ALLOW(set_robust_list), // pthread_create

331 SC_ALLOW(munmap), // pthread_create

332 SC_ALLOW(madvise), // thread exit

333 SC_ALLOW(mremap), // realloc

334 SC_ALLOW(select), // on old version of linux

335 SC_ALLOW(membarrier),

336 SC_ALLOW(sendmmsg),

337 #ifdef __NR_pselect6

338 SC_ALLOW(pselect6),

339 #endif

340 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),

341 };

342

343 #ifdef ENABLE_LANDLOCK

344 static inline int landlock_create_ruleset(const struct landlock_ruleset_attr *attr,

345 size_t size, uint32_t flags)

346 {

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

348 }

349

350 static inline int landlock_add_rule(int ruleset_fd, enum landlock_rule_type type,

351 const void *attr, uint32_t flags)

352 {

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

354 }

355

356 static inline int landlock_restrict_self(int ruleset_fd, __u32 flags)

357 {

358 return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);

359 }

360

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

362 {

363 struct landlock_path_beneath_attr attr = {

364 .allowed_access = perms,

365 .parent_fd = fd

366 };

367

368 int ret = landlock_add_rule(landlock_fd, LANDLOCK_RULE_PATH_BENEATH, &attr, 0);

369 int err = errno;

370 close(attr.parent_fd);

371 errno = err;

372 return ret;

373 }

374

375 #include <fcntl.h>

376 int landlock_unveil_path(int landlock_fd, const char* path, int perms) {

377 int fd = open(path, 0);

378 if (fd < 0) return -1;

379 int ret = landlock_unveil(landlock_fd, fd, perms);

380 return ret;

381 }

382

383 int landlock_init() {

384 struct landlock_ruleset_attr attr = {

385 .handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE |

386 LANDLOCK_ACCESS_FS_READ_FILE |

387 LANDLOCK_ACCESS_FS_READ_DIR |

388 LANDLOCK_ACCESS_FS_WRITE_FILE |

389 LANDLOCK_ACCESS_FS_REMOVE_DIR |

390 LANDLOCK_ACCESS_FS_REMOVE_FILE |

391 LANDLOCK_ACCESS_FS_MAKE_CHAR |

392 LANDLOCK_ACCESS_FS_MAKE_DIR |

393 LANDLOCK_ACCESS_FS_MAKE_REG |

394 LANDLOCK_ACCESS_FS_MAKE_SOCK |

395 LANDLOCK_ACCESS_FS_MAKE_FIFO |

396 LANDLOCK_ACCESS_FS_MAKE_BLOCK |

397 LANDLOCK_ACCESS_FS_MAKE_SYM,

398 };

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

400 }

401

402 int landlock_apply(int fd)

403 {

404 int ret = landlock_restrict_self(fd, 0);

405 int err = errno;

406 close(fd);

407 errno = err;

408 return ret;

409 }

410

411 extern char config_path[1024];

412 extern char download_path[1024];

413 #endif

414

415 int sandbox_init() {

416 #ifndef DISABLE_XDG

417 if (xdg_init()) {

418 printf("xdg failure\n");

419 return -1;

420 }

421 #endif

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

423 printf("PR_SET_NO_NEW_PRIVS failed\n");

424 return -1;

425 }

426

427 int dfd = getdownloadfd();

428 int cfd = getconfigfd();

429 if (cfd < 0 || dfd < 0) {

430 printf("Failed to access folders\n");

431 return -1;

432 }

433 #ifdef ENABLE_LANDLOCK

434 int llfd = landlock_init();

435 if (llfd < 0) {

436 printf("[WARNING] Failed to initialize landlock : %!s(MISSING)\n", strerror(errno));

437 printf("[WARNING] The filesystem won't be hidden from the program\n");

438 goto skip_landlock;

439 }

440 #ifndef HIDE_HOME

441 #include <pwd.h>

442 struct passwd *pw = getpwuid(geteuid());

443 if (!pw) {

444 printf("failed to get home folder: %!s(MISSING)\n", strerror(errno));

445 return -1;

446 }

447 int home = landlock_unveil_path(llfd, pw->pw_dir,

448 LANDLOCK_ACCESS_FS_READ_FILE);

449 #endif

450 int cfg = landlock_unveil_path(llfd, config_path,

451 LANDLOCK_ACCESS_FS_READ_FILE |

452 LANDLOCK_ACCESS_FS_WRITE_FILE |

453 LANDLOCK_ACCESS_FS_MAKE_REG);

454 int dl = landlock_unveil_path(llfd, download_path,

455 LANDLOCK_ACCESS_FS_WRITE_FILE |

456 LANDLOCK_ACCESS_FS_MAKE_REG);

457 int hosts = landlock_unveil_path(llfd, "/etc/hosts",

458 LANDLOCK_ACCESS_FS_READ_FILE);

459 int run = landlock_unveil_path(llfd, "/run",

460 LANDLOCK_ACCESS_FS_READ_FILE);

461

462 int resolv = landlock_unveil_path(llfd, "/etc/resolv.conf",

463 LANDLOCK_ACCESS_FS_READ_FILE);

464

465 if (dl || cfg || hosts || run || home || resolv) {

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

467 return -1;

468 }

469

470 #ifndef __MUSL__

471 // load dynamic library before restricting process

472 struct addrinfo hints, *result;

473 bzero(&hints, sizeof(hints));

474 hints.ai_family = AF_INET;

475 hints.ai_socktype = SOCK_STREAM;

476 hints.ai_flags |= AI_CANONNAME;

477

478 if (getaddrinfo("example.com", NULL, &hints, &result)) {

479 printf("getaddrinfo failed\n");

480 return -1;

481 }

482 #endif

483 if (landlock_apply(llfd)) {

484 printf("landlock, failed to restrict process : %!s(MISSING)\n", strerror(errno));

485 return -1;

486 }

487 skip_landlock:;

488 #endif

489 struct sock_fprog prog = {

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

491 .filter = filter,

492 };

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

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

495 return -1;

496 }

497 return 0;

498 }

499

500 #else

501 #define NOSANDBOX

502 int sandbox_init() {

503 return 0;

504 }

505

506 int sandbox_close() {

507 return 0;

508 }

509 #endif

510

511 #if !defined(NOSANDBOX) && defined(DISABLE_XDG)

512 int sandbox_close() {

513 return 0;

514 }

515 #endif

516