virtio-devices: determine tty size in console

This prepares us to be able to handle console resizes in the console
device's epoll loop, which we'll have to do if the output is a pty,
since we won't get SIGWINCH from it.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
This commit is contained in:
Alyssa Ross
2021-09-10 11:27:08 +00:00
committed by Rob Bradford
parent 68e6a14deb
commit 28382a1491
4 changed files with 47 additions and 44 deletions

View File

@@ -11,7 +11,7 @@ use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap;
use crate::VirtioInterrupt;
use libc::EFD_NONBLOCK;
use libc::{EFD_NONBLOCK, TIOCGWINSZ};
use seccompiler::SeccompAction;
use std::cmp;
use std::collections::VecDeque;
@@ -46,7 +46,7 @@ const FILE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 5;
//Console size feature bit
const VIRTIO_CONSOLE_F_SIZE: u64 = 0;
#[derive(Copy, Clone, Debug, Default, Versionize)]
#[derive(Copy, Clone, Debug, Versionize)]
#[repr(C, packed)]
pub struct VirtioConsoleConfig {
cols: u16,
@@ -55,6 +55,17 @@ pub struct VirtioConsoleConfig {
emerg_wr: u32,
}
impl Default for VirtioConsoleConfig {
fn default() -> Self {
VirtioConsoleConfig {
cols: 0,
rows: 0,
max_nr_ports: 1,
emerg_wr: 0,
}
}
}
// Safe because it only has data and has no implicit padding.
unsafe impl ByteValued for VirtioConsoleConfig {}
@@ -287,12 +298,13 @@ pub struct ConsoleResizer {
}
impl ConsoleResizer {
pub fn update_console_size(&self, cols: u16, rows: u16) {
pub fn update_console_size(&self) {
if self
.acked_features
.fetch_and(1u64 << VIRTIO_CONSOLE_F_SIZE, Ordering::AcqRel)
!= 0
{
let (cols, rows) = get_win_size();
self.config.lock().unwrap().update_console_size(cols, rows);
//Send the interrupt to the driver
let _ = self.config_evt.write(1);
@@ -301,15 +313,6 @@ impl ConsoleResizer {
}
impl VirtioConsoleConfig {
pub fn new(cols: u16, rows: u16) -> Self {
VirtioConsoleConfig {
cols,
rows,
max_nr_ports: 1u32,
emerg_wr: 0u32,
}
}
pub fn update_console_size(&mut self, cols: u16, rows: u16) {
self.cols = cols;
self.rows = rows;
@@ -336,6 +339,24 @@ pub struct ConsoleState {
in_buffer: Vec<u8>,
}
fn get_win_size() -> (u16, u16) {
#[repr(C)]
#[derive(Default)]
struct WindowSize {
rows: u16,
cols: u16,
xpixel: u16,
ypixel: u16,
}
let ws: WindowSize = WindowSize::default();
unsafe {
libc::ioctl(0, TIOCGWINSZ, &ws);
}
(ws.cols, ws.rows)
}
impl VersionMapped for ConsoleState {}
impl Console {
@@ -343,8 +364,6 @@ impl Console {
pub fn new(
id: String,
endpoint: Endpoint,
cols: u16,
rows: u16,
iommu: bool,
seccomp_action: SeccompAction,
exit_evt: EventFd,
@@ -356,13 +375,15 @@ impl Console {
}
let config_evt = EventFd::new(EFD_NONBLOCK).unwrap();
let console_config = Arc::new(Mutex::new(VirtioConsoleConfig::new(cols, rows)));
let console_config = Arc::new(Mutex::new(VirtioConsoleConfig::default()));
let resizer = Arc::new(ConsoleResizer {
config_evt,
config: console_config.clone(),
acked_features: AtomicU64::new(0),
});
resizer.update_console_size();
Ok((
Console {
common: VirtioCommon {

View File

@@ -48,6 +48,7 @@ macro_rules! or {
}
// See include/uapi/asm-generic/ioctls.h in the kernel code.
const TIOCGWINSZ: u64 = 0x5413;
const FIONBIO: u64 = 0x5421;
// See include/uapi/linux/vfio.h in the kernel code.
@@ -57,6 +58,10 @@ const VFIO_IOMMU_UNMAP_DMA: u64 = 0x3b72;
// See include/uapi/linux/if_tun.h in the kernel code.
const TUNSETOFFLOAD: u64 = 0x4004_54d0;
fn create_virtio_console_ioctl_seccomp_rule() -> Vec<SeccompRule> {
or![and![Cond::new(1, ArgLen::Dword, Eq, TIOCGWINSZ).unwrap()]]
}
fn create_virtio_iommu_ioctl_seccomp_rule() -> Vec<SeccompRule> {
or![
and![Cond::new(1, ArgLen::Dword, Eq, VFIO_IOMMU_MAP_DMA).unwrap()],
@@ -99,6 +104,7 @@ fn virtio_block_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
fn virtio_console_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
vec![
(libc::SYS_ioctl, create_virtio_console_ioctl_seccomp_rule()),
(libc::SYS_mprotect, vec![]),
(libc::SYS_prctl, vec![]),
(libc::SYS_sched_getaffinity, vec![]),