I’ve been working on getting TMUX to work in LXD containers. This is required because LXD makes sure to allocate a fresh pty device from the host and pass it to the container when we attach to it via lxc exec. We allocate the pty device from the host for security reasons! The main issue is that as soon as init has started it is possible that someone might tamper with the devpts mount inside the container (e.g. via fuse) and hand us a malicious pty file descriptor that can be used to escape to the host!
This requires a version of glibc that includes this patch (This commit will not change tmux behavior wrt to an unpatched glib version.):
Author: Christian Brauner <christian.brauner@canonical.com>
Date: Fri Jan 27 15:59:59 2017 +0100
linux ttyname and ttyname_r: do not return wrong results
If a link (say /proc/self/fd/0) pointing to a device, say /dev/pts/2, in a
parent mount namespace is passed to ttyname, and a /dev/pts/2 exists (in a
different devpts) in the current namespace, then it returns /dev/pts/2.
But /dev/pts/2 is NOT the current tty, it is a different file and device.
Detect this case and return ENODEV. Userspace can choose to take this as a hint
that the fd points to a tty device but to act on the fd rather than the link.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
To test whether you are running a patched glibc version you can do:
sudo unshare --fork --pid --mount-proc
and then to mount a new devpts instance:
mount -t devpts devpts /dev/pts
If you call
tty
you should see “not a tty”. Now you can compile this test program:
/*
*
* Copyright © 2017 Christian Brauner <christian.brauner@ubuntu.com>.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
/* Test whether this is a correctly patched version of ttyname(). */
int main(int argc, char *argv[])
{
int fd;
char buf[4096];
fd = open("/proc/self/fd/0", O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Could not open \"/proc/self/fd/0\": %s.\n",
strerror(errno));
exit(EXIT_FAILURE);
}
if (!ttyname(fd)) {
/* COMMENT(brauner): ENODEV will only be set by a patched
* glibc.
*/
if (errno == ENODEV) {
printf("ttyname(): The pty device might exist in a "
"different "
"namespace: %s\n",
strerror(errno));
} else {
exit(EXIT_FAILURE);
}
}
if (ttyname_r(fd, buf, sizeof(buf))) {
/* COMMENT(brauner): ENODEV will only be set by a patched
* glibc.
*/
if (errno == ENODEV) {
printf("ttyname_r(): The pty device might exist in a "
"different "
"namespace: %s\n",
strerror(errno));
} else {
exit(EXIT_FAILURE);
}
}
exit(EXIT_SUCCESS);
}
Now, in this setting you can also test a patched tmux version. A non-patched tmux version should refuse to run, a patched tmux version should run just fine.
Share this recording
Link
Append ?t=30
to start the playback at 30s, ?t=3:20
to start the playback at 3m 20s.
Embed image link
Use snippets below to display a screenshot linking to this recording.
Useful in places where scripts are not allowed (e.g. in a project's README file).
HTML:
Markdown:
Embed the player
If you're embedding on your own page or on a site which permits script tags, you can use the full player widget:
Paste the above script tag where you want the player to be displayed on your page.
See embedding docs for additional options.
Download this recording
You can download this recording in asciicast v1 format, as a .json file.
DownloadReplay in terminal
You can replay the downloaded recording in your terminal using the
asciinema play
command:
asciinema play 110681.json
If you don't have asciinema CLI installed then see installation instructions.
Use with stand-alone player on your website
Download asciinema player from
the releases page
(you only need .js
and .css
file), then use it like this:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="asciinema-player.css" />
</head>
<body>
<div id="player"></div>
<script src="asciinema-player.min.js"></script>
<script>
AsciinemaPlayer.create(
'/assets/110681.json',
document.getElementById('player'),
{ cols: 170, rows: 53 }
);
</script>
</body>
</html>
See asciinema player quick-start guide for full usage instructions.
Generate GIF from this recording
While this site doesn't provide GIF conversion at the moment, you can still do it yourself with the help of asciinema GIF generator utility - agg.
Once you have it installed, generate a GIF with the following command:
agg https://asciinema.org/a/110681 demo.gif
Or, if you already downloaded the recording file:
agg demo.cast demo.gif
Check agg --help
for all available options. You can change font
family and size, select color theme, adjust speed and more.
See agg manual for full usage instructions.