Skip to content

Commit 409e048

Browse files
committed
Merge branch 'master' into ai
# Conflicts: # debian/security-misc-shared.postinst # usr/bin/remount-secure#security-misc-shared # usr/libexec/security-misc/check-for-usb-controller#security-misc-shared # usr/share/lintian/overrides/security-misc-shared#security-misc-shared # usr/share/security-misc/lkrg/lkrg-virtualbox#security-misc-shared
2 parents 24b39b0 + c77beac commit 409e048

32 files changed

Lines changed: 857 additions & 267 deletions

‎.github/workflows/local-permission-hardener-test.yml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
## space is parsed as one entry instead of being split and silently
1212
## dropped. See ci/tests/permission_hardener/test_whitespace_filename.sh.
1313

14+
## FIXME: The actual scripts run here should be in dist-ai.
15+
16+
## WARNING: The new test scripts will not be reviewed by humans as they are
17+
## slated to be moved to dist-ai. This workflow file has been reviewed.
18+
1419
name: Test permission-hardener
1520

1621
on:

‎changelog.upstream‎

Lines changed: 708 additions & 0 deletions
Large diffs are not rendered by default.

‎ci/dfuzzer-build.sh‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,12 @@ if [ "${CI:-}" != "true" ] && [ "${ALLOW_LOCAL:-}" != "true" ]; then
4444
fi
4545

4646
DFUZZER_TAG="${DFUZZER_TAG:-v2.6}"
47-
## Pin the exact upstream commit. A tag is mutable; verifying the
48-
## resolved commit hash detects a re-pointed tag (supply-chain guard).
49-
## Keep in sync with DFUZZER_TAG on every version bump.
5047
DFUZZER_COMMIT="${DFUZZER_COMMIT:-a955a80f7dd20fd7aeffad91da1c495aab5dbbd3}"
5148

5249
git clone --depth 1 --branch "${DFUZZER_TAG}" \
5350
https://github.com/dbus-fuzzer/dfuzzer /tmp/dfuzzer
5451

55-
dfuzzer_actual_commit="$(git -C /tmp/dfuzzer rev-parse HEAD)"
52+
dfuzzer_actual_commit="$(git -C /tmp/dfuzzer rev-parse --verify HEAD)"
5653
if [ "${dfuzzer_actual_commit}" != "${DFUZZER_COMMIT}" ]; then
5754
printf '%s\n' "${BASH_SOURCE[0]}: dfuzzer tag ${DFUZZER_TAG} resolved to ${dfuzzer_actual_commit}, expected ${DFUZZER_COMMIT} -- refusing (tag moved?)." >&2
5855
exit 1

‎ci/tests/permission_hardener/test_state_spaced_filename.sh‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
## AI-Assisted
66

7+
## WARNING: Not human-reviewed, MUST be moved to dist-ai.
8+
79
## Regression test: a hardened file whose path contains spaces must be
810
## un-hardenable via 'disable'.
911
##

‎ci/tests/permission_hardener/test_whitelists_disable_all.sh‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
## AI-Assisted
66

7+
## WARNING: Not human-reviewed, MUST be moved to dist-ai.
8+
79
## Regression test: the documented special directive 'whitelists_disable_all=true'
810
## must be honored, not rejected.
911
##

‎ci/tests/permission_hardener/test_whitespace_filename.sh‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
## AI-Assisted
66

7+
## WARNING: Not human-reviewed, MUST be moved to dist-ai.
8+
79
## Regression test: permission-hardener must parse a config filename that
810
## contains spaces.
911
##

‎debian/changelog‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
security-misc (3:53.6-1) unstable; urgency=medium
2+
3+
* New upstream version (local package).
4+
5+
-- Patrick Schleizer <adrelanos@whonix.org> Tue, 08 Sep 2026 15:30:04 +0000
6+
7+
security-misc (3:53.5-1) unstable; urgency=medium
8+
9+
* New upstream version (local package).
10+
11+
-- Patrick Schleizer <adrelanos@whonix.org> Sun, 06 Sep 2026 16:58:23 +0000
12+
13+
security-misc (3:53.4-1) unstable; urgency=medium
14+
15+
* New upstream version (local package).
16+
17+
-- Patrick Schleizer <adrelanos@whonix.org> Sun, 16 Aug 2026 08:24:20 +0000
18+
119
security-misc (3:53.3-1) unstable; urgency=medium
220

321
* New upstream version (local package).

