Limiting Capsicum capabilities rights
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 13 Feb 2024 16:22:45 UTC
Hi all, I'm learning to use capability mode, and am having some difficulty understanding how to correctly limit the rights. I've been doing a lot of reading, watching video (Mariusz Zaborski's BSDcan talk from 2016), and a lot of experimenting. According to rights(4), when a file descriptor is created, it is granted all the rights. I'm having trouble limiting the rights so that it all works with the bare minimum of rights. In my test program, I can successfully do the following since all rights are granted: + first get a directory file descriptor for cwd + call cap_enter() + while in the sandbox, call a function that does: - call openat() and fdopen() to open an input file read-only - call openat() and fdopen() to open an output file read-write - read from in - write to out (which sets weird file perms!) - exit function - fix weird file perms with fchmodat() + done Relevant code snippets: ---------- 45 │ // Get cwd 46 │ if (getcwd(cwd, sizeof(cwd)) == NULL) { 47 │ perror("getcwd() error"); 48 │ return 1; 49 │ } ... 76 │ // Get fd for current directory 77 │ dirfd = open(cwd, O_RDONLY | O_DIRECTORY); ... 91 │ // Enter capability mode 92 │ if (cap_enter() < 0 && errno != ENOSYS) { 93 │ err(1, "Unable to enter capability mode"); 94 │ // Clean up code 95 │ return 1; 96 │ } ... // call function that does stuff with reading and writing files 113 │ // Clean up file permissions 114 │ if (fchmodat(dirfd, outfn, fmode, AT_RESOLVE_BENEATH) == -1) { 115 │ printf("chmod 0640 on %s failed.\n", outfn); 116 │ perror(""); 117 │ } 118 │ 119 │ return 0; 120 │ } ---------- As I say, this all works fine. But if I add in the following declaration and calls to set and limit rights, it fails; clearly too restrictive: ---------- 28 │ cap_rights_t rights; ... 86 │ // Set rights on directory fd 87 │ cap_rights_init(&rights, CAP_LOOKUP, CAP_CREATE, CAP_PREAD, \ 88 │ CAP_PWRITE, CAP_FCHMOD); 89 │ cap_rights_limit(dirfd, &rights); ---------- With my error messages turned on, I see that adding CAP_LOOKUP to the rights mask, (as per rights(4)), allows openat() to succeed, but fdopen() still fails and I'm not sure which right is needed for fdopen() to succeed: ---------- Trying: ifd = openat(dirfd, infn, O_RDONLY) : No error: 0 ifd = 4 Trying: in = fdopen(ifd, "r") : Capabilities insufficient in = 0 Could not open input file for reading. : Capabilities insufficient Cleaning up and exiting gracefully. ---------- Also, from openat(2): ---------- In capsicum(4) capability mode, open() is not permitted. The path argument to openat() must be strictly relative to a file descriptor fd. path must not be an absolute path and must not contain ".." components which cause the path resolution to escape the directory hierarchy starting at fd. Additionally, no symbolic link in path may target absolute path or contain escaping ".." components. fd must not be ^^^^^^^^^^^^^^ AT_FDCWD. ^^^^^^^^ ---------- Do I read this correctly that the directory file descriptor can _not_ be for the cwd? If so, that's confusing me as I am clearly using the cwd, and it works with all right granted. Or does it mean that you can't use the AT_FDCWD flag as 'fd'? Any enlightenment or pointing-me-in-the-right-direction is greatly appreciated. Thanks in advance! - Jonathan ____________________________________________ "Before Turing, things were done to numbers. After Turing, numbers began doing things" - George Dyson