Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Tue, 18 Apr 2023 22:12:29 +0200
From: Steffen Nurpmeso <steffen@...oden.eu>
To: oss-security@...ts.openwall.com
Subject: Re: CVE-2023-2002: Linux Bluetooth:
 Unauthorized management command execution

Todd C. Miller wrote in
 <043b8fbe6e014f17@...lert.dev>:
 |On Wed, 19 Apr 2023 02:59:26 +0800, Ruihan Li wrote:
 |
 |> Yeah, I see that you are removing ioctl calls on standard file
 |> descriptors. So actually, just to confirm, it is feasible to avoid
 |> all ioctl calls to standard file descriptors with root privileges
 |> (under all command line arguments), by using /dev/tty, assuming
 |> something like the window size... Right?
 |
 |For the most part, yes.  There are still some calls to isatty(3)

Frozen asset that i am,.., but i want to add this.
The POSIX standard says (i think quoting C99)

  [.]the standard input and standard output streams are fully
  buffered if and only if stream can be determined not to refer to
  an interactive device.[.]

Unless there is a new way of checking and/or unless creating
interactive devices is restrained to /dev/tty (pty etc) it seems
some calls done by C libraries cannot be avoided, only be delayed
a bit further down the road than what musl does.

  $ cat t.c
  #include <stdio.h>
  int main(void) { putc('\n',stdout);return 0; }
  $ gcc -o zt t.c

GNU libc:

  $ strace ./zt
  newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x3), ...}, AT_EMPTY_PATH) = 0

  $ strace ./zt >/dev/null
  newfstatat(1, "", {st_mode=S_IFCHR|0666, st_rdev=makedev(0x1, 0x3), ...}, AT_EMPTY_PATH) = 0
  ioctl(1, TCGETS, 0x7ffe2151dc30)        = -1 ENOTTY (Inappropriate ioctl for device)

  $ mkfifo c; cat < c & strace ./zt > c
  newfstatat(1, "", {st_mode=S_IFIFO|0640, st_size=0, ...}, AT_EMPTY_PATH) = 0

musl always simply says

  ioctl(1, TIOCGWINSZ, {ws_row=55, ws_col=191, ws_xpixel=1910, ws_ypixel=1045}) = 0
or
  ... = -1 ENOTTY (Not a tty)

 |using the standard file descriptors when setting up the event loop
 |to run the program but that is after the user has been verified.
 |I will add checks that the fd is a character special file before
 |calling isatty(3).  In most cases the code wants the contents of
 |struct stat anyway, so the S_ISCHR check is basically free.
 |
 |> If this is the case, I think it should not be difficult for other
 |> setuid programs to do similar things.  I am just thinking for a
 |> while, and cannot find a case where ioctl calls are unavoidable.
 |
 |If there are setuid programs that call ttyname(3) that will also
 |call tcgetattr(3).  Also, the glibc getpass(3) function will use
 |tcgetattr(3) and tcsetattr(3) (to disable echo) on the standard
 |input if /dev/tty is not available.  For getpass(3) this could be
 |avoided by only trying to disable echo when using /dev/tty.  That
 |would change the behavior of things like:
 |
 |    su < /some/other/tty 

..even though it mostly reiterates what is said.

 |when /dev/tty is unavailable but I don't know what use case that
 |would actually support.

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.