‎debian/security-misc-shared.install‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ usr/lib/permission-hardener.d/25_default_whitelist_passwd.conf#security-misc-sha
7171
usr/lib/permission-hardener.d/25_default_whitelist_policykit.conf#security-misc-shared => /usr/lib/permission-hardener.d/25_default_whitelist_policykit.conf
7272
usr/lib/permission-hardener.d/25_default_whitelist_postfix.conf#security-misc-shared => /usr/lib/permission-hardener.d/25_default_whitelist_postfix.conf
7373
usr/lib/permission-hardener.d/25_default_whitelist_qubes.conf#security-misc-shared => /usr/lib/permission-hardener.d/25_default_whitelist_qubes.conf
74-
usr/lib/permission-hardener.d/25_default_whitelist_selinux.conf#security-misc-shared => /usr/lib/permission-hardener.d/25_default_whitelist_selinux.conf
7574
usr/lib/permission-hardener.d/25_default_whitelist_spice.conf#security-misc-shared => /usr/lib/permission-hardener.d/25_default_whitelist_spice.conf
7675
usr/lib/permission-hardener.d/25_default_whitelist_ssh.conf#security-misc-shared => /usr/lib/permission-hardener.d/25_default_whitelist_ssh.conf
7776
usr/lib/permission-hardener.d/25_default_whitelist_sudo.conf#security-misc-shared => /usr/lib/permission-hardener.d/25_default_whitelist_sudo.conf

‎debian/security-misc-shared.postinst‎

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,16 @@ permission_hardening_legacy_config_folder() {
3131
}
3232

3333
permission_hardening() {
34-
echo "Running SUID Disabler and Permission Hardener... See also:"
35-
echo "https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener"
36-
echo "$0: INFO: running: permission-hardener enable"
34+
printf '%s\n' "Running SUID Disabler and Permission Hardener... See also:"
35+
printf '%s\n' "https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener"
36+
printf '%s\n' "$0: INFO: running: permission-hardener enable"
3737
## By design: report error but return 0 to avoid breaking APT.
3838
## A failing postinst would leave the package in a broken state.
3939
if ! permission-hardener enable ; then
40-
echo "$0: ERROR: Permission hardening failed." >&2
40+
printf '%s\n' "$0: ERROR: Permission hardening failed." >&2
4141
return 0
4242
fi
43-
echo "$0: INFO: Permission hardening success."
43+
printf '%s\n' "$0: INFO: Permission hardening success."
4444
}
4545

4646
fix_pkexec_remembered_permissions() {
@@ -173,25 +173,23 @@ case "$1" in
173173
## Build the org.freedesktop.FileManager1 shim backend.
174174
build_fm_shim_backend
175175

176-
## Compile emerg-shutdown into /usr/bin (on-target, so an
177-
## Architecture: all package still gets a correct per-arch binary);
178-
## the boot-time script then only copies it into /run.
176+
## Pre-compile emerg-shutdown.
179177
build_emerg_shutdown
180178
;;
181179

182180
abort-upgrade|abort-remove|abort-deconfigure)
183181
;;
184182

185183
triggered)
186-
echo "INFO: triggered ${DPKG_MAINTSCRIPT_PACKAGE}: '${DPKG_MAINTSCRIPT_PACKAGE}' ${DPKG_MAINTSCRIPT_PACKAGE} DPKG_MAINTSCRIPT_NAME: '${DPKG_MAINTSCRIPT_NAME}' $\*: '$*' 2: '$2'"
184+
printf '%s\n' "INFO: triggered ${DPKG_MAINTSCRIPT_PACKAGE}: '${DPKG_MAINTSCRIPT_PACKAGE}' ${DPKG_MAINTSCRIPT_PACKAGE} DPKG_MAINTSCRIPT_NAME: '${DPKG_MAINTSCRIPT_NAME}' $\*: '$*' 2: '$2'"
187185
/usr/share/security-misc/lkrg/lkrg-virtualbox || true
188186
/usr/libexec/security-misc/mmap-rnd-bits || true
189187
permission_hardening
190188
exit 0
191189
;;
192190

193191
*)
194-
echo "${DPKG_MAINTSCRIPT_NAME} called with unknown argument \`$1'" >&2
192+
printf '%s\n' "${DPKG_MAINTSCRIPT_NAME} called with unknown argument \`$1'" >&2
195193
exit 1
196194
;;
197195
esac
@@ -207,7 +205,7 @@ permission_hardening
207205
## https://bugs.debian.org/481542
208206
if command -v update-grub >/dev/null 2>&1; then
209207
update-grub || \
210-
echo "${DPKG_MAINTSCRIPT_PACKAGE} ${DPKG_MAINTSCRIPT_NAME} ERROR: Running \
208+
printf '%s\n' "${DPKG_MAINTSCRIPT_PACKAGE} ${DPKG_MAINTSCRIPT_NAME} ERROR: Running \
211209
'update-grub' failed with exit code $?. ${DPKG_MAINTSCRIPT_PACKAGE} is most \
212210
likely only the trigger, not the cause. Unless you know this is not an issue, \
213211
you should fix running 'update-grub', otherwise your system might no longer \

