Description
The ModifierGroup directive in /etc/selinux/*/setrans.conf is completely broken in mcstrans 3.6-1.el9. All ModifierGroup configurations fail silently, with translation functions returning input unchanged. Both raw→translated and translated→raw directions fail with no error messages.
This affects both custom user configurations and Red Hat's official NATO example in /usr/share/mcstrans/examples/nato/.
—
Version-Release number of selected component
mcstrans-3.6-1.el9
—
How reproducible
Always - 100% reproducible
—
Steps to Reproduce
1. Create ModifierGroup configuration:
cat > /etc/selinux/mls/setrans.d/cats.conf << 'EOF'
ModifierGroup=Categories
Whitespace=,
Join=,
Default=c1.c2
c1=Apples
c2=Bananas
EOF
2. Update main config to include it:
cat >> /etc/selinux/mls/setrans.conf << 'EOF'
Include=/etc/selinux/mls/setrans.d/cats.conf
EOF
3. Restart mcstrans:
systemctl restart mcstrans
4. Test translation (BOTH directions):
python3 << 'EOF' import selinux # Test 1: raw_to_trans (used by ls -Z) print("=== Test 1: raw_to_trans (reading) ===") result1 = selinux.selinux_raw_to_trans_context("system_u:object_r:user_tmp_t:s0:c1,c2") print(f"Result: {result1}") # Test 2: trans_to_raw (used by chcon -l) print("\n=== Test 2: trans_to_raw (writing) ===") result2 = selinux.selinux_trans_to_raw_context("system_u:object_r:user_tmp_t:SystemLow:Apples,Bananas") print(f"Result: {result2}") EOF
—
Actual results
=== Test 1: raw_to_trans (reading) === Result: [0, 'system_u:object_r:user_tmp_t:s0:c1,c2'] === Test 2: trans_to_raw (writing) === Result: [0, 'system_u:object_r:user_tmp_t:SystemLow:Apples,Bananas']
BOTH directions FAIL - returns input unchanged with no error.
—
Expected results
=== Test 1: raw_to_trans (reading) === Result: [0, 'system_u:object_r:user_tmp_t:SystemLow:Apples,Bananas'] === Test 2: trans_to_raw (writing) === Result: [0, 'system_u:object_r:user_tmp_t:s0:c1,c2']
Translation should convert between raw and human-readable formats using ModifierGroup definitions.
—
Additional info
Source Code Analysis
Root cause mechanism identified:
trans_context() in mcstrans.c (lines 1660-1679) always returns 0 (success) even when translation fails:
int trans_context(const char *incon, char **rcon) { // ... translation logic ... if (trans) { *rcon = new_context_str(incon, trans); // Success } else { *rcon = new_context_str(incon, range); // FAILURE - returns input unchanged } return 0; // ⚠️ Always returns success! }
This causes silent failure - no error messages, no warnings, making debugging impossible.
Tested Configurations
1. User custom config - FAILS
2. Red Hat NATO example (/usr/share/mcstrans/examples/nato/) - FAILS
3. Both raw→translated and translated→raw directions - BOTH FAIL
Workaround
Use old-style explicit category translations:
s1:c1=Unclassified:Apples s1:c2=Unclassified:Bananas s1:c1,c2=Unclassified:Apples,Bananas
Limitation: Not scalable - must define every combination explicitly.
Related Components
This bug also affects libselinux's silent failure handling - see separate bug for libselinux component.
Debug Recommendations
Enable debug logging by recompiling mcstrans with -DDEBUG flag to identify exact failure point in ModifierGroup translation logic.
Most likely cause: Default=c1.c2 parsing error causing empty word bitmaps in add_word() function.
—
Environment
- OS: RHEL 9
- SELinux Policy: MLS
- SELinux Mode: Enforcing
- mcstrans version: 3.6-1.el9
—