Print this page
12306 XPG4v2 slave pty behaviour should generally be disabled
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Change-ID: I7ccd399c22866f34dd20c6bb9d28e77ba4e24c67

@@ -23,11 +23,11 @@
 
 
 /*
  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2017 Joyent, Inc.
- * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
+ * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
  */
 
 #include <sys/types.h>
 #include <sys/sysmacros.h>
 #include <sys/param.h>

@@ -76,10 +76,11 @@
 #include <sys/sunldi_impl.h>
 #include <sys/autoconf.h>
 #include <sys/policy.h>
 #include <sys/dld.h>
 #include <sys/zone.h>
+#include <sys/ptms.h>
 #include <c2/audit.h>
 
 /*
  * This define helps improve the readability of streams code while
  * still maintaining a very old streams performance enhancement.  The

@@ -229,10 +230,54 @@
         mutex_exit(&stp->sd_lock);
 
         return (0);
 }
 
+static int
+xpg4_fixup(queue_t *qp, dev_t *devp, struct stdata *stp, cred_t *crp)
+{
+        static const char *ptsmods[] = {
+            "ptem", "ldterm", "ttcompat"
+        };
+        dev_t dummydev = *devp;
+        struct strioctl strioc;
+        zoneid_t zoneid;
+        int32_t rval;
+        uint_t i;
+
+        /*
+         * Push modules required for the slave PTY to have terminal
+         * semantics out of the box; this is required by XPG4v2.
+         * These three modules are flagged as single-instance so that
+         * the system will never end up with duplicate copies pushed
+         * onto a stream.
+         */
+
+        zoneid = crgetzoneid(crp);
+        for (i = 0; i < ARRAY_SIZE(ptsmods); i++) {
+                int error;
+
+                error = push_mod(qp, &dummydev, stp, ptsmods[i], 0,
+                    crp, zoneid);
+                if (error != 0)
+                        return (error);
+        }
+
+        /*
+         * Send PTSSTTY down the stream
+         */
+
+        strioc.ic_cmd = PTSSTTY;
+        strioc.ic_timout = 0;
+        strioc.ic_len = 0;
+        strioc.ic_dp = NULL;
+
+        (void) strdoioctl(stp, &strioc, FNATIVE, K_TO_K, crp, &rval);
+
+        return (0);
+}
+
 /*
  * Open a stream device.
  */
 int
 stropen(vnode_t *vp, dev_t *devp, int flag, cred_t *crp)

@@ -547,14 +592,19 @@
         sad_ap_rele(ap, ss);
         netstack_rele(ss->ss_netstack);
 
 opendone:
 
+        if (error == 0 &&
+            (stp->sd_flag & (STRISTTY|STRXPG4TTY)) == (STRISTTY|STRXPG4TTY)) {
+                error = xpg4_fixup(qp, devp, stp, crp);
+        }
+
         /*
          * let specfs know that open failed part way through
          */
-        if (error) {
+        if (error != 0) {
                 mutex_enter(&stp->sd_lock);
                 stp->sd_flag |= STREOPENFAIL;
                 mutex_exit(&stp->sd_lock);
         }