📖 ~4 min read • Source: Arch ASA ASA-201711-42
Related CVEs: CVE-2017-16612
Upstream summary: Type: arbitrary code execution. Status: Fixed. Affected: 1.1.14-1. Fixed in: 1.1.15-1. Group: AVG-532.
Table of contents
Symptom & Impact
Nothing executes lib32-libxcursor on its own; its code runs inside whatever links against or imports it, so the exposed surface on an Arch Linux host is the union of every process that has loaded it — web workers, cron jobs, mail handlers, backup agents. The package manager replaces the files on disk, but processes already running keep the old build mapped, and virtualenvs, vendored copies and container images each carry their own copy, so a host can report itself patched while still running vulnerable code. lib32-libxcursor is a library — code loaded by other programs rather than a daemon — so there is no unit to restart and systemctl status lib32-libxcursor will simply report no such unit; restart its consumers instead.
Environment & Reproduction
Reproduction targets Arch Linux. Because Arch is a rolling release, the fix may already be staged in the official repos — always run sudo pacman -Syu first before declaring the host vulnerable. Confirm release and the installed package:
cat /etc/arch-release
cat /etc/os-release
pacman -Qi lib32-libxcursor
pacman -Si lib32-libxcursor # repo (latest) version
pactree lib32-libxcursor | head -40 # reverse/forward deps
Exercise the workload that uses lib32-libxcursor while collecting:
sudo awk '/\(deleted\)/{print $6}' /proc/[0-9]*/maps 2>/dev/null | sort -u | xargs -r -n1 pacman -Qoq 2>/dev/null | sort -u # which packages those stale mappings belong to - proves whether lib32-libxcursor is genuinely one of them
pacman -Ql lib32-libxcursor | awk '$2 ~ /\.so($|\.)/ {print $2}' | sudo grep -lFf - /proc/[0-9]*/maps 2>/dev/null | cut -d/ -f3 | sort -u # PIDs mapping ANY shared object from lib32-libxcursor, deleted or not - the full blast radius
sudo needrestart -l -r l # 'needrestart' package: libraries-only check, list-only mode - reports every service running outdated libs and restarts nothing
sudo journalctl -xe --no-pager | tail -200
sudo tail -200 /var/log/pacman.log
# Optional evidence bundle for support:
sudo journalctl --since today --no-pager > /tmp/journal.txt
Root Cause Analysis
Root cause is documented in Arch ASA ASA-201711-42. Arch packagers ship the fix in the official repos as soon as the upstream tarball is rebuilt; running an outdated mirror or a stale local sync leaves the host exposed. Correlate pacman activity with system logs:
grep -E 'installed|upgraded|removed' /var/log/pacman.log | tail
grep -i lib32-libxcursor /var/log/pacman.log | tail
pacman -Qu # locally available updates
sudo journalctl -p err -b --no-pager | tail -100
cat /proc/sys/kernel/tainted # non-zero = tainted kernel / out-of-tree modules
Quick Triage
Run these on Arch Linux to capture the current state of lib32-libxcursor:
pacman -Qi lib32-libxcursor # installed version + deps
pacman -Qkk lib32-libxcursor # verify shipped files (size/mtime/checksum)
checkupdates # safe update check (pacman-contrib)
pacman -Qu # pending updates from local DB
systemctl --failed --no-pager
sudo nft list ruleset | head -50 # active firewall (nftables backend)
pacman -Ql lib32-libxcursor | awk '$2 ~ /\/systemd\/(system|user)\/[^\/]+$/ {n=split($2,a,"/"); print a[n]}' | sort -u # the REAL unit names, which rarely match the package name (bind -> named.service, postgresql -> postgresql.service)
systemctl list-unit-files --type=service,socket,timer --no-pager | grep -i lib32-libxcursor # fuzzy fallback when the unit name differs from the package name
Step-by-Step Diagnosis
-
List failed systemd units.
systemctl --failed --no-pager -
Tail the journal for
lib32-libxcursorand the system bus.sudo journalctl -xe -f --no-pager -
Inspect firewall posture (Arch defaults to nftables; iptables-nft and ufw are also available).
sudo nft list ruleset sudo iptables -S 2>/dev/null | head -50 sudo ufw status verbose 2>/dev/null || true -
Check that the host is fully synced — the fix may already be live in the repos.
sudo pacman -Syy # refresh repo DBs only checkupdates # show pending updates without touching system pacman -Si lib32-libxcursor | grep -E 'Version|Repository' -
Verify
lib32-libxcursorintegrity and reinstall if any file is altered.sudo pacman -Qkk lib32-libxcursor # Deeper file-level check (pacutils): sudo pacman -S --needed pacutils sudo paccheck --md5sum --quiet lib32-libxcursor sudo pacman -S lib32-libxcursor # reinstall current version -
Correlate findings with
/var/log/pacman.logand Arch ASA ASA-201711-42 to pin the change that introduced the regression.
Solution – Primary Fix
Apply the corrective pacman transaction referenced by Arch ASA ASA-201711-42, then reload affected systemd units. Arch does not support partial upgrades — always do a full system sync, never pacman -Sy lib32-libxcursor on its own:
sudo pacman -Syu # full system upgrade (REQUIRED on Arch)
# Or pull the specific package as part of the same transaction:
sudo pacman -Syu lib32-libxcursor
sudo systemctl daemon-reload
# Unit name may differ from pkg name; check first:
systemctl list-dependencies --reverse UNIT.service --no-pager # what sits on top of each unit: restart order and blast radius
systemctl show -p KillMode -p Type -p Restart UNIT.service # KillMode=control-group (the default) kills the whole cgroup, taking forked children with it. Arch's sshd.service sets KillMode=process so live SSH sessions survive a restart
sudo systemctl restart UNIT.service # for a shared-library CVE you must RESTART, not reload: 'systemctl reload' keeps the same process image and therefore keeps the old library mapped
sudo systemctl reload-or-restart UNIT.service # only where the daemon re-execs on reload; otherwise see the previous line
pacman -Qi lib32-libxcursor | grep -E 'Version|Install Date' # confirm new version
For kernel / glibc / systemd / openssl upgrades a reboot is required (Arch has no live-patch story in base):
# Check whether services or the kernel need a restart (pacman-contrib):
sudo pacman -S --needed pacman-contrib
checkservices 2>/dev/null || true
needrestart 2>/dev/null || true # from the optional needrestart pkg
sudo systemctl reboot # or: sudo shutdown -r now
AUR caveat: packages installed from the AUR are not covered by Arch Security Advisories. Rebuild them against the new repo libs immediately after the system sync:
# AUR packages aren't covered by ASAs; rebuild via paru/yay:
paru -Syu --aur # paru is not part of base; install it from AUR first
# Or with yay:
yay -Syu --aur
Need help rolling this patch across an Arch fleet? Our IT Solutions & Services team supports Arch Linux workstations and container builds with rolling-release patching playbooks. Get in touch for a free consultation.
Solution – Alternative Approaches
If the primary patch is not viable, choose from these:
-
Roll back to an earlier package build from the local cache:
ls /var/cache/pacman/pkg/ | grep ^lib32-libxcursor- | tail sudo pacman -U /var/cache/pacman/pkg/lib32-libxcursor-<old-version>.pkg.tar.zst -
Pin the host to a specific snapshot from the Arch Linux Archive to reproduce a known-good state:
# /etc/pacman.d/mirrorlist (replace all Server lines with): Server = https://archive.archlinux.org/repos/2024/05/01/$repo/os/$arch sudo pacman -Syyuu # downgrade the whole system to that date -
Hold the package temporarily by adding it to
IgnorePkgin/etc/pacman.conf:# /etc/pacman.conf: IgnorePkg = lib32-libxcursor # Lift the hold by removing the line, then run sudo pacman -Syu -
Enable AppArmor for an extra confinement layer (optional, not enabled by default on Arch):
sudo pacman -S apparmor sudo systemctl enable --now apparmor sudo aa-status -
Take a Btrfs / LVM snapshot before kernel / glibc upgrades for fast rollback:
# Btrfs: sudo btrfs subvolume snapshot / /.snapshots/preupgrade # LVM: sudo lvs sudo lvcreate -s -n preupgrade -L 4G /dev/<vg>/<lv> -
Run the affected service inside a hardened systemd-nspawn or Podman container until the host is patched.
Verification & Acceptance Criteria
All of these should pass after the fix:
pacman -Qi lib32-libxcursor | grep Version # expected fixed version
pacman -Qkk lib32-libxcursor # no file changes reported
checkupdates # no further updates pending for the listed CVE packages
sudo nft list ruleset | head
sudo aa-status 2>/dev/null || echo 'AppArmor not in use'
The conditions described in the advisory must no longer be reported for lib32-libxcursor across two consecutive runs.
Rollback Plan
Capture state before any change:
pacman -Qqe > /root/pkglist-pre.txt
sudo cp /var/log/pacman.log /root/pacman.log.pre
# Optional Btrfs/LVM snapshot:
sudo btrfs subvolume snapshot / /.snapshots/preupgrade
sudo lvcreate -s -n preupgrade -L 4G /dev/<vg>/<lv>
To revert if the patch is bad:
# Reinstall the previous build from the local cache:
sudo pacman -U /var/cache/pacman/pkg/lib32-libxcursor-<old-version>.pkg.tar.zst
# Or pin the whole system to a snapshot in the Arch Linux Archive:
# /etc/pacman.d/mirrorlist:
# Server = https://archive.archlinux.org/repos/2024/05/01/$repo/os/$arch
sudo pacman -Syyuu
sudo systemctl daemon-reload
# Or merge the Btrfs / LVM snapshot and reboot:
sudo lvconvert --merge /dev/<vg>/preupgrade && sudo systemctl reboot
Prevention & Hardening
Reduce the chance of this recurring on Arch Linux:
-
Install
pacman-contriband runcheckupdateson a timer so security errata land within hours, not weeks:sudo pacman -S --needed pacman-contrib # Then run checkupdates from a systemd timer or cron: checkupdates && sudo pacman -Syu -
Subscribe to arch-security and watch the Arch Linux security tracker for upstream changes.
-
Run a local mirror for controlled rollouts:
sudo pacman -S --needed rsync rsync -azH --delete rsync://mirrors.kernel.org/archlinux/ /srv/mirror/archlinux/ # Point /etc/pacman.d/mirrorlist on clients at the local mirror. -
Hold sensitive packages via
IgnorePkgin/etc/pacman.confonly when you have a roll-forward plan — do not leave them held indefinitely or you defeat the rolling-release model. -
Monitor file integrity with AIDE:
sudo pacman -S aide sudo aide --init && sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz sudo aide --check -
Enable AppArmor for confinement of network-facing daemons (Arch has no SELinux by default):
sudo pacman -S apparmor sudo systemctl enable --now apparmor sudo aa-status -
Audit AUR helpers and rebuild AUR packages whenever a major repo lib changes (glibc, openssl, icu, etc.).
-
Apply the Arch Linux Security wiki hardening guide and remove unused packages with
pacman -Qtdq.
Related Errors & Cross-Refs
Issues that commonly surface alongside a lib32-libxcursor update: pacman database lock contention, systemd unit ordering cycles, nftables rule drift, partial-upgrade breakage, and kernel taint flags. Useful triage:
sudo pacman -Dk # sanity-check the local pacman DB
systemd-analyze critical-chain
sudo journalctl -p warning -b --no-pager | tail
sudo nft list ruleset
cat /proc/sys/kernel/tainted
checkupdates
View all arch-linux tutorials on the Tutorials Hub →
Browse all common problems & solutions on the Tutorials Hub.
References & Further Reading
Primary reference: Arch ASA ASA-201711-42. Manual pages useful on Arch Linux:
man pacman
man pacman.conf
man systemctl
man journalctl
man nft
man checkupdates
man paccheck
man aa-status
Other resources: wiki.archlinux.org, Arch security tracker, Arch Linux Archive, and per-package notes in /usr/share/doc/lib32-libxcursor/ for components implicated in this advisory.