Hot Take Selinux user_u compatibility Fix

ChromeOS & Linux
1 Reply 30 Views

Victor M

Level 28
Verified
Top Poster
Well-known
FedoraGnome-user_t-compat-test-v1.0.sh was built as a standalone, removable SELinux compatibility module for Fedora GNOME systems where a desktop login is mapped to user_u and therefore normally runs applications in user_t. It does not alter the login mapping, disable SELinux, make user_t permissive, or change PAM.

It also worked for Fedora Cosmic systems.

You confine a regular user : sudo semanage login -a -s user_u <user account name>
and then you relable the files in their directory: sudo restorecon -RFv /home/<user account name>/

In short, after making an account user_u confined, you will find that the desktop icons are gone. And you cannot execute apps like LibreOffice Writer or Disks.

This module fixes it.

Code:
#!/usr/bin/bash
# FedoraGnome user_t compatibility test v1.0
# Installs only the previously established FedoraBraveVault v2.4j-v2.4v
# GTK/Glycin/bubblewrap user_t rules plus earlier Fedora GNOME user_u rules.
# Usage: sudo /usr/bin/bash FedoraGnome-user_t-compat-test-v1.0.sh {install|status|uninstall}
set -euo pipefail
IFS=$'\n\t'
MODULE=fedora_gnome_user_t_compat_test
WORKDIR=/var/lib/$MODULE
TE=$WORKDIR/$MODULE.te
PP=$WORKDIR/$MODULE.pp
die(){ echo "ERROR: $*" >&2; exit 1; }
log(){ echo "[FedoraGnome-user_t-compat-test] $*"; }
[[ ${EUID:-$(id -u)} -eq 0 ]] || die "run as root"
command -v getenforce >/dev/null || die "SELinux tools unavailable"
[[ $(getenforce) != Disabled ]] || die "SELinux is disabled"

status_module(){
  semodule -l | awk '{print $1}' | grep -Fxq "$MODULE" || { log "module status: NOT INSTALLED"; return 1; }
  log "module status: INSTALLED"
  command -v sesearch >/dev/null || { log "sesearch unavailable; per-rule check skipped"; return 0; }
  local checks=(
    proc_t:dir:mounton proc_t:filesystem:mount self:netlink_route_socket:nlmsg_write
    tmpfs_t:filesystem:mount fs_t:filesystem:remount user_tmp_t:file:mounton
    devpts_t:filesystem:mount fs_t:filesystem:unmount fonts_cache_t:dir:mounton
    tmpfs_t:filesystem:unmount root_t:dir:mounton tmp_t:dir:mounton
    systemd_hwdb_etc_t:file:read dma_device_t:chr_file:open
    dri_device_t:chr_file:open sound_device_t:chr_file:open
  )
  local x tgt cls perm hit missing=0
  for x in "${checks[@]}"; do
    tgt=${x%%:*}; x=${x#*:}; cls=${x%%:*}; perm=${x#*:}
    if [[ $tgt == self ]]; then
      hit=$(sesearch -A -s user_t -c "$cls" -p "$perm" 2>/dev/null || true)
    else
      hit=$(sesearch -A -s user_t -t "$tgt" -c "$cls" -p "$perm" 2>/dev/null || true)
    fi
    if [[ -n ${hit//[[:space:]]/} ]]; then
      printf 'PASS  user_t -> %s:%s %s\n' "$tgt" "$cls" "$perm"
    else
      printf 'FAIL  user_t -> %s:%s %s\n' "$tgt" "$cls" "$perm"; missing=1
    fi
  done
  ((missing==0))
}

install_module(){
  for c in checkmodule semodule_package semodule; do command -v "$c" >/dev/null || die "required command missing: $c"; done
  install -d -o root -g root -m 0700 "$WORKDIR"
  cat >"$TE" <<'EOF'
module fedora_gnome_user_t_compat_test 1.0;
require {
 type user_t; type proc_t; type tmpfs_t; type fs_t; type user_tmp_t;
 type devpts_t; type fonts_cache_t; type root_t; type tmp_t;
 type systemd_hwdb_etc_t; type dma_device_t; type dri_device_t; type sound_device_t;
 class dir mounton;
 class file { getattr open read map mounton };
 class filesystem { mount remount unmount };
 class netlink_route_socket { create getattr setattr read write getopt setopt shutdown nlmsg_read nlmsg_write };
 class chr_file { getattr ioctl open read write map };
}
# v2.4j-v2.4v: measured GTK/Glycin/bubblewrap requirements.
allow user_t proc_t:dir mounton;
allow user_t proc_t:filesystem mount;
allow user_t self:netlink_route_socket { create getattr setattr read write getopt setopt shutdown nlmsg_read nlmsg_write };
allow user_t tmpfs_t:filesystem mount;
allow user_t fs_t:filesystem remount;
allow user_t user_tmp_t:file mounton;
allow user_t devpts_t:filesystem mount;
allow user_t fs_t:filesystem unmount;
allow user_t fonts_cache_t:dir mounton;
allow user_t tmpfs_t:filesystem unmount;
allow user_t root_t:dir mounton;
allow user_t tmp_t:dir mounton;
# Earlier Fedora GNOME user_u compatibility additions.
allow user_t systemd_hwdb_etc_t:file { getattr open read map };
allow user_t dma_device_t:chr_file { getattr ioctl open read write map };
allow user_t dri_device_t:chr_file { getattr ioctl open read write map };
allow user_t sound_device_t:chr_file { getattr ioctl open read write map };
EOF
  checkmodule -M -m -o "$WORKDIR/$MODULE.mod" "$TE"
  semodule_package -o "$PP" -m "$WORKDIR/$MODULE.mod"
  semodule -i "$PP"
  log "module installed"
  status_module
  echo
  echo "Log out of yyy completely, then log back into GNOME as yyy."
  echo "Check the taskbar/dock icons, background, Files, Settings and Terminal."
}

uninstall_module(){
  if semodule -l | awk '{print $1}' | grep -Fxq "$MODULE"; then semodule -r "$MODULE"; log "module removed"; else log "module was not installed"; fi
  rm -rf -- "$WORKDIR"
}

case ${1:-} in
 install) install_module ;;
 status) status_module ;;
 uninstall) uninstall_module ;;
 *) die "usage: $0 {install|status|uninstall}" ;;
