This is the mail archive of the mailing list for the glibc project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/22145] ttyname() gives up too early in the face of namespaces

--- Comment #5 from Christian Brauner <christian.brauner at mailbox dot org> ---

I'm one of the authors of the original ttyname{_r}() patch you referred to.
Florian just made me aware of this bug report. Would've been cool if you
could've CCed us before. :)

(In reply to Luke Shumaker from comment #0)
> Commit 15e9a4f (which was the fix for #12167) introduced returning ENODEV
> for when we can't determine the TTY's name because we inherited it from a
> different mount namespace.  However, just because the TTY is from a
> different namespace, and we can no longer reach it at the original name
> doesn't mean its unreachable.  It shouldn't stop the old fallback iteration
> code from running; that fallback might very well find the name.
> For instance, systemd-nspawn arranges for the TTY to be at /dev/console,
> even though it's original /dev/pts/X location won't be the same TTY.  With
> glibc 2.25 this worked fine, but with 15e9a4f applied in 2.26, not so much:
>     $ sudo systemd-nspawn --register=no -D /path/to/my-container /bin/bash
>     Spawning container my-container on /path/to/my-container.
>     Press ^] three times within 1s to kill container.
>     bash: cannot set terminal process group (-1): Inappropriate ioctl for
> device
>     bash: no job control in this shell
>     [root@my-container /]# 

I'm a little confused. We do the same in liblxc namely, we bind-mount a
/dev/pty/<idx> path from the parent's devpts mount in the parent's mount
namespace over /dev/console. And things work just fine meaning:

> lxc-execute -n a5 -- bash
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell

root@a5:/# tty

root@a5:/# findmnt | grep console
| `-/dev/console                 devpts[/9]                                    
 devpts      rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000

root@a5:/# ls -al /dev/pts/
total 0
drwxr-xr-x 2 root root      0 Oct  6 09:18 .
drwxr-xr-x 6 root root    360 Oct  6 09:18 ..
crw--w---- 1 root tty  136, 0 Oct  6 09:18 0
crw--w---- 1 root tty  136, 1 Oct  6 09:18 1
crw--w---- 1 root tty  136, 2 Oct  6 09:18 2
crw--w---- 1 root tty  136, 3 Oct  6 09:18 3
crw-rw-rw- 1 root root   5, 2 Oct  6 09:18 ptmx

you can clearly see that the tty coreutil reports /dev/console and exits 0 so
it correctly detects that the program is attached to a pty and reports the
correct path even thought bind-mounted /dev/pts/<idx> (where <idx> == 9 in this
case) does not exist in the current devpts mount's mount namespace. Internally,
tty calls ttyname and isatty so there doesn't seem to be a regression here.

Also, I'm not sure how your patch would help with bash. What your patch does is
have ttyname() set ENODEV or have ttyname_r() return ENODEV but in both cases
no tty name will be returned. So this presupposes that any program that calls
ttyname{_r}() recognizes that ENODEV means "is a tty but no path was found"
which is not the case for bash so I'm confused how that would help you get
around this problem. Maybe you can explain this in a little more detail I might
just be dense.

> This is because the TTY, originally /dev/pts/${X}, is only available at
> /dev/console in the new mount namespace.  Bash gets the TTY on FD 0, and
> calls ttyname(STDIN_FILENO).  Before 15e9a4f, this correctly returned
> "/dev/console", but now it returns NULL and sets errno=ENODEV.

I don't completely understand this analysis as well. It seems to me that the
error comes from setting the process group leader and not from ttyname{_r}()
failures in the bash code. I think the codepath responsible is:

          /* If (and only if) we just set our process group to our pid,
             thereby becoming a process group leader, and the terminal
             is not in the same process group as our (new) process group,
             then set the terminal's process group to our (new) process
             group.  If that fails, set our process group back to what it
             was originally (so we can still read from the terminal) and
             turn off job control.  */
          if (shell_pgrp != original_pgrp && shell_pgrp != terminal_pgrp)
              if (give_terminal_to (shell_pgrp, 0) < 0)
                  t_errno = errno;
                  setpgid (0, original_pgrp);
                  shell_pgrp = original_pgrp;
                  errno = t_errno;
                  sys_error (_("cannot set terminal process group (%d)"),
                  job_control = 0;

You are receiving this mail because:
You are on the CC list for the bug.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]