ssh/tailssh: check IsSELinuxEnforcing in tailscaled process

Checking in the incubator as this used to do fails because
the getenforce command is not on the PATH.

Updates #12442

Signed-off-by: Percy Wegmann <percy@tailscale.com>
This commit is contained in:
Percy Wegmann 2024-06-12 18:02:54 -05:00 committed by Percy Wegmann
parent 02e3c046aa
commit d7fdc01f7f
2 changed files with 38 additions and 16 deletions

View File

@ -121,6 +121,13 @@ func (ss *sshSession) newIncubatorCommand(logf logger.Logf) (cmd *exec.Cmd, err
"--tty-name=", // updated in-place by startWithPTY "--tty-name=", // updated in-place by startWithPTY
} }
// We have to check the below outside of the incubator process, because it
// relies on the "getenforce" command being on the PATH, which it is not
// when in the incubator.
if runtime.GOOS == "linux" && hostinfo.IsSELinuxEnforcing() {
incubatorArgs = append(incubatorArgs, "--is-selinux-enforcing")
}
forceV1Behavior := ss.conn.srv.lb.NetMap().HasCap(tailcfg.NodeAttrSSHBehaviorV1) forceV1Behavior := ss.conn.srv.lb.NetMap().HasCap(tailcfg.NodeAttrSSHBehaviorV1)
if forceV1Behavior { if forceV1Behavior {
incubatorArgs = append(incubatorArgs, "--force-v1-behavior") incubatorArgs = append(incubatorArgs, "--force-v1-behavior")
@ -167,20 +174,21 @@ func (stdRWC) Close() error {
} }
type incubatorArgs struct { type incubatorArgs struct {
loginShell string loginShell string
uid int uid int
gid int gid int
gids []int gids []int
localUser string localUser string
remoteUser string remoteUser string
remoteIP string remoteIP string
ttyName string ttyName string
hasTTY bool hasTTY bool
cmd string cmd string
isSFTP bool isSFTP bool
isShell bool isShell bool
forceV1Behavior bool forceV1Behavior bool
debugTest bool debugTest bool
isSELinuxEnforcing bool
} }
func parseIncubatorArgs(args []string) (incubatorArgs, error) { func parseIncubatorArgs(args []string) (incubatorArgs, error) {
@ -202,6 +210,7 @@ func parseIncubatorArgs(args []string) (incubatorArgs, error) {
flags.BoolVar(&ia.isSFTP, "sftp", false, "run sftp server (cmd is ignored)") flags.BoolVar(&ia.isSFTP, "sftp", false, "run sftp server (cmd is ignored)")
flags.BoolVar(&ia.forceV1Behavior, "force-v1-behavior", false, "allow falling back to the su command if login is unavailable") flags.BoolVar(&ia.forceV1Behavior, "force-v1-behavior", false, "allow falling back to the su command if login is unavailable")
flags.BoolVar(&ia.debugTest, "debug-test", false, "should debug in test mode") flags.BoolVar(&ia.debugTest, "debug-test", false, "should debug in test mode")
flags.BoolVar(&ia.isSELinuxEnforcing, "is-selinux-enforcing", false, "whether SELinux is in enforcing mode")
flags.Parse(args) flags.Parse(args)
for _, g := range strings.Split(groups, ",") { for _, g := range strings.Split(groups, ",") {
@ -338,7 +347,7 @@ func shouldAttemptLoginShell(dlogf logger.Logf, ia incubatorArgs) bool {
return false return false
} }
return runningAsRoot() && !hostinfo.IsSELinuxEnforcing() return runningAsRoot() && !ia.isSELinuxEnforcing
} }
func runningAsRoot() bool { func runningAsRoot() bool {

View File

@ -31,9 +31,22 @@ RUN TAILSCALED_PATH=`pwd`tailscaled ./tailssh.test -test.v -test.run TestIntegra
RUN echo "Then run tests as non-root user testuser and make sure tests still pass." RUN echo "Then run tests as non-root user testuser and make sure tests still pass."
RUN chown testuser:groupone /tmp/tailscalessh.log RUN chown testuser:groupone /tmp/tailscalessh.log
RUN TAILSCALED_PATH=`pwd`tailscaled su -m testuser -c "./tailssh.test -test.v -test.run TestIntegration TestDoDropPrivileges" RUN TAILSCALED_PATH=`pwd`tailscaled su -m testuser -c "./tailssh.test -test.v -test.run TestIntegration TestDoDropPrivileges"
RUN chown root:root /tmp/tailscalessh.log
RUN echo "Then run tests in a system that's pretending to be SELinux in enforcing mode"
RUN mv /usr/bin/login /tmp/login_orig
# Use nonsense for /usr/bin/login so that it fails.
# It's not the same failure mode as in SELinux, but failure is good enough for test.
RUN echo "adsfasdfasdf" > /usr/bin/login
RUN chmod 755 /usr/bin/login
# Simulate getenforce command
RUN printf "#!/bin/bash\necho 'Enforcing'" > /usr/bin/getenforce
RUN chmod 755 /usr/bin/getenforce
RUN TAILSCALED_PATH=`pwd`tailscaled ./tailssh.test -test.v -test.run TestIntegration
RUN mv /tmp/login_orig /usr/bin/login
RUN rm /usr/bin/getenforce
RUN echo "Then remove the login command and make sure tests still pass." RUN echo "Then remove the login command and make sure tests still pass."
RUN chown root:root /tmp/tailscalessh.log
RUN rm `which login` RUN rm `which login`
RUN rm -Rf /home/testuser RUN rm -Rf /home/testuser
RUN TAILSCALED_PATH=`pwd`tailscaled ./tailssh.test -test.v -test.run TestIntegrationSFTP RUN TAILSCALED_PATH=`pwd`tailscaled ./tailssh.test -test.v -test.run TestIntegrationSFTP