diff --git a/device.te b/device.te
index 788d9cb2e7537f22fcd32737cab3345a76ec2c8a..abe5daaf90c0ebb68252393df8b5f81f358a7a1a 100644
--- a/device.te
+++ b/device.te
@@ -73,3 +73,6 @@ type userdata_block_device, dev_type;
 
 # Cache block device mounted on /cache.
 type cache_block_device, dev_type;
+
+# Block device for any swap partition.
+type swap_block_device, dev_type;
diff --git a/domain.te b/domain.te
index 23803df1ad2fab741ca8ae604aee8b9c7804e7fa..8e9d8c44696fe4a2244554d71ee038831e6022c8 100644
--- a/domain.te
+++ b/domain.te
@@ -102,6 +102,10 @@ allow domain system_file:file r_file_perms;
 allow domain system_file:file execute;
 allow domain system_file:lnk_file r_file_perms;
 
+# Run toolbox.
+# Kernel and init never run anything without changing domains.
+allow { domain -kernel -init } toolbox_exec:file rx_file_perms;
+
 # Read files already opened under /data.
 allow domain system_data_file:dir { search getattr };
 allow domain system_data_file:file { getattr read };
@@ -250,7 +254,7 @@ neverallow domain init:binder *;
 
 # Don't allow raw read/write/open access to block_device
 # Rather force a relabel to a more specific type
-neverallow { domain -kernel -init -recovery -vold -uncrypt -install_recovery } block_device:blk_file { open read write };
+neverallow { domain -kernel -init -recovery -vold -uncrypt -install_recovery -fsck } block_device:blk_file { open read write };
 
 # Don't allow raw read/write/open access to generic devices.
 # Rather force a relabel to a more specific type.
diff --git a/file_contexts b/file_contexts
index aa1cee07983250ad9d90c4f7edef2e6050807c52..2efd7e957fd906591e93ae71affa15b5cbcc7100 100644
--- a/file_contexts
+++ b/file_contexts
@@ -123,6 +123,8 @@
 # System files
 #
 /system(/.*)?		u:object_r:system_file:s0
+/system/bin/e2fsck	--	u:object_r:fsck_exec:s0
+/system/bin/toolbox	--	u:object_r:toolbox_exec:s0
 /system/bin/logcat	--	u:object_r:logcat_exec:s0
 /system/bin/sh		--	u:object_r:shell_exec:s0
 /system/bin/run-as	--	u:object_r:runas_exec:s0
diff --git a/fsck.te b/fsck.te
new file mode 100644
index 0000000000000000000000000000000000000000..57664770b184a6254ed4f2f58f61cc7f1414bd57
--- /dev/null
+++ b/fsck.te
@@ -0,0 +1,26 @@
+# e2fsck or any other fsck program run by init.
+type fsck, domain;
+type fsck_exec, exec_type, file_type;
+permissive_or_unconfined(fsck)
+
+init_daemon_domain(fsck)
+
+# /dev/__null__ created by init prior to policy load,
+# open fd inherited by fsck.
+allow fsck tmpfs:chr_file { read write ioctl };
+
+# Inherit and use pty created by android_fork_execvp_ext().
+allow fsck devpts:chr_file { read write };
+
+# Run e2fsck on block devices.
+# TODO:  Assign userdata and cache block device types to the corresponding
+# block devices in all device policies, and then remove access to
+# block_device:blk_file from here.
+allow fsck block_device:blk_file rw_file_perms;
+allow fsck userdata_block_device:blk_file rw_file_perms;
+allow fsck cache_block_device:blk_file rw_file_perms;
+
+# Only allow entry from init via the e2fsck binary.
+neverallow { domain -init } fsck:process transition;
+neverallow domain fsck:process dyntransition;
+neverallow fsck { file_type fs_type -fsck_exec}:file entrypoint;
diff --git a/init.te b/init.te
index 455442f1215a0f080c68f343dd3cd5d7cdfc0582..a6fadbd573e33ebdbe09f935ab76d34a7e76195c 100644
--- a/init.te
+++ b/init.te
@@ -6,14 +6,8 @@ tmpfs_domain(init)
 
 allow init self:capability { sys_rawio mknod };
 
-# Run helpers from / or /system without changing domain.
-# We do not include exec_type here since generally those
-# should always involve a domain transition.
-allow init rootfs:file execute_no_trans;
-allow init system_file:file execute_no_trans;
-
-# Running e2fsck or mkswap via fs_mgr.
-allow init dev_type:blk_file rw_file_perms;
+# Mounting filesystems from block devices.
+allow init dev_type:blk_file r_file_perms;
 
 # Mounting filesystems.
 # Only allow relabelto for types used in context= mount options,
@@ -121,3 +115,6 @@ neverallow init { file_type fs_type }:file entrypoint;
 # Never read/follow symlinks created by shell or untrusted apps.
 neverallow init shell_data_file:lnk_file read;
 neverallow init app_data_file:lnk_file read;
+
+# init should never execute a program without changing to another domain.
+neverallow init { file_type fs_type }:file execute_no_trans;
diff --git a/toolbox.te b/toolbox.te
new file mode 100644
index 0000000000000000000000000000000000000000..5d7f824d83d6974cf479ac6f19123bbf387b3d76
--- /dev/null
+++ b/toolbox.te
@@ -0,0 +1,26 @@
+# Any toolbox command run by init.
+# At present, the only known usage is for running mkswap via fs_mgr.
+# Do NOT use this domain for toolbox when run by any other domain.
+type toolbox, domain;
+type toolbox_exec, exec_type, file_type;
+permissive_or_unconfined(toolbox)
+
+init_daemon_domain(toolbox)
+
+# /dev/__null__ created by init prior to policy load,
+# open fd inherited by fsck.
+allow toolbox tmpfs:chr_file { read write ioctl };
+
+# Inherit and use pty created by android_fork_execvp_ext().
+allow toolbox devpts:chr_file { read write };
+
+# mkswap-specific.
+# Read/write block devices used for swap partitions.
+# Assign swap_block_device type any such partition in your
+# device/<vendor>/<product>/sepolicy/file_contexts file.
+allow toolbox swap_block_device:blk_file rw_file_perms;
+
+# Only allow entry from init via the toolbox binary.
+neverallow { domain -init } toolbox:process transition;
+neverallow domain toolbox:process dyntransition;
+neverallow toolbox { file_type fs_type -toolbox_exec}:file entrypoint;