[GH-ISSUE #31] --noroot does not allow to start urxvt/rxvt-unicode #18

Closed
opened 2026-05-05 04:45:02 -06:00 by gitea-mirror · 10 comments
Owner

Originally created by @blueyed on GitHub (Aug 17, 2015).
Original GitHub issue: https://github.com/netblue30/firejail/issues/31

I am using Vimperator in Firefox and have set editor=vim-in-term, which is a script that calls urxvt ... vim.

The noroot option in /etc/firejail/firefox.profile causes urxvt to fail:

urxvt: can't initialize pseudo-tty, aborting.

From reading the description of noroot this does not seem to be obvious:

  --noroot - install a user namespace with a single user - the current
    user. root user does not exist in the new namespace. This option
    is not supported for --chroot and --overlay configurations.

The code from rxvt-unicode is this, where pty appears to come from libptytty (CVS at :pserver:anonymous@cvs.schmorp.de/schmorpforge):

if (!pty->get ())
  rxvt_fatal ("can't initialize pseudo-tty, aborting.\n");

It can be reproduced using:

firejail --noroot /usr/bin/rxvt-unicode

Using firejail --noroot strace -f /usr/bin/rxvt-unicode shows this at the end (group 5 being tty):

chown("/dev/pts/10", 1000, 5)           = -1 EINVAL (Invalid argument)
clone(Process 7 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5891234ad0) = 7
[pid     6] wait4(7,  <unfinished ...>
[pid     7] set_robust_list(0x7f5891234ae0, 24) = 0
[pid     7] setrlimit(RLIMIT_CORE, {rlim_cur=0, rlim_max=0}) = 0
[pid     7] dup2(7, 3)                  = 3
[pid     7] openat(AT_FDCWD, "/proc/self/fd", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 8
[pid     7] getdents(8, /* 11 entries */, 32768) = 264
[pid     7] close(0)                    = 0
[pid     7] close(1)                    = 0
[pid     7] close(2)                    = 0
[pid     7] close(4)                    = 0
[pid     7] close(5)                    = 0
[pid     7] close(6)                    = 0
[pid     7] close(7)                    = 0
[pid     7] getdents(8, /* 0 entries */, 32768) = 0
[pid     7] close(8)                    = 0
[pid     7] open("/dev/null", O_RDONLY) = 0
[pid     7] open("/dev/null", O_WRONLY) = 1
[pid     7] dup2(1, 2)                  = 2
[pid     7] execve("/usr/lib/pt_chown", ["pt_chown"], [/* 0 vars */]) = 0
[pid     7] brk(0)                      = 0x7efede80a000
[pid     7] access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
[pid     7] mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efede28a000
[pid     7] access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
[pid     7] open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 4
[pid     7] fstat(4, {st_mode=S_IFREG|0644, st_size=265876, ...}) = 0
[pid     7] mmap(NULL, 265876, PROT_READ, MAP_PRIVATE, 4, 0) = 0x7efede249000
[pid     7] close(4)                    = 0
[pid     7] access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
[pid     7] open("/lib/x86_64-linux-gnu/libcap.so.2", O_RDONLY|O_CLOEXEC) = 4
[pid     7] read(4, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\25\0\0\0\0\0\0"..., 832) = 832
[pid     7] fstat(4, {st_mode=S_IFREG|0644, st_size=18952, ...}) = 0
[pid     7] mmap(NULL, 2114160, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0x7efeddc60000
[pid     7] mprotect(0x7efeddc64000, 2093056, PROT_NONE) = 0
[pid     7] mmap(0x7efedde63000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x3000) = 0x7efedde63000
[pid     7] close(4)                    = 0
[pid     7] access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
[pid     7] open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 4
[pid     7] read(4, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\v\2\0\0\0\0\0"..., 832) = 832
[pid     7] fstat(4, {st_mode=S_IFREG|0755, st_size=1869392, ...}) = 0
[pid     7] mmap(NULL, 3972864, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0x7efedd896000
[pid     7] mprotect(0x7efedda56000, 2097152, PROT_NONE) = 0
[pid     7] mmap(0x7efeddc56000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x1c0000) = 0x7efeddc56000
[pid     7] mmap(0x7efeddc5c000, 16128, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7efeddc5c000
[pid     7] close(4)                    = 0
[pid     7] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efede248000
[pid     7] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efede247000
[pid     7] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efede246000
[pid     7] arch_prctl(ARCH_SET_FS, 0x7efede247700) = 0
[pid     7] mprotect(0x7efeddc56000, 16384, PROT_READ) = 0
[pid     7] mprotect(0x7efedde63000, 4096, PROT_READ) = 0
[pid     7] mprotect(0x7efede28c000, 4096, PROT_READ) = 0
[pid     7] mprotect(0x7efede088000, 4096, PROT_READ) = 0
[pid     7] munmap(0x7efede249000, 265876) = 0
[pid     7] geteuid()                   = 1000
[pid     7] getuid()                    = 1000
[pid     7] setuid(1000)                = 0
[pid     7] brk(0)                      = 0x7efede80a000
[pid     7] brk(0x7efede82b000)         = 0x7efede82b000
[pid     7] write(2, "pt_chown: ", 10)  = 10
[pid     7] write(2, "needs to be installed setuid `ro"..., 35) = 35
[pid     7] write(2, "\n", 1)           = 1
[pid     7] exit_group(4)               = ?
[pid     7] +++ exited with 4 +++
<... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 4}], 0, NULL) = 7
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=7, si_status=4, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 7
close(7)                                = 0
write(1, "urxvt: ", 7urxvt: )                  = 7
write(1, "can't initialize pseudo-tty, abo"..., 39can't initialize pseudo-tty, aborting.
) = 39
futex(0x7f588f3a9650, FUTEX_WAKE_PRIVATE, 2147483647) = 0
munmap(0x7f588b49c000, 475136)          = 0
poll([{fd=6, events=POLLIN|POLLOUT}], 1, 4294967295) = 1 ([{fd=6, revents=POLLOUT}])
writev(6, [{"_\24\2\0\2\0\0\5<\0\2\0\0\0\0\5.\0\2\0\3\0\0\5+\0\1\0", 28}, {NULL, 0}, {"", 0}], 3) = 28
poll([{fd=6, events=POLLIN}], 1, 4294967295) = 1 ([{fd=6, revents=POLLIN}])
recvmsg(6, {msg_name(0)=NULL, msg_iov(1)=[{"\1\2\235\0\0\0\0\0\t\0\300\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 4096}], msg_controllen=0, msg_flags=0}, 0) = 32
recvmsg(6, 0x7ffc5207d360, 0)           = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(6, 0x7ffc5207d360, 0)           = -1 EAGAIN (Resource temporarily unavailable)
shutdown(6, SHUT_RDWR)                  = 0
close(6)                                = 0
rt_sigaction(SIGINT, {SIG_DFL, [INT], SA_RESTORER|SA_RESTART, 0x7f588f3df2f0}, {0x4381a0, ~[KILL STOP RTMIN RT_1], SA_RESTORER|SA_RESTART, 0x7f588f784d10}, 8) = 0
rt_sigaction(SIGTERM, {SIG_DFL, [TERM], SA_RESTORER|SA_RESTART, 0x7f588f3df2f0}, {0x4381a0, ~[KILL STOP RTMIN RT_1], SA_RESTORER|SA_RESTART, 0x7f588f784d10}, 8) = 0
exit_group(1)                           = ?
+++ exited with 1 +++

parent is shutting down, bye...

Is this a issue with rxvt-unicode, or is there anything firejail can do to allow this still?

Originally created by @blueyed on GitHub (Aug 17, 2015). Original GitHub issue: https://github.com/netblue30/firejail/issues/31 I am using Vimperator in Firefox and have `set editor=vim-in-term`, which is a script that calls `urxvt ... vim`. The `noroot` option in `/etc/firejail/firefox.profile` causes urxvt to fail: > urxvt: can't initialize pseudo-tty, aborting. From reading the description of `noroot` this does not seem to be obvious: ``` --noroot - install a user namespace with a single user - the current user. root user does not exist in the new namespace. This option is not supported for --chroot and --overlay configurations. ``` The code from rxvt-unicode is this, where `pty` appears to come from libptytty (CVS at `:pserver:anonymous@cvs.schmorp.de/schmorpforge`): ``` if (!pty->get ()) rxvt_fatal ("can't initialize pseudo-tty, aborting.\n"); ``` It can be reproduced using: > firejail --noroot /usr/bin/rxvt-unicode Using `firejail --noroot strace -f /usr/bin/rxvt-unicode` shows this at the end (group 5 being `tty`): ``` chown("/dev/pts/10", 1000, 5) = -1 EINVAL (Invalid argument) clone(Process 7 attached child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5891234ad0) = 7 [pid 6] wait4(7, <unfinished ...> [pid 7] set_robust_list(0x7f5891234ae0, 24) = 0 [pid 7] setrlimit(RLIMIT_CORE, {rlim_cur=0, rlim_max=0}) = 0 [pid 7] dup2(7, 3) = 3 [pid 7] openat(AT_FDCWD, "/proc/self/fd", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 8 [pid 7] getdents(8, /* 11 entries */, 32768) = 264 [pid 7] close(0) = 0 [pid 7] close(1) = 0 [pid 7] close(2) = 0 [pid 7] close(4) = 0 [pid 7] close(5) = 0 [pid 7] close(6) = 0 [pid 7] close(7) = 0 [pid 7] getdents(8, /* 0 entries */, 32768) = 0 [pid 7] close(8) = 0 [pid 7] open("/dev/null", O_RDONLY) = 0 [pid 7] open("/dev/null", O_WRONLY) = 1 [pid 7] dup2(1, 2) = 2 [pid 7] execve("/usr/lib/pt_chown", ["pt_chown"], [/* 0 vars */]) = 0 [pid 7] brk(0) = 0x7efede80a000 [pid 7] access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) [pid 7] mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efede28a000 [pid 7] access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) [pid 7] open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 4 [pid 7] fstat(4, {st_mode=S_IFREG|0644, st_size=265876, ...}) = 0 [pid 7] mmap(NULL, 265876, PROT_READ, MAP_PRIVATE, 4, 0) = 0x7efede249000 [pid 7] close(4) = 0 [pid 7] access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) [pid 7] open("/lib/x86_64-linux-gnu/libcap.so.2", O_RDONLY|O_CLOEXEC) = 4 [pid 7] read(4, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\25\0\0\0\0\0\0"..., 832) = 832 [pid 7] fstat(4, {st_mode=S_IFREG|0644, st_size=18952, ...}) = 0 [pid 7] mmap(NULL, 2114160, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0x7efeddc60000 [pid 7] mprotect(0x7efeddc64000, 2093056, PROT_NONE) = 0 [pid 7] mmap(0x7efedde63000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x3000) = 0x7efedde63000 [pid 7] close(4) = 0 [pid 7] access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) [pid 7] open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 4 [pid 7] read(4, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\v\2\0\0\0\0\0"..., 832) = 832 [pid 7] fstat(4, {st_mode=S_IFREG|0755, st_size=1869392, ...}) = 0 [pid 7] mmap(NULL, 3972864, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0x7efedd896000 [pid 7] mprotect(0x7efedda56000, 2097152, PROT_NONE) = 0 [pid 7] mmap(0x7efeddc56000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x1c0000) = 0x7efeddc56000 [pid 7] mmap(0x7efeddc5c000, 16128, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7efeddc5c000 [pid 7] close(4) = 0 [pid 7] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efede248000 [pid 7] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efede247000 [pid 7] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efede246000 [pid 7] arch_prctl(ARCH_SET_FS, 0x7efede247700) = 0 [pid 7] mprotect(0x7efeddc56000, 16384, PROT_READ) = 0 [pid 7] mprotect(0x7efedde63000, 4096, PROT_READ) = 0 [pid 7] mprotect(0x7efede28c000, 4096, PROT_READ) = 0 [pid 7] mprotect(0x7efede088000, 4096, PROT_READ) = 0 [pid 7] munmap(0x7efede249000, 265876) = 0 [pid 7] geteuid() = 1000 [pid 7] getuid() = 1000 [pid 7] setuid(1000) = 0 [pid 7] brk(0) = 0x7efede80a000 [pid 7] brk(0x7efede82b000) = 0x7efede82b000 [pid 7] write(2, "pt_chown: ", 10) = 10 [pid 7] write(2, "needs to be installed setuid `ro"..., 35) = 35 [pid 7] write(2, "\n", 1) = 1 [pid 7] exit_group(4) = ? [pid 7] +++ exited with 4 +++ <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 4}], 0, NULL) = 7 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=7, si_status=4, si_utime=0, si_stime=0} --- rt_sigreturn() = 7 close(7) = 0 write(1, "urxvt: ", 7urxvt: ) = 7 write(1, "can't initialize pseudo-tty, abo"..., 39can't initialize pseudo-tty, aborting. ) = 39 futex(0x7f588f3a9650, FUTEX_WAKE_PRIVATE, 2147483647) = 0 munmap(0x7f588b49c000, 475136) = 0 poll([{fd=6, events=POLLIN|POLLOUT}], 1, 4294967295) = 1 ([{fd=6, revents=POLLOUT}]) writev(6, [{"_\24\2\0\2\0\0\5<\0\2\0\0\0\0\5.\0\2\0\3\0\0\5+\0\1\0", 28}, {NULL, 0}, {"", 0}], 3) = 28 poll([{fd=6, events=POLLIN}], 1, 4294967295) = 1 ([{fd=6, revents=POLLIN}]) recvmsg(6, {msg_name(0)=NULL, msg_iov(1)=[{"\1\2\235\0\0\0\0\0\t\0\300\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 4096}], msg_controllen=0, msg_flags=0}, 0) = 32 recvmsg(6, 0x7ffc5207d360, 0) = -1 EAGAIN (Resource temporarily unavailable) recvmsg(6, 0x7ffc5207d360, 0) = -1 EAGAIN (Resource temporarily unavailable) shutdown(6, SHUT_RDWR) = 0 close(6) = 0 rt_sigaction(SIGINT, {SIG_DFL, [INT], SA_RESTORER|SA_RESTART, 0x7f588f3df2f0}, {0x4381a0, ~[KILL STOP RTMIN RT_1], SA_RESTORER|SA_RESTART, 0x7f588f784d10}, 8) = 0 rt_sigaction(SIGTERM, {SIG_DFL, [TERM], SA_RESTORER|SA_RESTART, 0x7f588f3df2f0}, {0x4381a0, ~[KILL STOP RTMIN RT_1], SA_RESTORER|SA_RESTART, 0x7f588f784d10}, 8) = 0 exit_group(1) = ? +++ exited with 1 +++ parent is shutting down, bye... ``` Is this a issue with rxvt-unicode, or is there anything firejail can do to allow this still?
Author
Owner

@ghost commented on GitHub (Aug 17, 2015):

From your error messages, it seems that urxvt is trying to start the pt_chown program to set the permissions on the new pty. This will fail under --noroot as pt_chown needs to be SUID root to run. With the --noroot option, there is no root user to SUID to!

The manual page for pt_chown says: "If you are using a 2.1 or newer Linux kernel with the 'devptsfs' or 'devfs' filesystems providing pty slaves, you don't need this program".

Therefore it might be possible to compile urxvt without pt_chown support. I'm not an expert in urxvt so you'd have to do some research.

<!-- gh-comment-id:131953643 --> @ghost commented on GitHub (Aug 17, 2015): From your error messages, it seems that `urxvt` is trying to start the `pt_chown` program to set the permissions on the new pty. This will fail under `--noroot` as `pt_chown` needs to be SUID root to run. With the `--noroot` option, there is no root user to SUID to! The manual page for `pt_chown` says: "If you are using a 2.1 or newer Linux kernel with the 'devptsfs' or 'devfs' filesystems providing pty slaves, you don't need this program". Therefore it might be possible to compile urxvt without pt_chown support. I'm not an expert in urxvt so you'd have to do some research.
Author
Owner

@blueyed commented on GitHub (Aug 17, 2015):

The call to pt_chown seems to happen through grantpt in get_pty (in libptytty/src/ptytty.C) (I have added the printf):

#if defined(UNIX98_PTY)

  static int
  get_pty (int *fd_tty, char **ttydev)
  {
    int pfd;

# if defined(HAVE_GETPT)
    pfd = getpt ();
# elif defined(HAVE_POSIX_OPENPT)
    pfd = posix_openpt (O_RDWR | O_NOCTTY);
# else
#  ifdef _AIX
    pfd = open ("/dev/ptc", O_RDWR | O_NOCTTY, 0);
#  else
    pfd = open ("/dev/ptmx", O_RDWR | O_NOCTTY, 0);
#  endif
# endif

    if (pfd >= 0)
      {
        printf("pfd: %d, %d\n", grantpt(pfd), errno);
        if (grantpt (pfd) == 0  /* change slave permissions */
            && unlockpt (pfd) == 0)
          {
            /* slave now unlocked */
            *ttydev = strdup (ptsname (pfd));   /* get slave's name */
            return pfd;
          }

        close (pfd);
      }

    return -1;
  }

#elif defined(HAVE_OPENPTY)

errno is EAGAIN 11 Resource temporarily unavailable, and while it is not in my manpage for grantpt a search appears to indicate that it means [EAGAIN] The system has no available pseudo-terminal devices.

btw: with firejail --noroot groups I am only in my user's group and nogroup. Is this expected?

It seems like the name --noroot is a bit misleading, because it apparently does much more?!

<!-- gh-comment-id:131968693 --> @blueyed commented on GitHub (Aug 17, 2015): The call to `pt_chown` seems to happen through `grantpt` in `get_pty` (in libptytty/src/ptytty.C) (I have added the `printf`): ``` #if defined(UNIX98_PTY) static int get_pty (int *fd_tty, char **ttydev) { int pfd; # if defined(HAVE_GETPT) pfd = getpt (); # elif defined(HAVE_POSIX_OPENPT) pfd = posix_openpt (O_RDWR | O_NOCTTY); # else # ifdef _AIX pfd = open ("/dev/ptc", O_RDWR | O_NOCTTY, 0); # else pfd = open ("/dev/ptmx", O_RDWR | O_NOCTTY, 0); # endif # endif if (pfd >= 0) { printf("pfd: %d, %d\n", grantpt(pfd), errno); if (grantpt (pfd) == 0 /* change slave permissions */ && unlockpt (pfd) == 0) { /* slave now unlocked */ *ttydev = strdup (ptsname (pfd)); /* get slave's name */ return pfd; } close (pfd); } return -1; } #elif defined(HAVE_OPENPTY) ``` errno is `EAGAIN 11 Resource temporarily unavailable`, and while it is not in my manpage for `grantpt` a search appears to indicate that it means `[EAGAIN] The system has no available pseudo-terminal devices`. btw: with `firejail --noroot groups` I am only in my user's group and `nogroup`. Is this expected? It seems like the name `--noroot` is a bit misleading, because it apparently does much more?!
Author
Owner

@ghost commented on GitHub (Aug 17, 2015):

Personally, I think the --noroot option isn't misleading - it removes the root user. The pt_chown program is attempting to change to the root user (as it's installed SUID root), but firejail has removed the root user! Therefore the pt_chown program can't run, and the program can't allocate a pty.

This is basically exactly what firejail --noroot is meant to do! You've told firejail to remove the root user and block anything it does, for security. All modern Linuxes can work perfectly fine without a SUID program managing pseudo-terminals, whereas your Linux is running a SUID binary in the background without your knowledge. This is a potential security hole and is exactly the kind of thing that firejail was written for.

TL;DR you told firejail to block root, it succeeded.

<!-- gh-comment-id:131980339 --> @ghost commented on GitHub (Aug 17, 2015): Personally, I think the `--noroot` option isn't misleading - it removes the root user. The `pt_chown` program is attempting to change to the root user (as it's installed SUID root), but firejail has removed the root user! Therefore the `pt_chown` program can't run, and the program can't allocate a pty. This is basically exactly what `firejail --noroot` is meant to do! You've told firejail to remove the root user and block anything it does, for security. All modern Linuxes can work perfectly fine without a SUID program managing pseudo-terminals, whereas your Linux is running a SUID binary in the background without your knowledge. This is a potential security hole and is exactly the kind of thing that firejail was written for. TL;DR you told firejail to block root, it succeeded.
Author
Owner

@blueyed commented on GitHub (Aug 17, 2015):

Well, grantpt comes from glibc (so it should be pretty common?!).

And it uses pt_chown as a (fallback) helper based on HAVE_PT_CHOWN.

   The  grantpt() function changes the mode and owner of the slave pseudoter‐
   minal device corresponding to the master pseudoterminal referred to by fd.
   The  user  ID  of the slave is set to the real UID of the calling process.
   The group ID is set to an unspecified value (e.g., tty).  The mode of  the
   slave is set to 0620 (crw--w----).

It looks to me like the pt_chown call gets only done, because the regular chown fails, which is because with --noroot the tty group does not exist anymore:

% touch foo
% sudo chgrp tty foo
% chgrp tty foo
% firejail --noroot chgrp tty foo
Parent pid 31667, child pid 31668
Child process initialized
chgrp: changing group of ‘foo’: Invalid argument

parent is shutting down, bye...

% firejail chgrp tty foo
Parent pid 31801, child pid 31802
Child process initialized

parent is shutting down, bye...

chgrp (and chmod) succeed if the group is already set as expected.

<!-- gh-comment-id:131989618 --> @blueyed commented on GitHub (Aug 17, 2015): Well, `grantpt` comes from glibc (so it should be pretty common?!). And it uses `pt_chown` as a (fallback) helper based on HAVE_PT_CHOWN. ``` The grantpt() function changes the mode and owner of the slave pseudoter‐ minal device corresponding to the master pseudoterminal referred to by fd. The user ID of the slave is set to the real UID of the calling process. The group ID is set to an unspecified value (e.g., tty). The mode of the slave is set to 0620 (crw--w----). ``` It looks to me like the `pt_chown` call gets only done, because the regular `chown` fails, which is because with `--noroot` the `tty` group does not exist anymore: ``` % touch foo % sudo chgrp tty foo % chgrp tty foo % firejail --noroot chgrp tty foo Parent pid 31667, child pid 31668 Child process initialized chgrp: changing group of ‘foo’: Invalid argument parent is shutting down, bye... % firejail chgrp tty foo Parent pid 31801, child pid 31802 Child process initialized parent is shutting down, bye... ``` `chgrp` (and `chmod`) succeed if the group is already set as expected.
Author
Owner

@netblue30 commented on GitHub (Aug 18, 2015):

Not all programs run in "firejail --noroot". In fact, lots of them crash. SUID programs will fail trying to execute root-only operations, because there is no root user in the namespace.

rxvt example on a Debian system:

$ firejail --noroot rxvt 
Parent pid 5793, child pid 5794
Child process initialized
rxvt: can't open pseudo-tty
rxvt: aborting

parent is shutting down, bye...

rxvt is a SUID binary. Just don't use --noroot with SUID binaries.

<!-- gh-comment-id:132003924 --> @netblue30 commented on GitHub (Aug 18, 2015): Not all programs run in "firejail --noroot". In fact, lots of them crash. SUID programs will fail trying to execute root-only operations, because there is no root user in the namespace. rxvt example on a Debian system: ``` $ firejail --noroot rxvt Parent pid 5793, child pid 5794 Child process initialized rxvt: can't open pseudo-tty rxvt: aborting parent is shutting down, bye... ``` rxvt is a SUID binary. Just don't use --noroot with SUID binaries.
Author
Owner

@blueyed commented on GitHub (Aug 19, 2015):

Neither rxvt-unicode nor gnome-terminal is SUID on my system (I have not checked rxvt - /etc/alternatives/rxvt points at /usr/bin/urxvt here, but I use /usr/local/bin/urxvt usually).

gnome-terminal fails with grantpt failed: Exec format error when used in the vim-in-term script (which gets called from Firefox via Vimperator). That appears to indicate the same issue.

The workaround seems to be using noroot from the Firefox profile, but I've hoped that there was a better fix for this.

I still think that if the tty group (id) was provided with --noroot then it might work.

<!-- gh-comment-id:132495621 --> @blueyed commented on GitHub (Aug 19, 2015): Neither `rxvt-unicode` nor `gnome-terminal` is SUID on my system (I have not checked `rxvt` - `/etc/alternatives/rxvt` points at `/usr/bin/urxvt` here, but I use `/usr/local/bin/urxvt` usually). `gnome-terminal` fails with `grantpt failed: Exec format error` when used in the `vim-in-term` script (which gets called from Firefox via Vimperator). That appears to indicate the same issue. The workaround seems to be using `noroot` from the Firefox profile, but I've hoped that there was a better fix for this. I still think that if the `tty` group (id) was provided with `--noroot` then it might work.
Author
Owner

@blueyed commented on GitHub (Aug 19, 2015):

For what it's worth, my hack / workaround for this is currently this:

Index: src/ptytty.C
===================================================================
RCS file: /schmorpforge/libptytty/src/ptytty.C,v
retrieving revision 1.56
diff -u -r1.56 ptytty.C
--- src/ptytty.C    1 May 2015 13:12:17 -0000   1.56
+++ src/ptytty.C    19 Aug 2015 08:49:47 -0000
@@ -87,7 +87,7 @@

     if (pfd >= 0)
       {
-        if (grantpt (pfd) == 0 /* change slave permissions */
+        if ((grantpt (pfd) == 0 || errno == ENOEXEC || errno == EAGAIN)    /* change slave permissions */
             && unlockpt (pfd) == 0)
           {
             /* slave now unlocked */
<!-- gh-comment-id:132497941 --> @blueyed commented on GitHub (Aug 19, 2015): For what it's worth, my hack / workaround for this is currently this: ``` Index: src/ptytty.C =================================================================== RCS file: /schmorpforge/libptytty/src/ptytty.C,v retrieving revision 1.56 diff -u -r1.56 ptytty.C --- src/ptytty.C 1 May 2015 13:12:17 -0000 1.56 +++ src/ptytty.C 19 Aug 2015 08:49:47 -0000 @@ -87,7 +87,7 @@ if (pfd >= 0) { - if (grantpt (pfd) == 0 /* change slave permissions */ + if ((grantpt (pfd) == 0 || errno == ENOEXEC || errno == EAGAIN) /* change slave permissions */ && unlockpt (pfd) == 0) { /* slave now unlocked */ ```
Author
Owner

@ghost commented on GitHub (Aug 19, 2015):

A simple solution would be to use xterm instead of rxvt, as xterm works fine in --noroot mode. Is there any reason you can't use xterm instead? It would seem to be more secure than rxvt.

<!-- gh-comment-id:132544071 --> @ghost commented on GitHub (Aug 19, 2015): A simple solution would be to use `xterm` instead of `rxvt`, as `xterm` works fine in `--noroot` mode. Is there any reason you can't use xterm instead? It would seem to be more secure than rxvt.
Author
Owner

@netblue30 commented on GitHub (Aug 20, 2015):

The issue with --noroot is like this:

I instruct the kernel to create a user namespace, with no root user in the namespace, just the current user and the group associated with the current user. I don't add any supplementary group to the namespace. The kernel code decides what is permitted or not, and it will crash the process according to its own rules. The easy fix is not to use --noroot with some programs. The real fix would be to argue with the kernel people and convince them to change user namespace code - good luck with that!

tty group: users in this group have permission to open /dev/tty. If I add tty group to noroot namespace, everybody will have permission to access /dev/tty directly. I don't think is a good idea
.
gnome-terminal has lots of problems related with the way they handle the terminal. Like Firefox, they also run a single instance of the program. I usually stay with xterm and lxterminal (from LXDE).

<!-- gh-comment-id:133017091 --> @netblue30 commented on GitHub (Aug 20, 2015): The issue with --noroot is like this: I instruct the kernel to create a user namespace, with no root user in the namespace, just the current user and the group associated with the current user. I don't add any supplementary group to the namespace. The kernel code decides what is permitted or not, and it will crash the process according to its own rules. The easy fix is not to use --noroot with some programs. The real fix would be to argue with the kernel people and convince them to change user namespace code - good luck with that! tty group: users in this group have permission to open /dev/tty. If I add tty group to noroot namespace, everybody will have permission to access /dev/tty directly. I don't think is a good idea . gnome-terminal has lots of problems related with the way they handle the terminal. Like Firefox, they also run a single instance of the program. I usually stay with xterm and lxterminal (from LXDE).
Author
Owner

@blueyed commented on GitHub (Aug 20, 2015):

Thanks for your explanation and suggestion to use xterm, which works.
However, my config is tailored for rxvt-unicode and its features in general, and therefore will keep using my above patch instead for now.

<!-- gh-comment-id:133183885 --> @blueyed commented on GitHub (Aug 20, 2015): Thanks for your explanation and suggestion to use `xterm`, which works. However, my config is tailored for rxvt-unicode and its features in general, and therefore will keep using my above patch instead for now.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/firejail#18
No description provided.