esac
 
Last edited:
FedoraGnome-user_t-compat-test-v1.0.sh was built as a standalone, removable SELinux compatibility module for Fedora GNOME systems where a desktop login is mapped to user_u and therefore normally runs applications in user_t. It does not alter the login mapping, disable SELinux, make user_t permissive […]


Hi Victor, this is a reasonable removable test workaround, but I would not yet describe it as a general Fedora GNOME/COSMIC compatibility fix.

The important distinction is that every rule has user_t as its source. Therefore, the module affects all processes remaining in user_t, for every account mapped to user_u—it is not scoped to GNOME, COSMIC, LibreOffice, Glycin or bubblewrap.

Several permissions are substantial:

  • mounting, remounting and unmounting filesystems;
  • mounting on root_t, tmp_t and other directories;
  • route-netlink writes;
  • read/write/ioctl/map access to DMA, DRI and sound character devices.

These rules do not magically grant CAP_SYS_ADMIN or bypass DAC, device ACLs and kernel checks. They do, however, remove the SELinux barrier whenever those other controls permit the operation, including inside user namespaces. That is a material relaxation of user_t, even though it is not permissive mode.

The underlying compatibility problem is genuine. Fedora has documented user_t failures involving systemd mount namespacing, including root_t:dir mounton denials in issue #2680. The preferable long-term solution is narrower application-domain policy. For example, Fedora recently added a specific proc mount permission to thumb_t, rather than granting it generally to user_t, in this policy commit.

A few practical corrections would help:

  1. reestorecon is a typo; it should be restorecon.
  2. The script accepts system-wide Permissive mode because it rejects only Disabled. For a functional enforcement test, require:

Code:
   [[ $(getenforce) == Enforcing ]] || die "SELinux must be Enforcing for this test"

3. Replace the hard-coded yyy logout message.
4. status is only a spot check. It checks open for device rules but not read, write, ioctl or map; similarly, it checks only one netlink permission. The self query also lacks -t user_t.
5. uninstall removes the policy module but deliberately leaves the account mapped to user_u. Readers should be told explicitly that the desktop may become unusable again after removal.
6. Keep a separate administrative account available. Fedora’s Confined Users SIG describes user_u as intentionally forbidding escalation through su and sudo; mapping the only administrator is an excellent way to turn a policy experiment into an unscheduled rescue exercise.

For reproducibility, publish the exact Fedora edition/release and these package versions:

Code:
rpm -q selinux-policy selinux-policy-targeted policycoreutils
id -Z

It would also help to provide the relevant AVCs before installation and show that they disappear after installation:

Code:
sudo ausearch -m AVC,USER_AVC -ts recent -i

That should be run from the separate administrative account. AVCs need review rather than automatic approval—the audit2allow documentation itself warns that defining narrower domains or types is often preferable to broad allow rules.

So my verdict is: useful diagnostic and compatibility test, but too broad to recommend as a production fix without the AVC evidence, tested policy versions, and an explanation of why each permission must remain on user_t rather than a narrower domain.

Sources
 

Recently browsing

Members who viewed this thread in the last 5 minutes

Back
Top