@@ -394,14 +394,172 @@ 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+ report_avcs () {
503+ {
504+ echo " ================================================================"
505+ echo " go-fdo-server SELinux AVC Denial Report"
506+ echo " Generated: $( date -u --iso-8601=seconds) "
507+ echo " ================================================================"
508+ echo " "
509+ if [ ! -s " ${selinux_avc_raw} " ]; then
510+ echo " No AVC data collected."
511+ elif grep -q " ^No AVC\|^ausearch not" " ${selinux_avc_raw} " ; then
512+ echo " No AVC denials were recorded during this test run."
513+ else
514+ echo " --- Raw AVC denial records (from ausearch) ---"
515+ echo " "
516+ cat " ${selinux_avc_raw} "
517+ echo " "
518+ echo " --- audit2allow suggested rules ---"
519+ echo " "
520+ cat " ${selinux_audit2allow_te} " 2> /dev/null || echo " (audit2allow output not available)"
521+ fi
522+ echo " "
523+ echo " ================================================================"
524+ } | tee " ${selinux_avc_report} "
525+
526+ log_info " AVC report saved to: ${selinux_avc_report} "
527+ log_info " Draft TE file saved to: ${selinux_audit2allow_te} "
528+ }
529+
530+ # Override start_services to record the AVC start timestamp and check SELinux
531+ # status before any service is launched.
532+ start_services () {
533+ log_info " Checking SELinux status"
534+ getenforce 2> /dev/null || log_warn " getenforce not available"
535+ check_go_fdo_server_permissive
536+ ensure_auditd_running
537+ mark_avc_start
538+
539+ log_info " Adding hostnames to '/etc/hosts'"
540+ set_hostnames
541+ log_info " Starting Services"
542+ for service in " ${services[@]} " ; do
543+ log " ⚙ Starting service ${service} "
544+ start_service " ${service} "
545+ log_success
546+ done
547+ }
548+
397549on_failure () {
398550 trap - ERR
551+ collect_avcs
552+ generate_audit2allow_report
553+ report_avcs
399554 save_logs
400555 stop_services
401556 test_fail
402557}
403558
404559cleanup () {
560+ collect_avcs
561+ generate_audit2allow_report
562+ report_avcs
405563 [ ! -v " PACKIT_COPR_RPMS" ] || save_logs
406564 stop_services
407565 unset_hostnames
0 commit comments