diff -Nru glibc-2.24/debian/changelog glibc-2.24/debian/changelog --- glibc-2.24/debian/changelog 2016-12-05 07:36:48.000000000 -0500 +++ glibc-2.24/debian/changelog 2017-03-02 15:22:01.000000000 -0500 @@ -1,3 +1,11 @@ +glibc (2.24-7ubuntu3) zesty; urgency=medium + + * Fix ttyname inside containers (LP: #1669578) + - ubuntu/submitted-ttyname-enodev.diff + - ubuntu/local-ttyname-return-symlink.diff + + -- Stéphane Graber Thu, 02 Mar 2017 15:22:01 -0500 + glibc (2.24-7ubuntu2) zesty; urgency=medium * Disable lock-elision on all targets to avoid regressions (LP: #1642390) diff -Nru glibc-2.24/debian/patches/series glibc-2.24/debian/patches/series --- glibc-2.24/debian/patches/series 2016-11-30 11:57:20.000000000 -0500 +++ glibc-2.24/debian/patches/series 2017-03-02 15:21:09.000000000 -0500 @@ -230,3 +230,5 @@ ubuntu/localedata/pt_BR-d_fmt.diff ubuntu/localedata/sd_PK.diff ubuntu/localedata/ug_CN@latin.diff +ubuntu/submitted-ttyname-enodev.diff +ubuntu/local-ttyname-return-symlink.diff diff -Nru glibc-2.24/debian/patches/ubuntu/local-ttyname-return-symlink.diff glibc-2.24/debian/patches/ubuntu/local-ttyname-return-symlink.diff --- glibc-2.24/debian/patches/ubuntu/local-ttyname-return-symlink.diff 1969-12-31 19:00:00.000000000 -0500 +++ glibc-2.24/debian/patches/ubuntu/local-ttyname-return-symlink.diff 2017-03-02 15:18:05.000000000 -0500 @@ -0,0 +1,71 @@ +From 93f44707175c22633633ddc66427b258286f5d89 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Fri, 24 Feb 2017 02:02:36 +0100 +Subject: [PATCH 2/2] linux ttyname and ttyname_r: return symlink + +Return the symbolic link /proc/self/fd/ instead of /dev/pts/ or NULL in +two case: + +- when the /dev/pts/ link exists but it exists in a different namespace +- when the /dev/pts/ link does not exist in the current namespace + +In both case the previous patch ensures that ENODEV is set. This will allow +allow programs like e.g. tmux to behave correctly when run in a container that +allocates a pty file descriptor from another namespace: + +ubuntu@edfu:~/glibc_build$ lxc exec xen1 -- bash +root@xen1:~# tty +/proc/self/fd/0 + +Signed-off-by: Christian Brauner +Acked-by: Serge Hallyn +--- + sysdeps/unix/sysv/linux/ttyname.c | 10 ++++++++-- + sysdeps/unix/sysv/linux/ttyname_r.c | 10 ++++++++-- + 2 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/ttyname.c b/sysdeps/unix/sysv/linux/ttyname.c +index 5909cb7..44c4941 100644 +--- a/sysdeps/unix/sysv/linux/ttyname.c ++++ b/sysdeps/unix/sysv/linux/ttyname.c +@@ -181,8 +181,14 @@ ttyname (int fd) + namespace. */ + if (is_pty (&st)) + { +- __set_errno (ENODEV); +- return NULL; ++ if (strlen (procname) < (buflen - 1)) ++ { ++ strcpy(ttyname_buf, procname); ++ __set_errno (ENODEV); ++ return ttyname_buf; ++ } ++ __set_errno (ENODEV); ++ return NULL; + } + } + +diff --git a/sysdeps/unix/sysv/linux/ttyname_r.c b/sysdeps/unix/sysv/linux/ttyname_r.c +index dc86352..a081a11 100644 +--- a/sysdeps/unix/sysv/linux/ttyname_r.c ++++ b/sysdeps/unix/sysv/linux/ttyname_r.c +@@ -164,8 +164,14 @@ __ttyname_r (int fd, char *buf, size_t buflen) + */ + if (is_pty (&st)) + { +- __set_errno (ENODEV); +- return ENODEV; ++ if (strlen (procname) < (buflen - 1)) ++ { ++ strcpy(buf, procname); ++ __set_errno (ENODEV); ++ return 0; ++ } ++ __set_errno (ENODEV); ++ return ENODEV; + } + } + +-- +2.10.2 + diff -Nru glibc-2.24/debian/patches/ubuntu/submitted-ttyname-enodev.diff glibc-2.24/debian/patches/ubuntu/submitted-ttyname-enodev.diff --- glibc-2.24/debian/patches/ubuntu/submitted-ttyname-enodev.diff 1969-12-31 19:00:00.000000000 -0500 +++ glibc-2.24/debian/patches/ubuntu/submitted-ttyname-enodev.diff 2017-03-02 15:18:05.000000000 -0500 @@ -0,0 +1,139 @@ +From c3a1fb13917857c03d83dcdd3f2ccf44aa765af2 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Fri, 24 Feb 2017 02:02:35 +0100 +Subject: [PATCH 1/2] 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 +Signed-off-by: Christian Brauner +--- + sysdeps/unix/sysv/linux/ttyname.c | 16 ++++++++++++---- + sysdeps/unix/sysv/linux/ttyname.h | 35 +++++++++++++++++++++++++++++++++++ + sysdeps/unix/sysv/linux/ttyname_r.c | 17 +++++++++++++---- + 3 files changed, 60 insertions(+), 8 deletions(-) + create mode 100644 sysdeps/unix/sysv/linux/ttyname.h + +diff --git a/sysdeps/unix/sysv/linux/ttyname.c b/sysdeps/unix/sysv/linux/ttyname.c +index e2686b5..5909cb7 100644 +--- a/sysdeps/unix/sysv/linux/ttyname.c ++++ b/sysdeps/unix/sysv/linux/ttyname.c +@@ -28,6 +28,8 @@ + + #include <_itoa.h> + ++#include "ttyname.h" ++ + #if 0 + /* Is this used anywhere? It is not exported. */ + char *__ttyname; +@@ -170,12 +172,18 @@ ttyname (int fd) + #ifdef _STATBUF_ST_RDEV + && S_ISCHR (st1.st_mode) + && st1.st_rdev == st.st_rdev +-#else +- && st1.st_ino == st.st_ino +- && st1.st_dev == st.st_dev + #endif +- ) ++ && st1.st_ino == st.st_ino ++ && st1.st_dev == st.st_dev) + return ttyname_buf; ++ ++ /* If the link doesn't exist, then it points to a device in another ++ namespace. */ ++ if (is_pty (&st)) ++ { ++ __set_errno (ENODEV); ++ return NULL; ++ } + } + + if (__xstat64 (_STAT_VER, "/dev/pts", &st1) == 0 && S_ISDIR (st1.st_mode)) +diff --git a/sysdeps/unix/sysv/linux/ttyname.h b/sysdeps/unix/sysv/linux/ttyname.h +new file mode 100644 +index 0000000..a1aa314 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/ttyname.h +@@ -0,0 +1,35 @@ ++/* Copyright (C) 2016 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ The GNU C Library 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++#include ++#include ++#include ++#include ++ ++/* Return true if this is a UNIX98 pty device, as defined in ++ linux/Documentation/devices.txt. */ ++static inline int ++is_pty (struct stat64 *sb) ++{ ++#ifdef _STATBUF_ST_RDEV ++ int m = major (sb->st_rdev); ++ return (136 <= m && m <= 143); ++#else ++ return false; ++#endif ++} ++ +diff --git a/sysdeps/unix/sysv/linux/ttyname_r.c b/sysdeps/unix/sysv/linux/ttyname_r.c +index 10b170a..dc86352 100644 +--- a/sysdeps/unix/sysv/linux/ttyname_r.c ++++ b/sysdeps/unix/sysv/linux/ttyname_r.c +@@ -28,6 +28,8 @@ + + #include <_itoa.h> + ++#include "ttyname.h" ++ + static int getttyname_r (char *buf, size_t buflen, + dev_t mydev, ino64_t myino, int save, + int *dostat) internal_function; +@@ -152,12 +154,19 @@ __ttyname_r (int fd, char *buf, size_t buflen) + #ifdef _STATBUF_ST_RDEV + && S_ISCHR (st1.st_mode) + && st1.st_rdev == st.st_rdev +-#else +- && st1.st_ino == st.st_ino +- && st1.st_dev == st.st_dev + #endif +- ) ++ && st1.st_ino == st.st_ino ++ && st1.st_dev == st.st_dev) + return 0; ++ ++ /* If the link doesn't exist, then it points to a device in another ++ * namespace. ++ */ ++ if (is_pty (&st)) ++ { ++ __set_errno (ENODEV); ++ return ENODEV; ++ } + } + + /* Prepare the result buffer. */ +-- +2.10.2 +