When examining the behavior of shared UID accounts in Linux/Unix systems, we observe that the kernel fundamentally tracks processes and files by numeric UID rather than username. This explains why two entries in /etc/passwd
with identical UID 5000 function as demonstrated:
# Example passwd entries
a1:$1$4zIl1:5000:5000::/home/a1:/bin/bash
a2:$1$bmh92:5000:5000::/home/a2:/bin/bash
The behavior remains consistent across major Unix-like systems including:
- Linux (RHEL, Debian, etc.)
- BSD derivatives (FreeBSD, OpenBSD)
- Commercial Unix (AIX, Solaris)
However, some tools may exhibit edge-case behaviors:
# Sample output variation
$ ls -ln
-rw-r--r-- 1 5000 5000 0 Aug 10 10:00 file1
$ ls -l
-rw-r--r-- 1 a1 5000 0 Aug 10 10:00 file1
While the shared UID approach provides login auditing separation, it introduces these security nuances:
- Process attribution becomes ambiguous in system logs
- SELinux/AppArmor contexts may require special configuration
- SUDO configurations need careful planning
# Example audit log entry
type=USER_AUTH msg=audit(1628607043.248:294): pid=12451 uid=0 auid=4294967295
ses=4294967295 msg='op=PAM:authentication acct="a1" exe="/bin/su" hostname=?'
Appropriate scenarios for shared UID implementation include:
- Service account separation with identical privileges
- Multi-role administrative access requirements
- Containerized environments needing UID namespace consistency
Example Dockerfile implementation:
FROM alpine:latest
RUN adduser -D -u 5000 service1 && \
adduser -D -u 5000 service2
USER 5000
For modern systems, consider these alternatives to shared UIDs:
- Linux capabilities (setcap)
- Filesystem ACLs
- Container user namespaces
- RBAC implementations
# Using capabilities example
$ sudo setcap CAP_NET_BIND_SERVICE=+ep /usr/local/bin/myservice
When two Unix/Linux accounts share the same UID (like in your RHEL5 example with UID 5000), the system treats them as the same user from a permissions perspective. This isn't accidental behavior - it's a fundamental design characteristic of Unix-style systems where the numeric UID is the true identity, while usernames are just human-readable aliases.
# Example /etc/passwd entries demonstrating UID sharing
service_audit:x:5000:5000:Audit Account:/var/empty:/sbin/nologin
service_backup:x:5000:5000:Backup Account:/var/backup:/bin/bash
Key observations from your testing hold true across POSIX systems:
- File ownership displays the first matching username from /etc/passwd (implementation-dependent)
- All processes run under the shared UID have identical privileges
- Password authentication remains separate per account
While the core behavior is standardized by POSIX, edge cases vary:
// BSD systems may handle getpwuid() differently
struct passwd *pwd = getpwuid(5000); // Returns first match
Solaris and AIX have historically shown quirks with NIS/YP integration when UIDs collide.
The practice is common for system accounts but carries risks:
- Pros: Fine-grained audit trails through separate login mechanisms
- Cons: Potential confusion in log analysis (both accounts appear identical in kernel logs)
Modern systems prefer SELinux/AppArmor contexts for better isolation.
Here's how you might properly implement this for a database system:
# /etc/passwd snippet
db_admin:x:5001:5001:DB Admin Account:/opt/db:/bin/bash
db_audit:x:5001:5001:DB Auditor:/opt/db:/bin/rbash
# /etc/shadow snippet
db_admin:$6$rounds=65536$salt$hash:18679:0:90:7:::
db_audit:$6$rounds=65536$diffsalt$diffhash:18679:0:90:7:::
Instead of shared UIDs, consider:
- Linux capabilities (setcap/getcap)
- Containerization with user namespace remapping
- Role-based access control systems
For legacy systems where shared UIDs are unavoidable, implement comprehensive monitoring of both accounts through tools like auditd.