diff --git a/policy/modules/roles/staff.te b/policy/modules/roles/staff.te
index b464dc219a..15cbd6f1c2 100644
--- a/policy/modules/roles/staff.te
+++ b/policy/modules/roles/staff.te
@@ -56,6 +56,10 @@ optional_policy(`
sudo_role_template(staff, staff_t, staff_application_exec_domain, staff_r)
')
+optional_policy(`
+ sway_role(staff, staff_t, staff_r)
+')
+
optional_policy(`
sysadm_role_change(staff_r, staff_t)
userdom_dontaudit_use_user_terminals(staff_t)
diff --git a/policy/modules/roles/sysadm.te b/policy/modules/roles/sysadm.te
index 3a82425685..7d74b005cc 100644
--- a/policy/modules/roles/sysadm.te
+++ b/policy/modules/roles/sysadm.te
@@ -1106,6 +1106,10 @@ optional_policy(`
svnserve_admin(sysadm_t, sysadm_r)
')
+optional_policy(`
+ sway_role(sysadm, sysadm_t, sysadm_r)
+')
+
optional_policy(`
sysnet_run_ifconfig(sysadm_t, sysadm_r)
sysnet_run_dhcpc(sysadm_t, sysadm_r)
diff --git a/policy/modules/roles/unprivuser.te b/policy/modules/roles/unprivuser.te
index d8d0e02788..06235ccadf 100644
--- a/policy/modules/roles/unprivuser.te
+++ b/policy/modules/roles/unprivuser.te
@@ -29,6 +29,10 @@ optional_policy(`
screen_role_template(user, user_t, user_application_exec_domain, user_r)
')
+optional_policy(`
+ sway_role(user, user_t, user_r)
+')
+
optional_policy(`
vlock_run(user_t, user_r)
')
diff --git a/policy/modules/session/sway.fc b/policy/modules/session/sway.fc
new file mode 100644
index 0000000000..82a0db668c
--- /dev/null
+++ b/policy/modules/session/sway.fc
@@ -0,0 +1,7 @@
+HOME_DIR/\.config/sway(/.*)? gen_context(system_u:object_r:sway_xdg_config_t,s0)
+
+/etc/sway(/.*)? gen_context(system_u:object_r:sway_etc_t,s0)
+
+/usr/bin/sway -- gen_context(system_u:object_r:sway_exec_t,s0)
+
+/run/user/%{USERID}/sway-ipc\..*\.sock -s gen_context(system_u:object_r:sway_runtime_t,s0)
diff --git a/policy/modules/session/sway.if b/policy/modules/session/sway.if
new file mode 100644
index 0000000000..806747dd94
--- /dev/null
+++ b/policy/modules/session/sway.if
@@ -0,0 +1,112 @@
+## Policy for the sway Wayland compositor.
+
+########################################
+##
+## Role access for sway.
+##
+##
+##
+## The prefix of the user role (e.g., user
+## is the prefix for user_r).
+##
+##
+##
+##
+## User domain for the role.
+##
+##
+##
+##
+## Role allowed access
+##
+##
+#
+template(`sway_role',`
+ gen_require(`
+ attribute_role sway_roles;
+ type sway_exec_t, sway_etc_t;
+ type sway_runtime_t, sway_xdg_config_t;
+ ')
+
+ type $1_sway_t;
+ # Even though sway instances for different user types are separated by the
+ # $1_ prefix before their domain, making separate domains, we still want
+ # the various sway instances to be ubac constrained for other various file
+ # types.
+ userdom_user_application_domain($1_sway_t, sway_exec_t)
+ wayland_compositor_domain($1_sway_t)
+
+ domtrans_pattern($2, sway_exec_t, $1_sway_t)
+
+ roleattribute $3 sway_roles;
+ role $3 types { $1_sway_t };
+
+ type $1_sway_tmpfs_t;
+ userdom_user_tmpfs_file($1_sway_tmpfs_t)
+ wayland_compositor_tmpfs($1_sway_tmpfs_t)
+
+ # https://github.com/swaywm/sway/blob/master/sway/realtime.c
+ allow $1_sway_t self:process { getsched setsched };
+
+ read_files_pattern($1_sway_t, sway_etc_t, sway_etc_t)
+
+ # No transition or creation: sway only ever reads the config.
+ read_files_pattern($1_sway_t, sway_xdg_config_t, sway_xdg_config_t)
+
+ manage_sock_files_pattern($1_sway_t, sway_runtime_t, sway_runtime_t)
+ # sway-ipc: Wayland display socket is handled by the implied transitions in
+ # wayland_compositor_domain().
+ files_runtime_filetrans($1_sway_t, sway_runtime_t, sock_file)
+
+ manage_files_pattern($1_sway_t, $1_sway_tmpfs_t, $1_sway_tmpfs_t)
+ allow $1_sway_t $1_sway_tmpfs_t:file map;
+ fs_tmpfs_filetrans($1_sway_t, $1_sway_tmpfs_t, file)
+
+ # os-release/lsb-release information, /etc/fonts/fonts.conf
+ files_read_etc_files($1_sway_t)
+
+ # pixmaps and icons for xcursor.
+ files_read_usr_files($1_sway_t)
+
+ # /dev/udmabuf allocator.
+ dev_rw_dma_dev($1_sway_t)
+
+ # XXX: mesa tries to read boot_vga when using i915, and also attempts to read
+ # the various cpu_capacity sysfiles - should this be moved into the wayland
+ # modules?
+ dev_read_sysfs($1_sway_t)
+
+ # XXX: /proc/meminfo, seems to be mesa related - should this be moved into the
+ # wayland module?
+ kernel_read_system_state($1_sway_t)
+
+ # No need for corecmd_bin_domtrans(), sway executes everything with /bin/sh:
+ # https://github.com/swaywm/sway/blob/055be4ec35eec4eaaf066a18ccbf5132ebed0694/sway/commands/exec_always.c#L64
+ # Other things that are executed (e.g. swaybar, swaybg, and swaynag) are done
+ # so specially by sway, and require specific policy. Those modules should add
+ # domain transitions as needed instead.
+ corecmd_shell_domtrans($1_sway_t, $2)
+
+ optional_policy(`
+ # Talk to systemd-logind over the system bus.
+ dbus_system_bus_client($1_sway_t)
+ ')
+
+ optional_policy(`
+ systemd_user_app_status($1, $1_sway_t)
+ ')
+
+ # Policy for the user_domain
+ allow $2 sway_xdg_config_t:dir { manage_dir_perms relabel_dir_perms };
+ allow $2 sway_xdg_config_t:file { manage_file_perms relabel_file_perms };
+ allow $2 sway_xdg_config_t:lnk_file { manage_lnk_file_perms relabel_lnk_file_perms };
+
+ allow $2 $1_sway_tmpfs_t:dir { manage_dir_perms relabel_dir_perms };
+ allow $2 $1_sway_tmpfs_t:file { manage_file_perms relabel_file_perms };
+ allow $2 $1_sway_tmpfs_t:fifo_file { manage_fifo_file_perms relabel_fifo_file_perms };
+ allow $2 $1_sway_tmpfs_t:sock_file { manage_sock_file_perms relabel_sock_file_perms };
+
+ optional_policy(`
+ xdg_config_filetrans($2, sway_xdg_config_t, dir, "sway")
+ ')
+')
diff --git a/policy/modules/session/sway.te b/policy/modules/session/sway.te
new file mode 100644
index 0000000000..37da8b1966
--- /dev/null
+++ b/policy/modules/session/sway.te
@@ -0,0 +1,19 @@
+policy_module(sway)
+
+########################################
+#
+# Declarations
+#
+
+attribute_role sway_roles;
+
+type sway_exec_t;
+
+type sway_etc_t;
+files_config_file(sway_etc_t)
+
+type sway_xdg_config_t;
+xdg_config_content(sway_xdg_config_t)
+
+type sway_runtime_t;
+files_runtime_file(sway_runtime_t)
diff --git a/policy/modules/session/wayland.te b/policy/modules/session/wayland.te
index c1b93b9c0e..1b3d3a88ab 100644
--- a/policy/modules/session/wayland.te
+++ b/policy/modules/session/wayland.te
@@ -66,6 +66,9 @@ userdom_user_runtime_filetrans(wayland_compositor, wayland_runtime_t, file, "way
# GPU Access
dev_rw_dri(wayland_compositor)
+# libinput
+dev_rw_input_dev(wayland_compositor)
+
files_read_usr_files(wayland_compositor)
# Fonts
@@ -77,5 +80,6 @@ xserver_rw_mesa_shader_cache(wayland_compositor)
optional_policy(`
# For seats
+ systemd_dbus_chat_logind(wayland_compositor)
systemd_use_logind_fds(wayland_compositor)
')