@@ -394,14 +394,182 @@ remove_files() {
394394 cleanup_home_dirs
395395}
396396
397+ # ---------------------------------------------------------------------------
398+ # SELinux AVC collection
399+ # ---------------------------------------------------------------------------
400+
401+ selinux_reports_dir=" ${base_dir} /selinux"
402+ selinux_avc_raw=" ${selinux_reports_dir} /avc-raw.txt"
403+ selinux_avc_report=" ${selinux_reports_dir} /avc-report.txt"
404+ selinux_audit2allow_te=" ${selinux_reports_dir} /go_fdo_server_avc.te"
405+ directories+=(" ${selinux_reports_dir} " )
406+
407+ # Timestamp set just before services start; used to scope ausearch to this run.
408+ _avc_start_timestamp=" "
409+
410+ # Record the start of the AVC collection window.
411+ mark_avc_start () {
412+ _avc_start_timestamp=" $( date ' +%m/%d/%Y %H:%M:%S' ) "
413+ log_info " AVC collection window starts at: ${_avc_start_timestamp} "
414+ }
415+
416+ # Warn if go_fdo_server_t is not in permissive mode (non-fatal).
417+ check_go_fdo_server_permissive () {
418+ if ! command -v semanage & > /dev/null; then
419+ log_warn " semanage not found; cannot verify go_fdo_server_t permissive status"
420+ return 0
421+ fi
422+ if semanage permissive -l 2> /dev/null | grep -q ' go_fdo_server_t' ; then
423+ log_info " go_fdo_server_t is in permissive mode"
424+ return 0
425+ fi
426+ if [ " $( getenforce 2> /dev/null) " = " Permissive" ]; then
427+ log_info " SELinux is globally permissive"
428+ return 0
429+ fi
430+ log_warn " go_fdo_server_t is NOT in permissive mode; AVCs may block services"
431+ }
432+
433+ # Ensure auditd is running so that AVC records reach the audit log.
434+ ensure_auditd_running () {
435+ if systemctl is-active --quiet auditd 2> /dev/null; then
436+ log_info " auditd is running"
437+ return 0
438+ fi
439+ log_warn " auditd is not running; attempting to start it"
440+ sudo systemctl start auditd || log_warn " Could not start auditd; AVC collection may be incomplete"
441+ }
442+
443+ # Collect all AVC records for go-fdo-server since _avc_start_timestamp.
444+ collect_avcs () {
445+ log_info " Collecting AVC denials for go-fdo-server"
446+ mkdir -p " ${selinux_reports_dir} "
447+
448+ if ! command -v ausearch & > /dev/null; then
449+ log_warn " ausearch not found; skipping AVC collection"
450+ echo " ausearch not available" > " ${selinux_avc_raw} "
451+ return
452+ fi
453+
454+ local ausearch_args=(" -m" " avc" " --comm" " go-fdo-server" )
455+ [ -z " ${_avc_start_timestamp} " ] || ausearch_args+=(" -ts" " ${_avc_start_timestamp} " )
456+
457+ sudo ausearch " ${ausearch_args[@]} " > " ${selinux_avc_raw} " 2>&1 || {
458+ local rc=$?
459+ if [ " ${rc} " -eq 1 ]; then
460+ echo " No AVC denials found for go-fdo-server" > " ${selinux_avc_raw} "
461+ log_info " No AVC denials found (policy may already be complete)"
462+ return 0
463+ fi
464+ log_warn " ausearch exited with code ${rc} "
465+ }
466+
467+ local avc_count
468+ avc_count=$( grep -c ' type=AVC' " ${selinux_avc_raw} " 2> /dev/null || echo 0)
469+ log_info " Found ${avc_count} AVC denial(s)"
470+ }
471+
472+ # Generate a draft TE policy snippet from the collected AVC records.
473+ generate_audit2allow_report () {
474+ log_info " Generating audit2allow report"
475+
476+ if ! command -v audit2allow & > /dev/null; then
477+ log_warn " audit2allow not found; skipping TE generation"
478+ return
479+ fi
480+
481+ if [ ! -s " ${selinux_avc_raw} " ] || grep -q " ^No AVC\|^ausearch not" " ${selinux_avc_raw} " ; then
482+ log_info " No AVCs to process with audit2allow"
483+ echo " (no AVC denials to report)" > " ${selinux_audit2allow_te} "
484+ return
485+ fi
486+
487+ {
488+ echo " # Draft SELinux rules generated from go-fdo-server AVC denials"
489+ echo " # Test run: $( date -u --iso-8601=seconds) "
490+ echo " # Policy domain: go_fdo_server_t"
491+ echo " #"
492+ echo " # These rules were produced by audit2allow and must be reviewed"
493+ echo " # before being added to the upstream selinux-policy package."
494+ echo " "
495+ } > " ${selinux_audit2allow_te} "
496+
497+ audit2allow -i " ${selinux_avc_raw} " >> " ${selinux_audit2allow_te} " 2>&1 ||
498+ log_warn " audit2allow exited with a non-zero status"
499+ }
500+
501+ # Print a human-readable AVC summary to stdout and save it as an artefact.
502+ # Artefact paths are only reported when actual denials were found.
503+ report_avcs () {
504+ local has_denials=0
505+ if [ -s " ${selinux_avc_raw} " ] && ! grep -q " ^No AVC\|^ausearch not" " ${selinux_avc_raw} " ; then
506+ has_denials=1
507+ fi
508+
509+ {
510+ echo " ================================================================"
511+ echo " go-fdo-server SELinux AVC Denial Report"
512+ echo " Generated: $( date -u --iso-8601=seconds) "
513+ echo " ================================================================"
514+ echo " "
515+ if [ " ${has_denials} " -eq 0 ]; then
516+ if [ ! -s " ${selinux_avc_raw} " ]; then
517+ echo " No AVC data collected."
518+ else
519+ echo " No AVC denials were recorded during this test run."
520+ fi
521+ else
522+ echo " --- Raw AVC denial records (from ausearch) ---"
523+ echo " "
524+ cat " ${selinux_avc_raw} "
525+ echo " "
526+ echo " --- audit2allow suggested rules ---"
527+ echo " "
528+ cat " ${selinux_audit2allow_te} " 2> /dev/null || echo " (audit2allow output not available)"
529+ fi
530+ echo " "
531+ echo " ================================================================"
532+ } | tee " ${selinux_avc_report} "
533+
534+ if [ " ${has_denials} " -eq 1 ]; then
535+ log_info " AVC report saved to: ${selinux_avc_report} "
536+ log_info " Draft TE file saved to: ${selinux_audit2allow_te} "
537+ fi
538+ }
539+
540+ # Override start_services to record the AVC start timestamp and check SELinux
541+ # status before any service is launched.
542+ start_services () {
543+ log_info " Checking SELinux status"
544+ getenforce 2> /dev/null || log_warn " getenforce not available"
545+ check_go_fdo_server_permissive
546+ ensure_auditd_running
547+ mark_avc_start
548+
549+ log_info " Adding hostnames to '/etc/hosts'"
550+ set_hostnames
551+ log_info " Starting Services"
552+ for service in " ${services[@]} " ; do
553+ log " ⚙ Starting service ${service} "
554+ start_service " ${service} "
555+ log_success
556+ done
557+ }
558+
397559on_failure () {
398560 trap - ERR
561+ collect_avcs
562+ generate_audit2allow_report
563+ report_avcs
399564 save_logs
400565 stop_services
401566 test_fail
402567}
403568
404569cleanup () {
570+ collect_avcs
571+ generate_audit2allow_report
572+ report_avcs
405573 [ ! -v " PACKIT_COPR_RPMS" ] || save_logs
406574 stop_services
407575 unset_hostnames
0 commit comments