]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
terminal-util: when querying bg color, ensure input fd and output fd refer to same tty
authorLennart Poettering <lennart@poettering.net>
Wed, 10 Jul 2024 15:18:55 +0000 (17:18 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 19 Jul 2024 09:41:43 +0000 (11:41 +0200)
Let's add an extra safety check: before issuing the ansi sequence to
query the bg color, let's make sure input and output fd actually
reference the same tty. because otherwise it's unlikely we'll be able to
read back the response from the tty driver.

This is mostly just paranoia.

src/basic/terminal-util.c

index 2ea502c2bcd860bb446fadfb05291b571dc6c2ea..fb6c9177d4936167a57cf57ba989612bff84da6e 100644 (file)
@@ -1576,6 +1576,37 @@ void termios_disable_echo(struct termios *termios) {
         termios->c_cc[VTIME] = 0;
 }
 
+static int terminal_verify_same(int input_fd, int output_fd) {
+        assert(input_fd >= 0);
+        assert(output_fd >= 0);
+
+        /* Validates that the specified fds reference the same TTY */
+
+        if (input_fd != output_fd) {
+                struct stat sti;
+                if (fstat(input_fd, &sti) < 0)
+                        return -errno;
+
+                if (!S_ISCHR(sti.st_mode)) /* TTYs are character devices */
+                        return -ENOTTY;
+
+                struct stat sto;
+                if (fstat(output_fd, &sto) < 0)
+                        return -errno;
+
+                if (!S_ISCHR(sto.st_mode))
+                        return -ENOTTY;
+
+                if (sti.st_rdev != sto.st_rdev)
+                        return -ENOLINK;
+        }
+
+        if (!isatty_safe(input_fd)) /* The check above was just for char device, but now let's ensure it's actually a tty */
+                return -ENOTTY;
+
+        return 0;
+}
+
 typedef enum BackgroundColorState {
         BACKGROUND_TEXT,
         BACKGROUND_ESCAPE,
@@ -1736,8 +1767,9 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret
         if (!colors_enabled())
                 return -EOPNOTSUPP;
 
-        if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO))
-                return -EOPNOTSUPP;
+        r = terminal_verify_same(STDIN_FILENO, STDOUT_FILENO);
+        if (r < 0)
+                return r;
 
         if (streq_ptr(getenv("TERM"), "linux")) {
                 /* Linux console is black */