diff --git a/overlay/usr/bin/set-root-password b/overlay/usr/bin/set-root-password
new file mode 100755
index 0000000..c26a8bd
--- /dev/null
+++ b/overlay/usr/bin/set-root-password
@@ -0,0 +1,56 @@
+#!/bin/sh
+# vim: set sw=4 ts=4 sts=4 et :
+
+if [ -z "${_UNSHARED}" ]; then
+ export _UNSHARED=1
+ exec unshare -m "$0" "$@"
+fi
+unset _UNSHARED
+
+cleanup() {
+ if is_mount -q /etc; then
+ umount -R /etc
+ fi
+ if [ -n "${tmpdir}" ] && [ "${tmpdir}" != / ]; then
+ if is_mount "${tmpdir}"; then
+ umount -R "${tmpdir}"
+ fi
+ rm -rf "${tmpdir}"
+ fi
+ unset tmpdir
+}
+
+is_mount() {
+ awk '
+ BEGIN { rc = 1 }
+ $5 == "'"${1}"'" { rc = 0 }
+ END { exit rc }
+ ' /proc/self/mountinfo
+}
+
+tmpdir=$(mktemp -d)
+trap 'cleanup' INT QUIT TERM EXIT
+mount \
+ -t tmpfs \
+ -o private,rootcontext=system_u:object_r:etc_t:s0 \
+ tmpfs \
+ "${tmpdir}" \
+ || exit
+
+mkdir -p \
+ "${tmpdir}"/etc \
+ "${tmpdir}"/etc/pam.d \
+ "${tmpdir}"/etc/security \
+ "${tmpdir}"/etc/selinux \
+ || exit
+cp -a /etc/passwd /etc/shadow "${tmpdir}"/etc || exit
+mount -o bind /etc/pam.d "${tmpdir}"/etc/pam.d || exit
+mount -o bind /etc/security "${tmpdir}"/etc/security || exit
+mount -o bind /etc/selinux "${tmpdir}"/etc/selinux || exit
+mount --rbind "${tmpdir}"/etc /etc || exit
+
+passwd || exit
+
+mv /etc/shadow "${tmpdir}"/shadow || exit
+umount -R /etc || exit
+cat "${tmpdir}"/shadow > /etc/shadow || exit
diff --git a/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.fc b/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.fc
index 85a4fab..45fee53 100644
--- a/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.fc
+++ b/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.fc
@@ -1,4 +1,5 @@
/usr/bin/system-update -- gen_context(system_u:object_r:aimee_sysupdate_exec_t,s0)
+/usr/bin/set-root-password -- gen_context(system_u:object_r:aimee_set_root_password_exec_t,s0)
/usr/libexec/factory-reset -- gen_context(system_u:object_r:aimee_factory_reset_exec_t,s0)
/usr/libexec/init-storage -- gen_context(system_u:object_r:aimee_storinit_exec_t,s0)
diff --git a/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.if b/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.if
index 4bcb069..8884541 100644
--- a/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.if
+++ b/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.if
@@ -45,3 +45,91 @@ interface(`aimee_os_run_system_update',`
aimee_os_system_update_domtrans($1)
role $2 types aimee_sysupdate_t;
')
+
+########################################
+##
+## Execute set-root-password in the
+## aimee_set_root_password_t domain.
+##
+##
+##
+## Domain allowed to transition.
+##
+##
+#
+interface(`aimee_os_set_root_password_domtrans',`
+ gen_require(`
+ type aimee_set_root_password_t, aimee_set_root_password_exec_t;
+ ')
+
+ domtrans_pattern($1, aimee_set_root_password_exec_t, aimee_set_root_password_t)
+')
+
+########################################
+##
+## Execute set-root-password in the
+## aimee_set_root_password_t domain, and
+## allow the specified role the
+## aimee_set_root_password_t domain.
+##
+##
+##
+## Domain allowed to transition.
+##
+##
+##
+##
+## Role allowed access.
+##
+##
+##
+#
+interface(`aimee_os_run_set_root_password',`
+ gen_require(`
+ type aimee_set_root_password_t;
+ ')
+
+ aimee_os_set_root_password_domtrans($1)
+ role $2 types aimee_set_root_password_t;
+ mount_run(aimee_set_root_password_t, $2)
+')
+
+########################################
+##
+## Execute set-root-password in the caller
+## domain.
+##
+##
+##
+## Domain allowed access.
+##
+##
+#
+interface(`aimee_os_set_root_password_exec',`
+ gen_require(`
+ type aimee_set_root_password_exec_t;
+ ')
+
+ corecmd_search_bin($1)
+ can_exec($1, aimee_set_root_password_exec_t)
+')
+
+########################################
+##
+## Create, read, write, and delete temporary
+## files used by Aimee OS set-root-password.
+##
+##
+##
+## Domain allowed access.
+##
+##
+#
+interface(`aimee_os_manage_set_root_password_tmp_files',`
+ gen_require(`
+ type aimee_set_root_password_tmp_t;
+ ')
+
+ manage_files_pattern($1, aimee_set_root_password_tmp_t, aimee_set_root_password_tmp_t)
+ read_lnk_files_pattern($1, aimee_set_root_password_tmp_t, aimee_set_root_password_tmp_t)
+')
diff --git a/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.te b/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.te
index eeaa03d..6f16f7d 100644
--- a/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.te
+++ b/repos/aimee-os/sec-policy/selinux-aimee-os/files/aimee-os.te
@@ -23,6 +23,13 @@ type aimee_factory_reset_t;
type aimee_factory_reset_exec_t;
init_daemon_domain(aimee_factory_reset_t, aimee_factory_reset_exec_t)
+type aimee_set_root_password_t;
+type aimee_set_root_password_exec_t;
+userdom_user_application_domain(aimee_set_root_password_t, aimee_set_root_password_exec_t)
+
+type aimee_set_root_password_tmp_t;
+files_tmp_file(aimee_set_root_password_tmp_t)
+
########################################
#
# init-storage local policy
@@ -198,6 +205,64 @@ fstools_manage_runtime_files(aimee_factory_reset_t)
miscfiles_read_localization(aimee_factory_reset_t)
storage_raw_rw_fixed_disk(aimee_factory_reset_t)
+########################################
+#
+# set-root-password local policy
+#
+
+gen_require(`
+ class passwd { passwd };
+')
+
+allow aimee_set_root_password_t self:capability { sys_admin };
+allow aimee_set_root_password_t self:fifo_file rw_fifo_file_perms;
+allow aimee_set_root_password_t self:process setfscreate;
+allow aimee_set_root_password_t self:process { ptrace sigkill sigstop signal };
+allow aimee_set_root_password_t self:passwd passwd;
+
+files_tmp_filetrans(aimee_set_root_password_t, aimee_set_root_password_tmp_t, dir)
+manage_dirs_pattern(aimee_set_root_password_t, aimee_set_root_password_tmp_t, aimee_set_root_password_tmp_t)
+manage_files_pattern(aimee_set_root_password_t, aimee_set_root_password_tmp_t, aimee_set_root_password_tmp_t)
+relabel_files_pattern(aimee_set_root_password_t, aimee_set_root_password_tmp_t, aimee_set_root_password_tmp_t)
+
+domain_use_interactive_fds(aimee_set_root_password_t)
+userdom_use_inherited_user_terminals(aimee_set_root_password_t)
+userdom_search_user_home_dirs(aimee_set_root_password_t)
+corecmd_exec_bin(aimee_set_root_password_t)
+selinux_get_fs_mount(aimee_set_root_password_t)
+seutil_read_config(aimee_set_root_password_t)
+miscfiles_read_localization(aimee_set_root_password_t)
+files_mounton_root(aimee_set_root_password_t)
+aimee_os_set_root_password_exec(aimee_set_root_password_t)
+mount_list_runtime(aimee_set_root_password_t)
+fs_getattr_all_fs(aimee_set_root_password_t)
+fs_mount_all_fs(aimee_set_root_password_t)
+fs_unmount_all_fs(aimee_set_root_password_t)
+files_read_var_lib_files(aimee_set_root_password_t)
+files_manage_etc_files(aimee_set_root_password_t)
+files_relabel_etc_files(aimee_set_root_password_t)
+files_manage_etc_dirs(aimee_set_root_password_t)
+auth_manage_shadow(aimee_set_root_password_t)
+auth_relabel_shadow(aimee_set_root_password_t)
+files_mounton_etc_dirs(aimee_set_root_password_t)
+usermanage_domtrans_passwd(aimee_set_root_password_t)
+dev_read_sysfs(aimee_set_root_password_t)
+aimee_os_manage_set_root_password_tmp_files(aimee_set_root_password_t)
+
+gen_require(`
+ type mount_t;
+ type passwd_t;
+')
+allow aimee_set_root_password_t aimee_set_root_password_tmp_t:dir mounton;
+allow mount_t aimee_set_root_password_tmp_t:dir mounton;
+aimee_os_manage_set_root_password_tmp_files(passwd_t)
+
+gen_require(`
+ type sysadm_t;
+ role sysadm_r;
+')
+aimee_os_run_set_root_password(sysadm_t, sysadm_r)
+
########################################
#
# Additional policy rules for Aimee OS-specific behavior