[lxc-devel] [lxd/master] shared: Rewrite OpenPty without cgo
stgraber on Github
lxc-bot at linuxcontainers.org
Fri May 8 22:25:48 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 354 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200508/6ca6a002/attachment.bin>
-------------- next part --------------
From fc0d4c4158413248e940ce602a9080a6d60b256f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 8 May 2020 18:25:13 -0400
Subject: [PATCH] shared: Rewrite OpenPty without cgo
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
shared/util_linux.go | 89 ++++++++++++++++++++++++++++++++++++++++
shared/util_linux_cgo.go | 76 ----------------------------------
2 files changed, 89 insertions(+), 76 deletions(-)
diff --git a/shared/util_linux.go b/shared/util_linux.go
index ded0dac39e..c739b42058 100644
--- a/shared/util_linux.go
+++ b/shared/util_linux.go
@@ -391,3 +391,92 @@ func DeviceTotalMemory() (int64, error) {
return -1, fmt.Errorf("Couldn't find MemTotal")
}
+
+// OpenPty creates a new PTS pair, configures them and returns them.
+func OpenPty(uid, gid int64) (*os.File, *os.File, error) {
+ revert := true
+
+ // Create a PTS pair.
+ master, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
+ if err != nil {
+ return nil, nil, err
+ }
+ defer func() {
+ if revert {
+ master.Close()
+ }
+ }()
+
+ // Get the slave side.
+ id := 0
+ _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(master.Fd()), unix.TIOCGPTN, uintptr(unsafe.Pointer(&id)))
+ if errno != 0 {
+ return nil, nil, unix.Errno(errno)
+ }
+
+ // Unlock the slave side.
+ val := 0
+ _, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(master.Fd()), unix.TIOCSPTLCK, uintptr(unsafe.Pointer(&val)))
+ if errno != 0 {
+ return nil, nil, unix.Errno(errno)
+ }
+
+ // Open the slave.
+ slave, err := os.OpenFile(fmt.Sprintf("/dev/pts/%d", id), os.O_RDWR|unix.O_NOCTTY, 0)
+ if err != nil {
+ return nil, nil, err
+ }
+ defer func() {
+ if revert {
+ slave.Close()
+ }
+ }()
+
+ // Configure both sides
+ for _, entry := range []*os.File{master, slave} {
+ // Get termios.
+ t, err := unix.IoctlGetTermios(int(entry.Fd()), unix.TCGETS)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // Set flags.
+ t.Cflag |= unix.IMAXBEL
+ t.Cflag |= unix.IUTF8
+ t.Cflag |= unix.BRKINT
+ t.Cflag |= unix.IXANY
+ t.Cflag |= unix.HUPCL
+
+ // Set termios.
+ err = unix.IoctlSetTermios(int(entry.Fd()), unix.TCSETS, t)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // Set the default window size.
+ sz := &unix.Winsize{
+ Col: 80,
+ Row: 25,
+ }
+
+ err = unix.IoctlSetWinsize(int(entry.Fd()), unix.TIOCSWINSZ, sz)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // Set CLOEXEC.
+ _, _, errno = unix.Syscall(unix.SYS_FCNTL, uintptr(entry.Fd()), unix.F_SETFD, unix.FD_CLOEXEC)
+ if errno != 0 {
+ return nil, nil, unix.Errno(errno)
+ }
+ }
+
+ // Fix the ownership of the slave side.
+ err = os.Chown(slave.Name(), int(uid), int(gid))
+ if err != nil {
+ return nil, nil, err
+ }
+
+ revert = false
+ return master, slave, nil
+}
diff --git a/shared/util_linux_cgo.go b/shared/util_linux_cgo.go
index bb37c1f33a..e986dce8ee 100644
--- a/shared/util_linux_cgo.go
+++ b/shared/util_linux_cgo.go
@@ -4,7 +4,6 @@
package shared
import (
- "errors"
"fmt"
"io"
"os"
@@ -42,63 +41,6 @@ import (
// This is an adaption from https://codereview.appspot.com/4589049, to be
// included in the stdlib with the stdlib's license.
-void configure_pty(int fd) {
- struct termios term_settings;
- struct winsize win;
-
- if (tcgetattr(fd, &term_settings) < 0) {
- fprintf(stderr, "Failed to get settings: %s\n", strerror(errno));
- return;
- }
-
- term_settings.c_iflag |= IMAXBEL;
- term_settings.c_iflag |= IUTF8;
- term_settings.c_iflag |= BRKINT;
- term_settings.c_iflag |= IXANY;
-
- term_settings.c_cflag |= HUPCL;
-
- if (tcsetattr(fd, TCSANOW, &term_settings) < 0) {
- fprintf(stderr, "Failed to set settings: %s\n", strerror(errno));
- return;
- }
-
- if (ioctl(fd, TIOCGWINSZ, &win) < 0) {
- fprintf(stderr, "Failed to get the terminal size: %s\n", strerror(errno));
- return;
- }
-
- win.ws_col = 80;
- win.ws_row = 25;
-
- if (ioctl(fd, TIOCSWINSZ, &win) < 0) {
- fprintf(stderr, "Failed to set the terminal size: %s\n", strerror(errno));
- return;
- }
-
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
- fprintf(stderr, "Failed to set FD_CLOEXEC: %s\n", strerror(errno));
- return;
- }
-
- return;
-}
-
-void create_pty(int *master, int *slave, uid_t uid, gid_t gid) {
- if (openpty(master, slave, NULL, NULL, NULL) < 0) {
- fprintf(stderr, "Failed to openpty: %s\n", strerror(errno));
- return;
- }
-
- configure_pty(*master);
- configure_pty(*slave);
-
- if (fchown(*slave, uid, gid) < 0) {
- fprintf(stderr, "Warning: error chowning pty to container root\n");
- fprintf(stderr, "Continuing...\n");
- }
-}
-
int get_poll_revents(int lfd, int timeout, int flags, int *revents, int *saved_errno)
{
int ret;
@@ -160,24 +102,6 @@ func GetPollRevents(fd int, timeout int, flags int) (int, int, error) {
return int(ret), int(revents), err
}
-func OpenPty(uid, gid int64) (master *os.File, slave *os.File, err error) {
- fd_master := C.int(-1)
- fd_slave := C.int(-1)
- rootUid := C.uid_t(uid)
- rootGid := C.gid_t(gid)
-
- C.create_pty(&fd_master, &fd_slave, rootUid, rootGid)
-
- if fd_master == -1 || fd_slave == -1 {
- return nil, nil, errors.New("Failed to create a new pts pair")
- }
-
- master = os.NewFile(uintptr(fd_master), "master")
- slave = os.NewFile(uintptr(fd_slave), "slave")
-
- return master, slave, nil
-}
-
// UserId is an adaption from https://codereview.appspot.com/4589049.
func UserId(name string) (int, error) {
var pw C.struct_passwd
More information about the lxc-devel
mailing list