Red Hat Bugzilla – Bug 1412838
Running passwd changes the security context of /etc/security/opasswd
Last modified: 2018-04-10 08:26:56 EDT
Description of problem: A user with an expired password logging in through a virtual terminal is unable to change their password and receives the error: "authentication token manipulation error". This does not affect the same user logging in through GDM. Users without expired passwords are able to change them just fine using passwd /var/log/auth.log shows: login: pam_unix(login:chauthtok): can't open /etc/security/opasswd ls -lZ /etc/security/opasswd rw- --- --- root root system_u:object_r:shadow_t:s0 A different user changes their password using passwd ls -lZ /etc/security/opasswd rw- --- --- root root system_u:object_r:passwd_file_t:s0 At this point users with expired passwords can successfully change their passwords when logging in through a virtual console. No error messages in /var/log/auth.log Version-Release number of selected component (if applicable): RHEL 7.3 How reproducible: 100% Steps to Reproduce: 1. Create user1 and expire passwd 2. Create user2 with valid/non-expired passwd 3. Enable password history in pam 4. Set SELinux to enforcing 5. Attempt to logon to a virtual console as user1. Enter valid existing password and a new password that meets complexity requirements. Will get an error. 6. Login as user2. Change user2's password. 7. ls -lZ /etc/security/opasswd; context will have changed 8. Attempt to logon to a virtual console as user1. Enter valid existing password and a new password that meets complexity requirements. user1 successfully is logged in. Actual results: user1 is unable to login to the virtual console. SELinux context of /etc/security/opasswd is changed after a user changes their password using passwd Expected results: user1 is able to login to the virtual console. SELinux context of /etc/security/opasswd is not changed after a user changes their password using passwd Additional info:
The correct context of the opasswd file should be shadow_t because we want the same protection of its contents as for /etc/shadow. 1. Please use pam_pwhistory instead of adding remember option to pam_unix. There is no way to make that remember option of pam_unix properly supported with SELinux. Example of system-auth with it: password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= password requisite pam_pwhistory.so use_authtok remember=3 password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok password required pam_deny.so 2. SELinux policy still needs fix as my testing shows that even with pam_pwhistory there is change of the context from shadow_t to etc_t. opasswd is changed by pwhistory_helper which has updpwd_exec_t which means it would be running with updpwd_t domain. Reassigning to selinux-policy for further investigation.
Right now, we have two file transitions for updpwd_t: type_transition updpwd_t etc_t:file shadow_t "gshadow"; type_transition updpwd_t etc_t:file shadow_t "nshadow"; But we need to add following transition rule: type_transition updpwd_t etc_t:file shadow_t "opasswd"; Milos, Could we test this?
Any update on this? It's also still happening on 7.4. Feel free to send me the PP file to test it.
# rpm -qa selinux\* selinux-policy-3.13.1-166.el7_4.8.noarch selinux-policy-targeted-3.13.1-166.el7_4.8.noarch # restorecon -Rv /etc/ # ls -Z /etc/security/opasswd -rw-------. root root unconfined_u:object_r:shadow_t:s0 /etc/security/opasswd # chage -d 0 user1 # Now I logged via ssh as user1 to the same machine and changed my password because it was expired. # ls -Z /etc/security/opasswd -rw-------. root root unconfined_u:object_r:etc_t:s0 /etc/security/opasswd #
The comment above was using the latest RHEL-7.4.z selinux-policy. This comment is using the latest RHEL-7.5 selinux-policy: # rpm -qa selinux\* pam\* pam-1.1.8-22.el7.x86_64 selinux-policy-targeted-3.13.1-186.el7.noarch selinux-policy-3.13.1-186.el7.noarch # restorecon -Rv /etc/ # ls -Z /etc/security/opasswd -rw-------. root root unconfined_u:object_r:shadow_t:s0 /etc/security/opasswd # chage -d 0 user1 # Now I logged via ssh as user1 to the same machine and changed my password because it was expired. # ls -Z /etc/security/opasswd -rw-------. root root unconfined_u:object_r:etc_t:s0 /etc/security/opasswd # From my point of view the bug is NOT fixed.
Following rule is present in the latest RHEL-7.5 policy, but the bug can still be reproduced. # sesearch -s updpwd_t -t etc_t -c file -T | grep opasswd type_transition updpwd_t etc_t : file shadow_t "opasswd"; # The type_transition rule is applied if and only if the opasswd file is created. If the file is created with a different name and renamed to opasswd, the type_transition rule is NOT applied. Can you confirm which way is the /etc/security/opasswd file created and updated?
Running "strace -f -o output.txt passwd" as root revealed following things: 9835 open("/etc/security/opasswd", O_RDONLY) = 3 9835 fstat(3, {st_mode=S_IFREG|0600, st_size=95, ...}) = 0 9835 getpid() = 9835 9835 open("/etc/security/opasswd.tmp48vH27", O_RDWR|O_CREAT|O_EXCL, 0600) = 4 9835 fchmod(4, 0100600) = 0 9835 fchown(4, 0, 0) = 0 9835 fcntl(4, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE) 9835 fstat(3, {st_mode=S_IFREG|0600, st_size=95, ...}) = 0 9835 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5a94109000 9835 read(3, "user1:1000:2:!!,$1$zLPN4Foi$yoiN"..., 4096) = 95 9835 fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 9835 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5a94108000 9835 read(3, "", 4096) = 0 9835 close(3) = 0 9835 munmap(0x7f5a94109000, 4096) = 0 9835 write(4, "user1:1000:2:!!,$1$zLPN4Foi$yoiN"..., 130) = 130 9835 fsync(4) = 0 9835 close(4) = 0 9835 munmap(0x7f5a94108000, 4096) = 0 9835 unlink("/etc/security/opasswd.old") = 0 9835 link("/etc/security/opasswd", "/etc/security/opasswd.old") = 0 9835 rename("/etc/security/opasswd.tmp48vH27", "/etc/security/opasswd") = 0 9835 unlink("/etc/security/opasswd.tmp48vH27") = -1 ENOENT (No such file or dir ectory)
Did you use pam_pwhistory? I suppose you did.
Can there be a type transition rule with wildcard name?
The only difference between the password section in comment#3 and password section in my /etc/pam.d/system-auth file was: md5 vs. sha512 on the "password sufficient pam_unix.so" line.
Unfortunately, wildcards are not supported. But I can test the scenario with policy which contains a type_transition rule without a specific filename: type_transition updpwd_t etc_t : file shadow_t; Which will apply to any file that is created by a process running as updpwd_t.
I am afraid that would break update of /etc/passwd if you are moving from password has in /etc/passwd into shadowed password in /etc/shadow. What executables are running as updpwd_t? We would have to create a special domain for pwhistory_helper binary which could have such type transition rule, because pwhistory_helper does not write anything else than the opasswd file.
Or could the rule be limited just to the /etc/security subdirectory?
If I load a special policy module, so that policy contains following rule: # sesearch -s updpwd_t -t etc_t -T Found 1 semantic te rules: type_transition updpwd_t etc_t : file shadow_t; ... before password change and after password change the label remains the same: # ls -Z /etc/security/opasswd -rw-------. root root unconfined_u:object_r:shadow_t:s0 /etc/security/opasswd # Also "restorecon -Rv /etc" did not find any mislabeled objects under /etc.
# semanage fcontext -l | grep updpwd_exec_t /sbin/unix_update regular file system_u:object_r:updpwd_exec_t:s0 /usr/sbin/unix_update regular file system_u:object_r:updpwd_exec_t:s0 /usr/sbin/pwhistory_helper regular file system_u:object_r:updpwd_exec_t:s0 #
But try this - put your password hash from /etc/shadow to /etc/passwd instead of the x and try to change the password. Won't it change /etc/passwd to shadow_t?
After connecting via SSH I executed passwd as user1 and the change of password was successful. The hash in /etc/shadow is different and the hash in /etc/passwd got replaced by "x". Unfortunately, if I made the user1 password expired (chage -d 0 user1) and then I connected via SSH as user1, the login process didn't tell me to change my password.
But what is the context of /etc/passwd now? Even if it is correct, I am a little bit afraid of such general rule. We certainly would have to test things around changing passwords thoroughly. The /etc/shadow is not consulted if /etc/passwd password hash is not 'x' AFAIK.
In both cases the label on /etc/passwd was correct: # ls -Z /etc/passwd -rw-r--r--. root root system_u:object_r:passwd_file_t:s0 /etc/passwd # Tested before and after the password change.
OK, great. unix_update actually tries to preserve the label on the passwd and shadow files. Unfortunately pwhistory_helper does not which is the reason we need this rule.
Please note /etc/security/nopasswd can also be used, suffering from the same problem: #define OLD_PASSWORDS_FILE "/etc/security/opasswd" ... #define OPW_TMPFILE "/etc/security/nopasswd" ... pwfile = fopen(OPW_TMPFILE, "w"); ... opwfile = fopen(OLD_PASSWORDS_FILE, "r"); ... if (!err) { if (rename(OPW_TMPFILE, OLD_PASSWORDS_FILE)) err = 1; } I suppose the current change in the selinux-policy package does not cover this scenario. Does the type transition for this file need be added to the policy, too?
Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://access.redhat.com/errata/RHBA-2018:0763