‎usr/bin/permission-hardener#security-misc-shared‎

Lines changed: 48 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -403,10 +403,7 @@ load_late_nosuid_policy() {
403403
load_state_without_policy() {
404404
local line sf_owner sf_group sf_mode sf_path
405405

406-
## Load the state file from disk. Each dpkg-statoverride entry is
407-
## 'owner group mode path'; the path is last and may contain spaces, so read
408-
## the three fixed fields and take the remainder as the path. A plain 4-way
409-
## split would drop any spaced path -- it could then never be un-hardened.
406+
## Load the state file from disk.
410407
if [ -f "${state_file}" ]; then
411408
while read -r line; do
412409
read -r sf_owner sf_group sf_mode sf_path <<< "${line}"
@@ -434,7 +431,7 @@ load_state() {
434431
## to mean that all whitelisting should be ignored.
435432

436433
local config_file line field_list policy_nosuid_file_item policy_file_item
437-
local field_count recovered_file_name mode_index fallback_index candidate_index
434+
local one_field field_count fso_name meta_list field_index hit_barrier
438435

439436
## Load configuration, deferring whitelist handling until later
440437
for config_file in \
@@ -458,9 +455,6 @@ load_state() {
458455
continue
459456
fi
460457

461-
## Recognize the special directive before the character-class check below,
462-
## whose allowed set excludes '=' and would otherwise reject and abort on
463-
## this documented line.
464458
if [ "${line}" = 'whitelists_disable_all=true' ]; then
465459
whitelists_disable_all=true
466460
log info "whitelists_disable_all=true"
@@ -477,63 +471,44 @@ load_state() {
477471

478472
processed_config_line="${line}"
479473

480-
IFS=' ' read -r -a field_list <<< "${line}"
481-
482-
## A filename may contain spaces. The option grammar is unambiguous at the
483-
## END of a line -- either a single trailing whitelist keyword, or a
484-
## mode/owner/group[/capability] tail whose first field is the octal mode
485-
## -- so recover the filename by parsing options from the right and
486-
## rejoining everything before them. Space-free lines are left unchanged.
487-
## The mode tail has a fixed width -- 3 fields (mode owner group) or 4
488-
## (mode owner group capability) -- so anchor the mode from the RIGHT. A
489-
## left-to-right scan misanchors when a space-delimited filename chunk is
490-
## itself a bare octal (e.g. '/path/a 744 name 0744 root root').
491-
## Two readings can be lexically valid when a filename component OR a
492-
## numeric owner looks octal ('/a 744 0644 root root' wants the spaced
493-
## name; '/foo 0744 1000 root cap' wants no recovery). Disambiguate by
494-
## which candidate exists on disk -- the tool skips nonexistent targets
495-
## anyway -- keeping the no-recovery reading when field 1 is really the mode.
496-
## Limitation: consecutive spaces collapse and quoting/escaping is not
497-
## supported; a line whose field count is still invalid after recovery is
498-
## rejected loudly (exit 200 below), not silently skipped.
474+
## We can handle filenames with spaces. This is because the first item
475+
## after a filename is either an octal file mode or a keyword, and we
476+
## only support user/group names, not UIDs and GIDs, as owner
477+
## identifiers. This means that we can scan from right to left for the
478+
## furthest-right octal integer or keyword field and use it to separate
479+
## the filename from the rest of the options. (If usernames could
480+
## themselves be octal integers, this would break, but adduser.conf's
481+
## default NAME_REGEX forbids this. This is definitely a hack, but the
482+
## alternative is to change the format of the policy files, which would
483+
## break custom config for users.
484+
##
485+
## 'read' will collapse consecutive spaces when splitting on spaces.
486+
## Convert spaces into newlines first, then split on newlines with a
487+
## loop.
488+
field_list=()
489+
while IFS= read -r one_field; do
490+
field_list+=( "${one_field}" )
491+
done < <(printf '%s\n' "${line}" | tr ' ' '\n')
499492
field_count="${#field_list[@]}"
500-
if (( field_count > 2 )); then
501-
case "${field_list[field_count-1]}" in
502-
exactwhitelist|matchwhitelist|disablewhitelist|nosuid)
503-
recovered_file_name="$(IFS=' '; printf '%s' "${field_list[*]:0:field_count-1}")"
504-
field_list=( "${recovered_file_name}" "${field_list[field_count-1]}" )
505-
;;
506-
*)
507-
## The octal mode sits at field_count-3 (3-field tail) or
508-
## field_count-4 (4-field tail with capability). Both positions can
509-
## look octal -- a numeric owner, or a filename component -- so pick
510-
## the candidate whose recovered filename exists on disk (the tool
511-
## skips nonexistent targets anyway). A mode at field 1 means a
512-
## single-field, no-space filename: nothing to recover. Fall back to
513-
## the first (rightmost) octal candidate when neither name exists.
514-
mode_index=''
515-
fallback_index=''
516-
for candidate_index in "$(( field_count - 3 ))" "$(( field_count - 4 ))"; do
517-
(( candidate_index >= 1 )) || continue
518-
[[ "${field_list[candidate_index]}" =~ ^0?[0-7]{3,4}$ ]] || continue
519-
[ -z "${fallback_index}" ] && fallback_index="${candidate_index}"
520-
recovered_file_name="$(IFS=' '; printf '%s' "${field_list[*]:0:candidate_index}")"
521-
if (( candidate_index == 1 )) || [ -e "${recovered_file_name}" ]; then
522-
mode_index="${candidate_index}"
523-
break
524-
fi
525-
done
526-
[ -z "${mode_index}" ] && mode_index="${fallback_index}"
527-
if [ -n "${mode_index}" ] && (( mode_index > 1 )); then
528-
recovered_file_name="$(IFS=' '; printf '%s' "${field_list[*]:0:mode_index}")"
529-
field_list=( "${recovered_file_name}" "${field_list[@]:mode_index}" )
530-
fi
531-
;;
532-
esac
533-
fi
534493

535-
case "${#field_list[@]}" in
536-
2|4|5)
494+
hit_barrier='false'
495+
fso_name=""
496+
meta_list=()
497+
for (( field_index = field_count - 1; field_index >= 0; \
498+
field_index-- )); do
499+
if [ "${hit_barrier}" = 'false' ]; then
500+
if [[ "${field_list[field_index]}" =~ ^[0-7]{3,4}$ ]] \
501+
|| [[ "${field_list[field_index]}" =~ ^(nosuid|exactwhitelist|matchwhitelist|disablewhitelist)$ ]]; then
502+
hit_barrier='true'
503+
fi
504+
meta_list=( "${field_list[field_index]}" "${meta_list[@]}" )
505+
else
506+
fso_name="${field_list[field_index]}${fso_name:+" ${fso_name}"}"
507+
fi
508+
done
509+
510+
case "${#meta_list[@]}" in
511+
1|3|4)
537512
true
538513
;;
539514
*)
@@ -544,29 +519,29 @@ load_state() {
544519
esac
545520

546521
# Strip trailing slash if appropriate
547-
field_list[0]="${field_list[0]%/}"
522+
fso_name="${fso_name%/}"
548523

549-
case "${field_list[1]}" in
524+
case "${meta_list[0]}" in
550525
'exactwhitelist')
551-
[ ! -e "${field_list[0]}" ] && continue
552-
policy_exact_white_list+=( "${field_list[0]}" )
526+
[ ! -e "${fso_name}" ] && continue
527+
policy_exact_white_list+=( "${fso_name}" )
553528
continue
554529
;;
555530
'matchwhitelist')
556-
policy_match_white_list+=( "${field_list[0]}" )
531+
policy_match_white_list+=( "${fso_name}" )
557532
continue
558533
;;
559534
'disablewhitelist')
560-
policy_disable_white_list+=( "${field_list[0]}" )
535+
policy_disable_white_list+=( "${fso_name}" )
561536
continue
562537
;;
563538
'nosuid')
564-
[ ! -e "${field_list[0]}" ] && continue
565-
policy_nosuid_file_list+=( "${field_list[0]}" )
539+
[ ! -e "${fso_name}" ] && continue
540+
policy_nosuid_file_list+=( "${fso_name}" )
566541
;;
567542
*)
568-
[ ! -e "${field_list[0]}" ] && continue
569-
add_to_policy "${field_list[@]}"
543+
[ ! -e "${fso_name}" ] && continue
544+
add_to_policy "${fso_name}" "${meta_list[@]}"
570545
;;
571546
esac
572547
done < "${config_file}"

0 commit comments

Comments
 (0)