mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-01 23:05:39 +00:00
tty: Restore locked termios with usernsd call
Locked termios require global CAP_SYS_ADMIN. But let's restore everything for tty in one call since regular termios depend on locked and it's not nice to do sync usernsd call for locked only. Signed-off-by: Pavel Emelyanov <xemul@parallels.com> Acked-by: Andrew Vagin <avagin@parallels.com>
This commit is contained in:
78
tty.c
78
tty.c
@@ -28,6 +28,7 @@
|
|||||||
#include "proc_parse.h"
|
#include "proc_parse.h"
|
||||||
#include "file-ids.h"
|
#include "file-ids.h"
|
||||||
#include "files-reg.h"
|
#include "files-reg.h"
|
||||||
|
#include "namespaces.h"
|
||||||
|
|
||||||
#include "protobuf.h"
|
#include "protobuf.h"
|
||||||
#include "protobuf/tty.pb-c.h"
|
#include "protobuf/tty.pb-c.h"
|
||||||
@@ -606,10 +607,54 @@ static void tty_show_pty_info(char *prefix, struct tty_info *info)
|
|||||||
tty_is_master(info), info->tie->sid, info->tie->pgrp, info->inherit);
|
tty_is_master(info), info->tie->sid, info->tie->pgrp, info->inherit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct tty_parms {
|
||||||
|
int tty_id;
|
||||||
|
unsigned has;
|
||||||
|
#define HAS_TERMIOS_L 0x1
|
||||||
|
#define HAS_TERMIOS 0x2
|
||||||
|
#define HAS_WINS 0x4
|
||||||
|
struct termios tl;
|
||||||
|
struct termios t;
|
||||||
|
struct winsize w;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int do_restore_tty_parms(void *arg, int fd)
|
||||||
|
{
|
||||||
|
struct tty_parms *p = arg;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only locked termios need CAP_SYS_ADMIN, but we
|
||||||
|
* restore them all here, since the regular tremios
|
||||||
|
* restore is affected by locked and thus we would
|
||||||
|
* have to do synchronous usernsd call which is not
|
||||||
|
* nice.
|
||||||
|
*
|
||||||
|
* Window size is restored here as it might depend
|
||||||
|
* on termios too. Just to be on the safe side.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((p->has & HAS_TERMIOS_L) &&
|
||||||
|
ioctl(fd, TIOCSLCKTRMIOS, &p->tl) < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if ((p->has & HAS_TERMIOS) &&
|
||||||
|
ioctl(fd, TCSETS, &p->t) < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if ((p->has & HAS_WINS) &&
|
||||||
|
ioctl(fd, TIOCSWINSZ, &p->w) < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
pr_perror("Can't set tty params on %d", p->tty_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int restore_tty_params(int fd, struct tty_info *info)
|
static int restore_tty_params(int fd, struct tty_info *info)
|
||||||
{
|
{
|
||||||
struct winsize w;
|
struct tty_parms p;
|
||||||
struct termios t;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It's important to zeroify termios
|
* It's important to zeroify termios
|
||||||
@@ -620,31 +665,28 @@ static int restore_tty_params(int fd, struct tty_info *info)
|
|||||||
* never be extended.
|
* never be extended.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
p.has = 0;
|
||||||
|
p.tty_id = info->tfe->id;
|
||||||
|
|
||||||
if (info->tie->termios_locked) {
|
if (info->tie->termios_locked) {
|
||||||
memzero(&t, sizeof(t));
|
memzero(&p.tl, sizeof(p.tl));
|
||||||
termios_copy(&t, info->tie->termios_locked);
|
p.has |= HAS_TERMIOS_L;
|
||||||
if (ioctl(fd, TIOCSLCKTRMIOS, &t) < 0)
|
termios_copy(&p.tl, info->tie->termios_locked);
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->tie->termios) {
|
if (info->tie->termios) {
|
||||||
memzero(&t, sizeof(t));
|
memzero(&p.t, sizeof(p.t));
|
||||||
termios_copy(&t, info->tie->termios);
|
p.has |= HAS_TERMIOS;
|
||||||
if (ioctl(fd, TCSETS, &t) < 0)
|
termios_copy(&p.t, info->tie->termios);
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->tie->winsize) {
|
if (info->tie->winsize) {
|
||||||
memzero(&w, sizeof(w));
|
memzero(&p.w, sizeof(p.w));
|
||||||
winsize_copy(&w, info->tie->winsize);
|
p.has |= HAS_WINS;
|
||||||
if (ioctl(fd, TIOCSWINSZ, &w) < 0)
|
winsize_copy(&p.w, info->tie->winsize);
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return userns_call(do_restore_tty_parms, UNS_ASYNC, &p, sizeof(p), fd);
|
||||||
err:
|
|
||||||
pr_perror("Can't set tty params on %d", info->tfe->id);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pty_open_slaves(struct tty_info *info)
|
static int pty_open_slaves(struct tty_info *info)
|
||||||
|
Reference in New Issue
Block a user