CAP_RIGHTS_LIMIT(2)

✨ CAP_RIGHTS_LIMIT(2) ✨

okay so bestie, we're doing a system call today β€” it lives in the System Calls Manual (that's the section 2 girlies πŸ’…) and it's called cap_rights_limit(2). yes it's giving serious security energy, no it's not scary, come sit with me 🫢


πŸŽ€ NAME πŸŽ€

cap_rights_limit β€” limit capability rights

lowkey the whole plot in four words. iconique.


πŸ“š LIBRARY πŸ“š

Standard C Library (libc, -lc)

so you just link -lc like always and she's there for you, no cap.


🌸 SYNOPSIS 🌸

#include <sys/capsicum.h>

int
cap_rights_limit(int fd, const cap_rights_t *rights);

two args, one int coming back, and <sys/capsicum.h> doing the heavy lifting ✨


πŸ’– DESCRIPTION πŸ’–

okay so here's the tea. when a file descriptor gets created by literally any of these besties β€” accept(2), accept4(2), fhopen(2), kqueue(2), mq_open(2), open(2), openat(2), pdfork(2), pipe(2), shm_open(2), socket(2) or socketpair(2) β€” it shows up holding all the capability rights. like, all of them. every single one. main character energy from birth πŸ‘‘

those rights can be reduced by calling the cap_rights_limit() system call β€” and bestie, listen to me, never expanded. reduced only. the vibes only go one direction, and that direction is down πŸ“‰

once you've reduced the capability rights, everything you do on that file descriptor is limited to just the stuff rights permits. that's it. that's the boundary. respect the boundary 🫢

the rights argument? you gotta prepare it with the cap_rights_init(3) family of functions. that's the pre-game routine, don't skip it.

and if you wanna see what capability rights a file descriptor already has, that's cap_rights_get(3). peek before you tweak, periodt.

the complete list of capability rights lives in the rights(4) manual page. go read her, she's thorough.


πŸ¦‹ RETURN VALUES πŸ¦‹

  • on success, you get the value 0 back β€” slay πŸŽ‰
  • otherwise you get the value -1 back, and the global variable errno gets set to tell you what the error was. the classic -1-and-errno combo, we've all been there 😭

πŸ’… EXAMPLES πŸ’…

here's a little demo showing how to limit file descriptor capability rights so that only reading is allowed. watch her work ✨

cap_rights_t setrights;
char buf[1];
int fd;

fd = open("/tmp/foo", O_RDWR);
if (fd < 0)
        err(1, "open() failed");

if (cap_enter() < 0)
        err(1, "cap_enter() failed");

cap_rights_init(&setrights, CAP_READ);
if (cap_rights_limit(fd, &setrights) < 0)
        err(1, "cap_rights_limit() failed");

buf[0] = 'X';

if (write(fd, buf, sizeof(buf)) > 0)
        errx(1, "write() succeeded!");

if (read(fd, buf, sizeof(buf)) < 0)
        err(1, "read() failed");

see how she opens with O_RDWR, enters capabilities mode with cap_enter(), then slaps CAP_READ on there and expects the write() to blow up? that's the whole point bestie, we shrank the rights and now write can't sit with us πŸ’€


πŸ”₯ ERRORS πŸ”₯

cap_rights_limit() succeeds unless one of these happens:

  • [EBADF] β€” the fd argument is not a valid active descriptor. she's not real, she's not here, we can't work with this πŸ™ˆ
  • [EINVAL] β€” an invalid right has been requested in rights. you asked for something that isn't a thing. not the move πŸ’€
  • [ENOTCAPABLE] β€” the rights argument contains capability rights that are not present for the given file descriptor. and bestie, say it with me: the capability rights list can only be reduced, never expanded. there is no glow-up option here, only glow-down πŸ“‰

πŸ‘‘ SEE ALSO πŸ‘‘

accept(2), accept4(2), cap_enter(2), fhopen(2), kqueue(2), mq_open(2), open(2), openat(2), pdfork(2), pipe(2), read(2), shm_open(2), socket(2), socketpair(2), write(2), cap_rights_get(3), cap_rights_init(3), err(3), capsicum(4), rights(4)

a whole friend group, honestly. all of them in the group chat 🌈


🌟 HISTORY 🌟

the cap_rights_limit() function first appeared in FreeBSD 8.3. support for capabilities and capabilities mode was developed as part of the TrustedBSD Project. vintage, but make it secure πŸŽ€


πŸ’œ AUTHORS πŸ’œ

this function was created by Pawel Jakub Dawidek <pawel@dawidek.net> under sponsorship of the FreeBSD Foundation. giving credit where credit is due, always 🫢


and that's the page bestie!! this one came from Debian, dated May 5, 2020, and it's the CAP_RIGHTS_LIMIT(2) page from the System Calls Manual πŸ’– go forth, limit those rights, never expand them, and stay capsicum-pilled βœ¨πŸ¦‹πŸŒΈ

πŸ“¦ where this page comes from