📖 ~4 min read • Source: SUSE advisory SUSE-SU-2012:0147-1 (see also SUSE bugzilla)
Related CVEs: CVE-2011-4815 CVE-2009-4492 CVE-2010-0541 CVE-2011-1004 CVE-2011-1005
Upstream summary: Ruby (aka CRuby) before 1.8.7-p357 computes hash values without restricting the ability to trigger hash collisions predictably, which allows context-dependent attackers to cause a denial of service (CPU consumption) via crafted input to an application that maintains a hash table.
Table of contents
Symptom & Impact
ruby is executed by every process started from it, so a flaw here surfaces inside your applications rather than in ruby itself: header-parsing and request-smuggling bugs in the bundled HTTP stack, weaknesses in the runtime’s own TLS and crypto code, unsafe archive, XML or deserialisation handling in the standard library, or memory-safety bugs in the JIT. Long-lived workers such as application servers, JVM daemons and resident node processes keep executing the old build after SLES 12 replaces it on disk, so a patched machine stays exposed until each one is restarted. ruby is an interpreter or virtual machine plus its standard library, not a daemon: it runs only inside processes you start, so there is no ruby unit to restart — restart the applications that execute it instead.
Environment & Reproduction
Reproduction targets SLES 12. Confirm release, registration, and installed package:
cat /etc/os-release
SUSEConnect --status-text
SUSEConnect --list-extensions 2>/dev/null | head -30
rpm -q ruby
zypper info ruby | head -20
Exercise the workload that uses ruby while collecting:
sudo zypper ps # NATIVE SUSE TOOL, no extra package: every running process still using deleted/replaced files, plus the owning service name
sudo zypper ps -s # short table (PID, PPID, UID, login, command, service) without the per-file detail
sudo zypper ps -sss # service names ONLY, one per line - safe to pipe straight into systemctl
sudo journalctl -xe --no-pager | tail -200
sudo tail -200 /var/log/zypp/history
sudo tail -200 /var/log/audit/audit.log
# For SUSE support, bundle evidence with supportconfig:
sudo supportconfig -R /var/tmp -B ruby
Root Cause Analysis
Root cause is documented in SUSE advisory SUSE-SU-2012:0147-1. SUSE security maintainers shipped fixes in the corresponding ruby update for SLES 12; running an outdated build leaves the host exposed to the failure modes described in the advisory. Correlate zypper history with system logs:
sudo zypper history | grep ruby
sudo zypper history --since='-7 days' | tail -40
sudo journalctl -k | grep -i apparmor | tail -100
cat /proc/sys/kernel/tainted # non-zero = tainted kernel / out-of-tree modules
Quick Triage
Run these on SLES 12 to capture the current state of ruby:
rpm -q ruby # installed NVR
rpm -V ruby # verify shipped files
sudo zypper patch-check # open patches
sudo zypper lp -r SUSE-SLE-Server-12-* 2>/dev/null | head
systemctl --failed --no-pager
sudo firewall-cmd --list-all 2>/dev/null || sudo SuSEfirewall2 status 2>/dev/null
sudo aa-status # AppArmor profiles
rpm -ql ruby | grep -E '^/(usr/lib|etc)/systemd/(system|user)/[^/]+\.(service|socket|timer|path|target|mount)$' # the units ruby REALLY ships - NO OUTPUT means it ships no service at all, so never run systemctl on it
rpm -ql ruby | grep -E '^/usr/sbin/rc[^/]+$' # SUSE-only rcNAME compat symlink (it points at /usr/sbin/service, not at a unit): the NAME after 'rc' IS the service name - bind ships /usr/sbin/rcnamed, so the unit is named.service
Step-by-Step Diagnosis
-
List failed systemd units.
systemctl --failed --no-pager -
Tail the journal for
rubyand the system bus.sudo journalctl -xe -f --no-pager -
Inspect firewall posture. This release uses firewalld; SuSEfirewall2 may still be present on SLES 12 GA.
sudo firewall-cmd --list-all-zones sudo SuSEfirewall2 status 2>/dev/null # legacy, only present on early SLES 12 sudo iptables -L -n -v | head -30 -
Surface AppArmor denials and switch the profile to complain mode if needed.
sudo journalctl -k | grep -i 'apparmor="DENIED"' | tail -30 sudo aa-status -
Verify
rubyintegrity and reinstall if anything is altered.sudo rpm -V ruby sudo zypper verify sudo zypper install --force ruby -
Correlate findings with
/var/log/zypp/history,zypper history, and SUSE advisory SUSE-SU-2012:0147-1 to pin the change that introduced the regression.
Solution – Primary Fix
Apply the corrective zypper transaction referenced by SUSE advisory SUSE-SU-2012:0147-1, then reload affected systemd units:
sudo zypper ref # refresh repos
sudo zypper -n patch # apply ALL open patches (recommended)
# Or target a single package:
sudo zypper -n update ruby
sudo systemctl daemon-reload
# Unit name may differ from pkg name; check first:
sudo systemctl daemon-reload # load unit files replaced by the update; this alone restarts nothing
sudo systemctl restart UNIT1.service UNIT2.service # restart several in ONE transaction - systemd applies their own After=/Before= ordering, so low-level units (dbus, database, broker) go before their consumers
sudo systemctl restart UNIT.service # NOTE: 'systemctl reload' is NOT enough after a library patch - the process must re-exec to map the new .so
sudo systemctl reload apparmor.service # only if 'rpm -ql ruby | grep /etc/apparmor.d/' showed the package ships AppArmor profiles
rpm -q ruby # confirm new NVR
For kernel / glibc / systemd / openssl advisories a reboot is required (or SLE Live Patching where licensed):
sudo zypper ps -s # services using deleted libs
sudo systemctl reboot # or: sudo shutdown -r now
# SUSE Live Patching (kgraft / klp) avoids reboot for kernel CVEs:
sudo zypper install -y kernel-livepatch-$(uname -r | tr - _)
klp -v patches # active livepatches
Need help rolling this patch across a SUSE fleet? Our IT Solutions & Services team manages SUSE patch windows with SUSE Manager / RMT and Live Patching. Get in touch for a free consultation.
Solution – Alternative Approaches
If the primary patch is not viable, choose from these:
-
Roll back via Snapper (Btrfs snapshots taken automatically before zypper transactions on SLES 12):
sudo snapper list sudo snapper undochange <pre>..<post> # diff between two snapshot numbers sudo snapper rollback <pre> # boot the host into the chosen snapshot -
Lock the package so zypper cannot upgrade it:
sudo zypper al ruby # add lock zypper ll | grep ruby # list locks sudo zypper rl ruby # remove lock -
Install an older NVR if a regression is suspected:
zypper se -s ruby # show all available versions sudo zypper install --oldpackage ruby-<older-NVR> -
If SuSEfirewall2 is still in use (rare on modern SLES 12), migrate to firewalld:
sudo zypper install -y firewalld sudo systemctl disable --now SuSEfirewall2 sudo systemctl enable --now firewalld -
Disable the AppArmor profile briefly to confirm policy is the cause, then re-enable:
# reproduce, capture denials in the journal: sudo journalctl -k | grep apparmor | tail -
Where SLE Live Patching is licensed, apply kernel fixes without reboot:
klp -v patches # active livepatches sudo zypper install -y kernel-livepatch-$(uname -r | tr - _)
Verification & Acceptance Criteria
All of these should pass after the fix:
rpm -q ruby # expected fixed NVR
sudo zypper patch-check # 0 critical patches outstanding
sudo firewall-cmd --list-services
sudo aa-status | head -5
sudo zypper ps -s # any services still using deleted libs
The conditions described in the advisory must no longer be reported for ruby across two consecutive runs.
Rollback Plan
Capture state before any change:
rpm -qa > /root/rpm-pre.txt
sudo zypper history list > /root/zypper-history-pre.txt
# Snapper takes pre/post snapshots automatically on Btrfs root.
sudo snapper create -d 'pre-patch-ruby' # explicit named snapshot
sudo snapper list | head
To revert if the patch is bad:
# Preferred on Btrfs root — boot the prior snapshot:
sudo snapper rollback <snapshot-id>
sudo systemctl reboot
# Or downgrade just the package:
sudo zypper install --oldpackage ruby-<older-NVR>
sudo systemctl daemon-reload
# Custom security policy cleanup:
Prevention & Hardening
Reduce the chance of this recurring on SLES 12:
-
Enable automatic patch installation:
sudo zypper install -y zypper-automatic sudo systemctl enable --now zypper-automatic.timer # Or use YaST: yast2 online_update_configuration -
Subscribe to sle-security-updates and watch suse.com/support/update.
-
Mirror through SUSE Manager or RMT (Repository Mirroring Tool) for controlled rollouts:
sudo zypper install -y rmt-server rmt-cli sudo rmt-cli sync sudo rmt-cli products enable SLES/12/x86_64 -
Lock sensitive packages so they cannot be auto-upgraded:
sudo zypper al ruby -
Ensure Snapper is enabled on the root subvolume and pre/post hooks run for every zypper transaction:
sudo snapper -c root get-config | head # Default zypper plugin: /usr/lib/zypp/plugins/commit/snapper.zypp-commit-plugin -
Monitor file integrity with AIDE:
sudo zypper install -y aide sudo aide --init && sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db sudo aide --check -
Subscribe to SUSE Live Patching so kernel CVEs can be remediated without reboot:
sudo SUSEConnect -p sle-module-live-patching/12.0/x86_64 sudo zypper install -y kernel-livepatch-$(uname -r | tr - _) klp -v patches -
Keep AppArmor profiles in enforce; review
/etc/apparmor.d/after every package upgrade. -
Apply CIS SUSE Linux Enterprise Server Benchmark hardening.
Related Errors & Cross-Refs
Issues that commonly surface alongside a ruby update: zypper lock contention, systemd unit ordering cycles, AppArmor denials, firewalld zone drift, and kernel taint flags. Useful triage:
sudo zypper ps -s
systemd-analyze critical-chain
sudo journalctl -k | grep apparmor | tail
sudo firewall-cmd --get-active-zones
cat /proc/sys/kernel/tainted
View all sles-12 tutorials on the Tutorials Hub →
Browse all common problems & solutions on the Tutorials Hub.
References & Further Reading
Primary reference: SUSE advisory SUSE-SU-2012:0147-1 (see also SUSE bugzilla). Manual pages useful on SLES 12:
man zypper
man zypper.conf
man systemctl
man journalctl
man firewall-cmd
man snapper
man apparmor
man aa-status
man SUSEConnect
man klp
Other resources: SUSE Linux Enterprise Server 12 documentation, suse.com/security, SUSE security blog, and per-package notes in /usr/share/doc/packages/ruby/ for components implicated in this advisory.