mirror of
https://github.com/gravitational/teleport.git
synced 2026-09-21 14:05:34 +08:00
tsh: Add wrapper for syscall.Dup2 for linux/arm64 (#55925)
* tsh: Add wrapper for syscall.Dup2 for linux/arm64
Add a wrapper for `syscall.Dup2()` as linux ARM64 does not have that
syscall. On that platform, `syscall.Dup3()` needs to be used instead.
Fixes: 57c909dab1
* Implement dup2 with syscall.Dup3 on all linux platforms
* Add explicit "unix" constraint to dup2_unix.go to ensure Windows is excluded
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
// Teleport
|
||||
// Copyright (C) 2025 Gravitational, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build linux
|
||||
|
||||
package common
|
||||
|
||||
import "syscall"
|
||||
|
||||
// dup2 implements syscall.Dup2(oldfd, newfd) in a way that works on all
|
||||
// current Linux platforms, and likely on any new platforms. New platforms
|
||||
// such as ARM64 do not implement syscall.Dup2() instead implementing
|
||||
// syscall.Dup3() which is largely a superset, with one special case.
|
||||
func dup2(oldfd, newfd int) error {
|
||||
if oldfd == newfd {
|
||||
// dup2 would do nothing in this case, but dup3 returns an error.
|
||||
// Emulate dup2 behavior.
|
||||
return nil
|
||||
}
|
||||
return syscall.Dup3(oldfd, newfd, 0)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Teleport
|
||||
// Copyright (C) 2025 Gravitational, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build unix && !linux
|
||||
|
||||
package common
|
||||
|
||||
import "syscall"
|
||||
|
||||
// dup2 wraps syscall.Dup2(oldfd, newfd) on non-linux unix platforms. The
|
||||
// linux implementation uses syscall.Dup3() as Dup2() is not available
|
||||
// on all linux platforms.
|
||||
func dup2(oldfd, newfd int) error {
|
||||
return syscall.Dup2(oldfd, newfd)
|
||||
}
|
||||
@@ -51,16 +51,17 @@ func replaceStdin() (*os.File, error) {
|
||||
}
|
||||
var dupErr error
|
||||
if ctrlErr := rc.Control(func(fd uintptr) {
|
||||
dupErr = syscall.Dup2(int(fd), syscall.Stdin)
|
||||
// stdin is not O_CLOEXEC after dup2 but thankfully the three stdio
|
||||
// file descriptors must be not O_CLOEXEC anyway, so we can avoid
|
||||
// a linux-specific implementation or syscall.ForkLock shenanigans
|
||||
dupErr = dup2(int(fd), syscall.Stdin)
|
||||
// dup2() is sufficient here as the three stdio file
|
||||
// descriptors must not be O_CLOEXEC. Darwin does not have
|
||||
// dup3(), so would need to resort to syscall.ForkLock
|
||||
// shenanigans if we did need to set O_CLOEXEC.
|
||||
}); ctrlErr != nil {
|
||||
_ = devNull.Close()
|
||||
return nil, trace.Wrap(ctrlErr)
|
||||
}
|
||||
if dupErr != nil {
|
||||
// this is the error from Dup2
|
||||
// this is the error from dup2
|
||||
_ = devNull.Close()
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user