Bug 1633756 - ssh-copy-id does not restore correct selinux context on ~/.ssh
Summary: ssh-copy-id does not restore correct selinux context on ~/.ssh
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: openssh
Version: 28
Hardware: All
OS: Linux
unspecified
medium
Target Milestone: ---
Assignee: Jakub Jelen
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2018-09-27 16:18 UTC by Geoff Goas
Modified: 2018-11-04 06:50 UTC (History)
7 users (show)

Fixed In Version: openssh-7.9p1-1.fc29
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2018-11-04 06:50:43 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Geoff Goas 2018-09-27 16:18:44 UTC
Description of problem:

ssh-copy-id (openssh-clients) runs a string of commands, which includes a call to run the restorecon command (policycoreutils). This does not work, however, leaving the ~/.ssh directory with the incorrect selinux context, which means public key authentication will not work.

I experience the issue in attempting to copy my public key to any Fedora/RHEL machine with selinux enabled. Public key auth fails with any machine set to enforcing mode.

Version-Release number of selected component (if applicable):

openssh-clients-7.8p1-2.fc28.x86_64
policycoreutils-2.8-1.fc28.x86_64

How reproducible:

Consistently

Steps to Reproduce:
1. Generate a private/public key pair using ssh-keygen
2. Use ssh-copy-id to copy the public key to another host that has selinux enabled (enforcing or permissive)
3. Run ls -Z ~/.ssh ~/.ssh/authorized_keys on the target host

Actual results:

Both ~/.ssh and ~/.ssh/authorized_keys have the *incorrect* selinux context.

Expected results:

Both ~/.ssh and ~/.ssh/authorized_keys have the *correct* selinux context.

Additional info:

Here is the string of commands executed by ssh-copy-id:

ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys ; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'"

The issue appears to be because restorecon is located in /usr/sbin, and the user does not have /usr/sbin in their path until after having logged in. Here are my tests running against my personal Fedora 28 machine:

$ ssh localhost "exec sh -c 'type restorecon'"
sh: line 0: type: restorecon: not found

$ type restorecon
restorecon is hashed (/usr/sbin/restorecon)

$ which restorecon
/usr/sbin/restorecon

$ sudo -i

# cp /usr/sbin/restorecon /usr/bin
# logout

$ ssh localhost "exec sh -c 'type restorecon'"
restorecon is /usr/bin/restorecon

$ ssh localhost "exec sh  -c 'echo \$PATH'"
/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin

Comment 1 Jakub Jelen 2018-10-01 11:00:15 UTC
Hmm ... the restorecon binary is in /usr/sbin/ for some time already.

The thing is that unless you have /usr/sbin/ in your path on your server (there were some changes around this in past in Fedora), it will not work. But the sbin paths are appended for login shells since Fedora 10 [1], but they are not included for non-login shells which is an issue here. The ssh executes the command in non-login shell and therefore the /etc/profile is not executed.

So what are our ways out?

 * Consider using login shell (-l switch to sh). Not sure how portable this is:

$ ssh localhost "exec sh -l -c 'echo \$PATH'"
[...]/usr/lib64/ccache:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin

 * Fix the setup package to generate correct path also for non-login shells?

This will need some more consideration to make sure we do not break other things by doing so.

[1] https://fedoraproject.org/wiki/Features/SbinSanity

Comment 2 Geoff Goas 2018-10-01 18:08:58 UTC
Thank you for your feedback. 

I pose the following questions to the general audience:

1. Why does restorecon live in /usr/sbin when super user privileges are not required to use it?

2. Where is the path for non-login shells configured?

Comment 3 Jakub Jelen 2018-10-02 10:13:43 UTC
> 1. Why does restorecon live in /usr/sbin when super user privileges are not required to use it?

The sbin directory does contain some other binaries without the requirement to be run with superuser privileges (ifconfig, ...). From man hier, the specification fits:

> /sbin  Like /bin, this directory holds commands needed to boot the system, but which are usually not executed by normal users.

The word _usually_ ... normal users should not need to run restorecon manually.

> 2. Where is the path for non-login shells configured?

The distinguishing between login and non-login shell is not in path, but in arguments. Adding the -l to sh will make the shell login shell and working as you expect.

Comment 4 Geoff Goas 2018-10-02 21:19:48 UTC
Sorry, I should clarify for question #2 -

PATH is different when using sh -c vs. sh -l. PATH is set by /etc/profile when using sh -l. What sets PATH when using sh -c?

Comment 5 Jakub Jelen 2018-10-03 09:01:27 UTC
If I understand correctly what is going on there, the sshd is setting the path environment variable, which is configured during the configure time in spec file:

         --with-default-path=/usr/local/bin:/usr/bin \

This environment is passed to the children which invokes sh. The sh does not touch the environment variables at all if it is not a login shell.

I assume this turns out as a bug in openssh package that was overlooked during the previous Fedora changes referenced in the previous comments.

We should follow the system-wide path settings also in OpenSSH and change the above to

         --with-default-path=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin \

Would you like to test the change? This is server change so you need to update server so it will take any effect. Here is a scratch build:

https://koji.fedoraproject.org/koji/taskinfo?taskID=30024415

Comment 6 Geoff Goas 2018-10-03 16:24:10 UTC
That fixed it. I created a test user and ran ssh-copy-id. Pub key auth works, and the correct selinux contexts are there.

$ ssh localhost "exec sh  -c 'echo \$PATH'"
/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin

With the spec file being what defines the default path, where is /usr/lib64/qt-3.3/bin coming from in my case?

Comment 7 Jakub Jelen 2018-10-03 17:15:34 UTC
Thank you for patience, testing and verifying that it is indeed the issue. I will fix this in the Fedora soon.

The profile.d scripts are for some reasons called from the non-interactive shells so it is appended in one of them:

  grep -r " PATH=" /etc/profile.d/

Comment 8 Geoff Goas 2018-10-04 15:52:28 UTC
Well spotted -

$ grep -r " PATH=" /etc/profile.d/
/etc/profile.d/qt.sh:    *) PATH=$QTDIR/bin:$PATH ;;

Thanks for your time!

Comment 9 Fedora Update System 2018-10-19 11:07:41 UTC
openssh-7.9p1-1.fc29 has been submitted as an update to Fedora 29. https://bodhi.fedoraproject.org/updates/FEDORA-2018-5be740cab4

Comment 10 Fedora Update System 2018-10-20 19:24:16 UTC
openssh-7.9p1-1.fc29 has been pushed to the Fedora 29 testing repository. If problems still persist, please make note of it in this bug report.
See https://fedoraproject.org/wiki/QA:Updates_Testing for
instructions on how to install test updates.
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2018-5be740cab4

Comment 11 Fedora Update System 2018-11-04 06:50:43 UTC
openssh-7.9p1-1.fc29 has been pushed to the Fedora 29 stable repository. If problems still persist, please make note of it in this bug report.


Note You need to log in before you can comment on or make changes to this bug.