ttyname_r returns ENODEV error in strict confinement

Bug #1936712 reported by Alexis Reigel
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
snapd
Confirmed
Undecided
Unassigned

Bug Description

I stumbled upon this issue when printing to the terminal in a Crystal app without a newline at the end. The text would not be flushed out immediately.

Digging through the Crystal sourcecode i found that https://github.com/crystal-lang/crystal/blob/849d1d1ce6dac18b580767f99681e5062a6ac2e8/src/crystal/system/unix/file_descriptor.cr#L172-L173 is responsible for figuring out if STDOUT is a TTY or not, and setting `io.sync = true` in the case of a TTY. It calls `ttyname_r` https://linux.die.net/man/3/ttyname_r to get the TTY name.

The following test code reveals the issue:

    require "c/fcntl"

    puts "--> tty?: #{STDOUT.tty?} / sync?: #{STDOUT.sync?} / close_on_exec?: #{STDOUT.close_on_exec?}"

    path = uninitialized UInt8[256]
    ret = LibC.ttyname_r(STDOUT.fd, path, 256)
    puts "LibC.ttyname_r: #{ret}"

    puts "Errno.value: #{Errno.value}"

    clone_fd = LibC.open(path, LibC::O_RDWR)
    puts "LibC.open: #{clone_fd}"

Running the code outside of snap or in a "classic" confinement works as expected:

    --> tty?: true / sync?: true / close_on_exec?: false
    LibC.ttyname_r: 0
    Errno.value: NONE
    LibC.open: 7

In a "strict" confinement:

    --> tty?: true / sync?: false / close_on_exec?: false
    LibC.ttyname_r: 19
    Errno.value: ENODEV
    LibC.open: -1

The error code `ENODEV` is defined as follows (from https://www.gnu.org/software/libc/manual/html_node/Error-Codes.html):

    Macro: int ENODEV

        “No such device.” The wrong type of device was given to a function that expects a particular sort of device.

Is this a bug in the behaviour of the snap sandbox?

description: updated
description: updated
Revision history for this message
Sergio Schvezov (sergiusens) wrote :

Moved to the snapd queue as this is confinement related.

affects: snapcraft → snapd
Revision history for this message
Maciej Borzecki (maciek-borzecki) wrote (last edit ):

Yes, this part of the sandbox. I'm not aware any form of mediating the access to /dev/pts. When you run a snap, you get a new devpts mount under /dev/pts, otherwise each snap would get immediate access to all your terminals.

For the record, the situation is that when you run a snap, your process gets access to the pts of your terminal via stdin/stdout/stderr. However, once within the snap that /dev/pts/<nn> device is no longer present and you have just obtained a new devpts filesystem on /dev/pts. So while you still can access the terminal you started with, you cannot see any other terminals. The downside is that /proc/self/fd/{0,1,2} now point to something that is not present in your namespace.

Changed in snapd:
status: New → Confirmed
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.