Commit 7d482de1 authored by Pavel Emelyanov's avatar Pavel Emelyanov

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: 's avatarPavel Emelyanov <xemul@parallels.com>
Acked-by: 's avatarAndrew Vagin <avagin@parallels.com>
parent 26ef7867
...@@ -28,6 +28,7 @@ ...@@ -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) ...@@ -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) ...@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment