summaryrefslogtreecommitdiff
path: root/blog/access-control
diff options
context:
space:
mode:
authorJohn Turner <jturner.usa@gmail.com>2025-08-26 02:03:35 -0400
committerJohn Turner <jturner.usa@gmail.com>2025-08-26 02:07:41 -0400
commit52a2cae0b3583d4148cbc183f6ce551f94ae3676 (patch)
tree60389f6ef604945e337ee890ccf10c493ab9e2a0 /blog/access-control
parentdaa0086eff780285f273cc4af527a091133eef72 (diff)
downloadwebsite-52a2cae0b3583d4148cbc183f6ce551f94ae3676.tar.gz
create blog post about access control methods
Diffstat (limited to 'blog/access-control')
-rw-r--r--blog/access-control/weechat.cil171
-rw-r--r--blog/access-control/xdgfile.cil47
2 files changed, 218 insertions, 0 deletions
diff --git a/blog/access-control/weechat.cil b/blog/access-control/weechat.cil
new file mode 100644
index 0000000..c453063
--- /dev/null
+++ b/blog/access-control/weechat.cil
@@ -0,0 +1,171 @@
+;; Selinux is deny by default. So we must explicitly allow access to everything weechat needs,
+;; including system libraries, the dynamic loader, xdg directories and more.
+
+;; reserve ports for irc purposes
+(block irc
+ (portcon "tcp" 6667 port_context)
+ (portcon "tcp" 6697 port_context)
+ (blockinherit .net.port.unreserved.template))
+
+;; define our weechat namespace
+(block weechat
+ ;; most or all things have a template defined that we can use
+ ;; rarely do we write policy "from scratch", this includes subjects which are
+ ;; what we are creating here
+ (blockinherit .subj.template)
+
+ ;; authorize sys.role to access the subj domain
+ (roletype .sys.role subj)
+
+ ;; allow signaling ourself
+ (allow subj self (process (fork sigchld sigkill signal signull sigstop)))
+
+ ;; allow setattr and getattr on our own files
+ (allow subj self (file (setattr getattr)))
+
+ ;; allow reading and executing our own binary (/usr/bin/weechat)
+ ;; also allow a type transition from .sys.subj to .weechat.subj
+ (call .weechat.exec.subj_type_transition (.sys.subj subj))
+ (call .weechat.exec.entrypoint_file_files (subj))
+ (call .weechat.exec.mapexecute_file_files (subj))
+ (call .weechat.exec.read_file_files (subj))
+
+ ;; nearly full access to our own data files
+ (call .weechat.data.search_file_dirs (subj))
+ (call .weechat.data.create_file_dirs (subj))
+ (call .weechat.data.create_file_files (subj))
+ (call .weechat.data.delete_file_files (subj))
+ (call .weechat.data.readwrite_file_files (subj))
+ (call .weechat.data.rename_file_files (subj))
+ (call .weechat.data.addname_file_dirs (subj))
+ (call .weechat.data.deletename_file_dirs (subj))
+ (call .weechat.data.rename_file_dirs (subj))
+
+ ;; same as above, nearly full access to our runtime files
+ (call .weechat.run.search_file_dirs (subj))
+ (call .weechat.run.create_file_dirs (subj))
+ (call .weechat.run.create_file_files (subj))
+ (call .weechat.run.delete_file_files (subj))
+ (call .weechat.run.readwrite_file_files (subj))
+ (call .weechat.run.rename_file_files (subj))
+ (call .weechat.run.addname_file_dirs (subj))
+ (call .weechat.run.deletename_file_dirs (subj))
+ (call .weechat.run.rename_file_dirs (subj))
+
+ ;; allow using unix sockets so long as they are the same type as ourself
+ (allow subj self (unix_dgram_socket (create sendto read write)))
+
+ ;; allowing using the network but only irc ports specifically
+ (allow subj self create_tcp_socket)
+ (call irc.nameconnect_port_tcp_sockets (subj))
+
+ ;; You need to be able to traverse directories before you can access files.
+ ;; Each parent dir needs to be traversable, so we have to allow traversing root.
+ (call .root.search_file_dirs (subj))
+
+ ;; allow access to procfs
+ (call .proc.read_fs_lnk_files (subj))
+ (call .proc.search_fs_dirs (subj))
+
+ ;; allow access to sysfs
+ (call .sys.search_fs_dirs (subj))
+ (call .sys.read_fs_files (subj))
+
+ ;; use system libraries
+ (call .lib.search_file_dirs (subj))
+ (call .lib.read_file_files (subj))
+ (call .lib.mapexecute_file_files (subj))
+ (call .lib.read_file_lnk_files (subj))
+
+ ;; read /etc
+ (call .conf.search_file_dirs (subj))
+ (call .conf.read_file_files (subj))
+ (call .conf.read_file_lnk_files (subj))
+ ;; The dynamic loader is currently labeled .conf.file, and we need to be able to map and exec it.
+ ;; This is something you probably want to fix when writing your own policy on top of dssp5.
+ (call .conf.mapexecute_file_files (subj))
+
+ ;; use ssl certs
+ (call .cert.search_file_dirs (subj))
+ (call .cert.read_file_files (subj))
+
+ ;; use terminal
+ (call .sys.use_subj_fds (subj))
+ (call .dev.readwriteinherited_file_chr_files (subj))
+ (call .ptytermdev.readwriteinherited_all_chr_files (subj))
+
+ ;; read /usr/share
+ (call .data.search_file_dirs (subj))
+ (call .data.read_file_files (subj))
+
+ ;; traverse /home
+ (call .home.search_file_dirs (subj))
+
+ ;; allow creating dirs in ~/.config
+ (call .xdg.config.home.search_file_dirs (subj))
+ (call .xdg.config.home.create_file_dirs (subj))
+ (call .xdg.config.home.addname_file_dirs (subj))
+
+ ;; allow creating dirs in ~/.cache
+ (call .xdg.cache.home.search_file_dirs (subj))
+ (call .xdg.cache.home.create_file_dirs (subj))
+ (call .xdg.cache.home.addname_file_dirs (subj))
+
+ ;; allow creating dirs in ~/.local/share
+ (call .xdg.share.home.search_file_dirs (subj))
+ (call .xdg.share.home.create_file_dirs (subj))
+ (call .xdg.share.home.addname_file_dirs (subj))
+
+ ;; allow creating dirs in ~/.local/state
+ (call .xdg.state.home.search_file_dirs (subj))
+ (call .xdg.state.home.create_file_dirs (subj))
+ (call .xdg.state.home.addname_file_dirs (subj))
+
+ ;; allow creating files in the runtime directory
+ (call .run.search_file_dirs (subj))
+ (call .run.create_file_dirs (subj))
+
+ (block exec
+ (blockinherit .file.exec.template)
+
+ ;; Label the weechat executable itself.
+ ;; This along with some macros we called earlier cause executing weechat to transition to
+ ;; the weechat.subj context.
+ (filecon "/usr/bin/weechat" file file_context))
+
+ (block data
+ ;; This macro will be called at some point and is what makes the files and directories
+ ;; weechat creates in ~/.config and such transition to .weechat.data.file type from
+ ;; .home.file.
+ (macro xdg_file_type_transition_file ((type ARG1) (class ARG2) (name ARG3))
+ (call .xdg.config.home.file_type_transition (ARG1 file ARG2 ARG3))
+ (call .xdg.cache.home.file_type_transition (ARG1 file ARG2 ARG3))
+ (call .xdg.share.home.file_type_transition (ARG1 file ARG2 ARG3))
+ (call .xdg.state.home.file_type_transition (ARG1 file ARG2 ARG3)))
+
+ (blockinherit .file.home.template)
+
+ (filecon "HOME_DIR/\.config/weechat(/.*)?" any file_context)
+ (filecon "HOME_DIR/\.local/share/weechat(/.*)?" any file_context)
+ (filecon "HOME_DIR/\.local/state/weechat(/.*)?" any file_context)
+ (filecon "HOME_DIR/\.cache/weechat(/.*)?" any file_context))
+
+ (block run
+ ;; This is similar to the file type transition macro above, but for runtime files instead
+ ;; of config and state files.
+ (macro file_type_transition_file ((type ARG1) (class ARG2) (name ARG3))
+ (call .run.file_type_transition (ARG1 file ARG2 ARG3)))
+
+ (blockinherit .file.run.template)
+
+ (filecon "/run/user/%{USERID}/weechat" dir file_context)
+ (filecon "/run/user/%{USERID}/weechat/.*" any file_context)))
+
+;; we want files and dirs weechat creates to be of the weechat type so we call our
+;; type transition macro.
+(call .weechat.data.xdg_file_type_transition_file (.weechat.subj dir "*"))
+(call .weechat.data.xdg_file_type_transition_file (.weechat.subj file "*"))
+
+;; same as above but for runtime files
+(call .weechat.run.file_type_transition_file (.weechat.subj dir "weechat"))
+(call .weechat.run.file_type_transition_file (.weechat.subj file "*"))
diff --git a/blog/access-control/xdgfile.cil b/blog/access-control/xdgfile.cil
new file mode 100644
index 0000000..67f5e31
--- /dev/null
+++ b/blog/access-control/xdgfile.cil
@@ -0,0 +1,47 @@
+;; create out xdg namespace
+(block xdg
+ ;; we will create a subnamespace for each xdg file type (e.g config, cache, share, state)
+ (block config
+ ;; this next block isn't technically required but it shows that we are a subtype of .file.home
+ (block home
+ ;; create a macro to allow type transitions for files in our context
+ (macro file_type_transition_file ((type ARG1) (class ARG2) (name ARG3))
+ (call .home.file_type_transition_file (ARG1 file ARG2 ARG3)))
+
+ ;; inherit the template which defines some types for us and also provides some macros
+ (blockinherit .file.home.template)
+
+ ;; define a context for the ~/.cache directory itself
+ ;; hint: HOME_DIR is one of the few variables that can be interpolated into strings
+ (filecon "HOME_DIR/\.config" dir file_context)
+ (filecon "HOME_DIR/\.config/.*" file file_context)))
+
+ (block cache
+ (block home
+ (macro file_type_transition_file ((type ARG1) (class ARG2) (name ARG3))
+ (call .home.file_type_transition_file (ARG1 file ARG2 ARG3)))
+
+ (blockinherit .file.home.template)
+
+ (filecon "HOME_DIR/\.cache" dir file_context)
+ (filecon "HOME_DIR/\.cache/.*" file file_context)))
+
+ (block share
+ (block home
+ (macro file_type_transition_file ((type ARG1) (class ARG2) (name ARG3))
+ (call .home.file_type_transition_file (ARG1 file ARG2 ARG3)))
+
+ (blockinherit .file.home.template)
+
+ (filecon "HOME_DIR/\.local/share" dir file_context)
+ (filecon "HOME_DIR/\.local/share/.*" file file_context)))
+
+ (block state
+ (block home
+ (macro file_type_transition_file ((type ARG1) (class ARG2) (name ARG3))
+ (call .home.file_type_transition_file (ARG1 file ARG2 ARG3)))
+
+ (blockinherit .file.home.template)
+
+ (filecon "HOME_DIR/\.local/state" dir file_context)
+ (filecon "HOME_DIR/\.local/state/.*" file file_context))))