selinux_status_open(3)

πŸ“¦
version 3.11 Β· 2 versions
, in alpine 3.24, centos-stream 10, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, ubuntu resolute, ubuntu stonking

πŸ’– selinux_status_open(3) β€” SELinux API documentation πŸ’–

ok so bestie. this is a page about peeking at the SELinux kernel status without ever making a system call, and it's genuinely one of the most iconic little tricks in the SELinux API. it lives in the SELinux API documentation, and the star of the show is selinux_status_open(3). let's get into it 🫢


✨ NAME ✨

selinux_status_open, selinux_status_close, selinux_status_updated, selinux_status_getenforce, selinux_status_policyload and selinux_status_deny_unknown β€” reference the SELinux kernel status without invocation of system calls

like, no syscalls. none. zero. it's giving efficiency queen πŸ‘‘


🌸 SYNOPSIS 🌸

#include <selinux/avc.h>

int selinux_status_open(int fallback);

void selinux_status_close(void);

int selinux_status_updated(void);

int selinux_status_getenforce(void);

int selinux_status_policyload(void);

int selinux_status_deny_unknown(void);

πŸ¦‹ DESCRIPTION πŸ¦‹

ok so here's the lore. Linux 2.6.37 or later gives you a SELinux kernel status page, and it's mostly chillin' at the /sys/fs/selinux/status entry. this page lets userspace applications mmap it in read-only mode, and then it just tells you stuff β€” no system call invocations required. periodt. πŸ’…

in some cases where a userspace application is trying to do heavy frequent access control β€” like, think row-level security in databases β€” it's gonna hit an unignorable cost talking to kernel space just to check whether the userspace avc has been invalidated. imagine paying that toll every single time. exhausting. 😭

so these functions hand applications a way to know about some kernel events with no system-call invocation and no worker thread doing the monitoring. main character energy fr fr.


πŸ’œ selinux_status_open() πŸ’œ

selinux_status_open() tries to open(2) /sys/fs/selinux/status and mmap(2) it in read-only mode. the file-descriptor and the pointer to the page get stored internally β€” don't touch them directly, bestie, they're not yours, hands off πŸ™ˆ.

set 1 on the fallback argument to handle the case of older kernels that don't have kernel status page support. in that case, this function tries to open a netlink socket using avc_netlink_open(3) and overwrite the corresponding callbacks (setenforce and policyload). so heads up: we need to pay attention to the interaction with these interfaces when fallback mode is enabled. like, they're entangled now, iykyk.


πŸ’œ selinux_status_close() πŸ’œ

selinux_status_close() unmaps the kernel status page and closes its file descriptor β€” or closes the netlink socket if it was fallbacked. clean up after yourself, it's the bare minimum πŸŽ€


πŸ’œ selinux_status_updated() πŸ’œ

selinux_status_updated() processes status update events. there are two kinds of status updates:

  • setenforce events will change the effective enforcing state used within the AVC
  • policyload events will result in a cache flush

and the return value:

  • returns 0 if there have been no updates since the last call
  • returns 1 if there have been updates since the last call
  • returns -1 on error

πŸ’œ selinux_status_getenforce() πŸ’œ

selinux_status_getenforce() returns 0 if SELinux is running in permissive mode, 1 if enforcing mode, or -1 on error.

it's the same as security_getenforce(3) β€” except with or without system call invocation. same vibe, different mechanics, slay ✨


πŸ’œ selinux_status_policyload() πŸ’œ

selinux_status_policyload() returns the times of policy reloaded on the running system, or -1 on error.

⚠️ note that it is not a reliable value on fallback-mode until it receives the first event message via netlink socket. so don't use this value to figure out the actual times of policy reloaded. it's just not that girl in fallback mode 😭

πŸ’œ selinux_status_deny_unknown() πŸ’œ

selinux_status_deny_unknown() returns 0 if SELinux treats policy queries on undefined object classes or permissions as being allowed, 1 if such queries are denied, or -1 on error. yes ma'am, three possible answers, pick your fighter 🧚


⭐ RETURN VALUE ⭐

selinux_status_open() returns 0 or 1 on success.

  • 1 means we are ready to use these interfaces, but the netlink socket was opened as fallback instead of the kernel status page
  • on error, -1 shall be returned

any other functions with a return value shall return their characteristic value as described above, or -1 on errors. simple as that πŸ’–


πŸ’€ CAVEATS πŸ’€

these functions are not thread-safe. you have to protect them from concurrent calls using exclusive locks when multiple threads are executing. no cap. if you're running multithreaded and you skip the lock, that's on you bestie, the manpage literally warned you πŸ™ˆ


🌈 SEE ALSO 🌈


and that's the whole page, gorgeous. shoutout to kaigai@ak.jp.nec.com for writing this one back on 22 January 2011 β€” it's the selinux_status_open(3) page from the SELinux API documentation, and honestly? it ate. go forth and mmap responsibly πŸ’…βœ¨πŸ¦‹

πŸ“¦ where this page comes from