From 11810e7ce07cb6078647e77e75aa48edc1362359 Mon Sep 17 00:00:00 2001 From: utam0k Date: Tue, 15 Jun 2021 08:48:43 +0900 Subject: [PATCH] clean up around the tty. --- src/cgroups/v2/manager.rs | 2 +- src/create.rs | 19 ++++------ src/main.rs | 1 - src/namespaces.rs | 2 +- src/tty.rs | 77 +++++++++++++++++---------------------- src/utils.rs | 11 ++---- 6 files changed, 47 insertions(+), 65 deletions(-) diff --git a/src/cgroups/v2/manager.rs b/src/cgroups/v2/manager.rs index 9a0d2a163..597a644a4 100644 --- a/src/cgroups/v2/manager.rs +++ b/src/cgroups/v2/manager.rs @@ -102,7 +102,7 @@ impl Manager { Ok(controllers) } - fn write_controllers(path: &Path, controllers: &Vec) -> Result<()> { + fn write_controllers(path: &Path, controllers: &[String]) -> Result<()> { for controller in controllers { common::write_cgroup_file_str(path.join(CGROUP_SUBTREE_CONTROL), controller)?; } diff --git a/src/create.rs b/src/create.rs index 9b10cc8bb..3c1b19e1d 100644 --- a/src/create.rs +++ b/src/create.rs @@ -33,7 +33,7 @@ pub struct Create { bundle: PathBuf, /// Unix socket (file) path , which will receive file descriptor of the writing end of the pseudoterminal #[clap(short, long)] - console_socket: Option, + console_socket: Option, /// name of the container instance to be started pub container_id: String, } @@ -86,16 +86,13 @@ impl Create { let mut notify_socket: NotifyListener = NotifyListener::new(&container_dir)?; // convert path of root file system of the container to absolute path let rootfs = fs::canonicalize(&spec.root.path)?; + // if socket file path is given in commandline options, - // get file descriptors of console and console socket - let (csocketfd, _consolefd) = { - if let Some(console_socket) = &self.console_socket { - let (csocketfd, consolefd) = - tty::load_console_sockets(&container_dir, console_socket)?; - (Some(csocketfd), Some(consolefd)) - } else { - (None, None) - } + // get file descriptors of console socket + let csocketfd = if let Some(console_socket) = &self.console_socket { + Some(tty::setup_console_socket(&container_dir, console_socket)?) + } else { + None }; let process = run_container( @@ -162,7 +159,7 @@ fn run_container>( // set up tty if specified if let Some(csocketfd) = csocketfd { - tty::ready(csocketfd)?; + tty::setup_console(csocketfd)?; } // set namespaces diff --git a/src/main.rs b/src/main.rs index f174cb600..04ee7102e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,6 @@ //! Container Runtime written in Rust, inspired by [railcar](https://github.com/oracle/railcar) //! This crate provides a container runtime which can be used by a high-level container runtime to run containers. -use procfs; use std::fs; use std::path::{Path, PathBuf}; diff --git a/src/namespaces.rs b/src/namespaces.rs index f075ea6dc..4fffea80e 100644 --- a/src/namespaces.rs +++ b/src/namespaces.rs @@ -3,7 +3,7 @@ //! Process (processes in a namespace have two PIDs, one for the global PID, //! which is used by the main system and the second one is for the child within the process tree), //! Interprocess Communication (Control or communication between processes), -//! Network (which network devices can be seen by the processes in the namespace), User (User configs), +//! Network (which network devices can be seen by the processes in the namespace), User (User configs), //! UTS (hostname and domain information, processes will think they're running on servers with different names), //! Cgroup (Resource limits, execution priority etc.) diff --git a/src/tty.rs b/src/tty.rs index 7fb621496..b6bf4be34 100644 --- a/src/tty.rs +++ b/src/tty.rs @@ -6,44 +6,21 @@ use std::path::Path; use anyhow::{bail, Result}; use nix::errno::Errno; -use nix::fcntl; use nix::sys::socket; -use nix::sys::stat; +use nix::sys::uio; use nix::unistd::{close, setsid}; use crate::stdio; use crate::stdio::FileDescriptor; -pub fn ready(console_fd: FileDescriptor) -> Result<()> { - let openpty_result = nix::pty::openpty(None, None)?; - let data: &[u8] = b"/dev/ptmx"; - let iov = [nix::sys::uio::IoVec::from_slice(data)]; - let fds = [openpty_result.master]; - let cmsg = socket::ControlMessage::ScmRights(&fds); - socket::sendmsg( - console_fd.as_raw_fd(), - &iov, - &[cmsg], - socket::MsgFlags::empty(), - None, - )?; +// TODO: Handling when there isn't console-socket. - setsid()?; - if unsafe { libc::ioctl(openpty_result.slave, libc::TIOCSCTTY) } < 0 { - log::warn!("could not TIOCSCTTY"); - }; - let slave = FileDescriptor::from(openpty_result.slave); - stdio::connect_stdio(&slave, &slave, &slave).expect("could not dup tty to stderr"); - close(console_fd.as_raw_fd())?; - Ok(()) -} - -pub fn load_console_sockets( +pub fn setup_console_socket( container_dir: &Path, - console_socket: &str, -) -> Result<(FileDescriptor, FileDescriptor)> { - let csocket = "console-stdout"; - symlink(console_socket, container_dir.join(csocket))?; + console_socket_path: &Path, +) -> Result { + let csocket = "console-socket"; + symlink(console_socket_path, container_dir.join(csocket))?; let mut csocketfd = socket::socket( socket::AddressFamily::Unix, @@ -63,19 +40,31 @@ pub fn load_console_sockets( } Ok(()) => csocketfd, }; - let console = "console"; - let consolefd = match fcntl::open( - &*console, - fcntl::OFlag::O_NOCTTY | fcntl::OFlag::O_RDWR, - stat::Mode::empty(), - ) { - Err(e) => { - if e != ::nix::Error::Sys(Errno::ENOENT) { - bail!("failed to open {}", console); - } - -1 - } - Ok(fd) => fd, + Ok(csocketfd.into()) +} + +pub fn setup_console(console_fd: FileDescriptor) -> Result<()> { + // You can also access pty master, but it is better to use the API. + // ref. https://github.com/containerd/containerd/blob/261c107ffc4ff681bc73988f64e3f60c32233b37/vendor/github.com/containerd/go-runc/console.go#L139-L154 + let openpty_result = nix::pty::openpty(None, None)?; + let pty_name: &[u8] = b"/dev/ptmx"; + let iov = [uio::IoVec::from_slice(pty_name)]; + let fds = [openpty_result.master]; + let cmsg = socket::ControlMessage::ScmRights(&fds); + socket::sendmsg( + console_fd.as_raw_fd(), + &iov, + &[cmsg], + socket::MsgFlags::empty(), + None, + )?; + + setsid()?; + if unsafe { libc::ioctl(openpty_result.slave, libc::TIOCSCTTY) } < 0 { + log::warn!("could not TIOCSCTTY"); }; - Ok((csocketfd.into(), consolefd.into())) + let slave = FileDescriptor::from(openpty_result.slave); + stdio::connect_stdio(&slave, &slave, &slave).expect("could not dup tty to stderr"); + close(console_fd.as_raw_fd())?; + Ok(()) } diff --git a/src/utils.rs b/src/utils.rs index 549d223ed..178b3d054 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -46,13 +46,10 @@ pub fn do_exec(path: impl AsRef, args: &[String], envs: &[String]) -> Resu env::vars().for_each(|(key, _value)| std::env::remove_var(key)); // set env vars envs.iter().for_each(|e| { - let mut split = e.split("="); - match split.next() { - Some(key) => { - let value: String = split.collect::>().join("="); - env::set_var(key, value) - } - None => {} + let mut split = e.split('='); + if let Some(key) = split.next() { + let value: String = split.collect::>().join("="); + env::set_var(key, value) }; });