[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    _BRANCH Konsole & FreeBSD
From:       Adriaan de Groot <adridg () cs ! kun ! nl>
Date:       2003-08-24 21:56:59
[Download RAW message or body]

Many moons ago, I wrote patches to get konsole to work around many linuxistic 
assumptions and actually invoke konsole_grantpty properly; recent changes in 
-CURRENT that break konsole wrt. gethostname() reminded me that I still 
haven't committed them nor ported them to HEAD. Find attached a patch:

* Makes the FD that konsole_grantpty uses a parameter. To be sure, I can't 
tell what the security implications of this change might be. I can imagine

	konsole_grantpty --revoke 3> /tmp/bar

actually already as a way to mess with /tmp/bar (well, if it was a tty).

To be on the safe side, konsole_grantpty should still work with FD 3 if no 
extra parameter is given. This allows the patched konsole_grantpty to work 
with older konsole's. Might be overkill, though.

* gethostname() may also return ENAMETOOLONG.

* ttyname() only works on ttys, not ptys in FreeBSD.

* Use Q_OS_FREEBSD instead of __FreeBSD__.


OK to apply? Look sensible for HEAD as well?

-- 
pub  1024D/FEA2A3FE 2002-06-18 Adriaan de Groot <groot@kde.org>
     Key fingerprint = 934E 31AA 80A7 723F 54F9  50ED 76AC EE01 FEA2 A3FE

["konsole.diff" (text/x-diff)]

Index: TEPty.cpp
===================================================================
RCS file: /home/kde/kdebase/konsole/konsole/TEPty.cpp,v
retrieving revision 1.75
diff -u -3 -p -r1.75 TEPty.cpp
--- TEPty.cpp	22 Nov 2002 13:17:57 -0000	1.75
+++ TEPty.cpp	24 Aug 2003 21:44:00 -0000
@@ -65,6 +65,9 @@
 #include <config.h>
 #endif
 
+// Get the Q_OS_* defines
+#include <qglobal.h>
+
 #ifdef __sgi
 #define __svr4__
 #endif
@@ -88,6 +91,10 @@
 #include <sys/types.h>
 #endif
 
+#ifdef Q_OS_FREEBSD
+#include <sys/param.h>
+#endif
+
 #include <stdlib.h>
 #include <stdio.h>
 
@@ -198,9 +205,30 @@ public:
 
 FILE* syslog_file = NULL; //stdout;
 
-#define PTY_FILENO 3
+#define DEFAULT_PTY_FILENO 3
+int PTY_FILENO = -1; // None allocated yet.
+
 #define BASE_CHOWN "konsole_grantpty"
 
+void TEPtyInit()
+{
+/*
+** FreeBSD can't dup2(fd,3) because fd 3 is already in use by
+** some weird pipe. So instead, we get a new throwaway fd
+** that's not in use by anyone.
+*/
+#ifdef Q_OS_FREEBSD
+  PTY_FILENO = open("/dev/null",O_RDWR);
+  if (PTY_FILENO == -1) {
+    perror("konsole:open PTY");
+    /* This won't work either, but hey .. */
+    PTY_FILENO = DEFAULT_PTY_FILENO;
+  }
+#else
+  PTY_FILENO = DEFAULT_PTY_FILENO;
+#endif
+}
+
 int chownpty(int fd, bool grant)
 // param fd: the fd of a master pty.
 // param grant: true to grant, false to revoke
@@ -212,6 +240,8 @@ int chownpty(int fd, bool grant)
   newsa.sa_flags = 0;
   sigaction(SIGCHLD, &newsa, &oldsa);
 
+  if (PTY_FILENO == -1) TEPtyInit();
+
   pid_t pid = fork();
   if (pid < 0)
   {
@@ -225,7 +255,12 @@ int chownpty(int fd, bool grant)
     /* We pass the master pseudo terminal as file descriptor PTY_FILENO. */
     if (fd != PTY_FILENO && dup2(fd, PTY_FILENO) < 0) exit(1);
     QString path = locate("exe", BASE_CHOWN);
-    execle(path.ascii(), BASE_CHOWN, grant?"--grant":"--revoke", NULL, NULL);
+    /*
+    ** Because konsole_grantpty now can't expect the fd
+    ** to be constant, we need an additional parameter.
+    */
+    QString fdnumber = QString::number(PTY_FILENO);
+    execle(path.ascii(), BASE_CHOWN, grant?"--grant":"--revoke", fdnumber.ascii(), \
NULL, NULL);  exit(1); // should not be reached
   }
 
@@ -486,6 +521,16 @@ int TEPty::makePty(bool _addutmp)
   // open and set all standard files to slave tty
   int tt = m_SlaveFd; // Already opened?
 
+#ifdef Q_OS_FREEBSD
+  /*
+  ** It seems to be possible for SlaveFd to be closed in error
+  ** somewhere along the line. So check it for "liveness".
+  */
+  struct stat sb;
+  if (fstat(tt,&sb)!=0)
+    tt=-1; // Apparently not alive.
+#endif
+
   if (tt < 0)
     tt = open(ttynam, O_RDWR);
 
@@ -524,14 +569,57 @@ int TEPty::makePty(bool _addutmp)
   }
   strncpy(l_struct.ut_name, str_ptr, UT_NAMESIZE);
 
+#ifdef Q_OS_FREEBSD
+     /* FreeBSD until august 22, 2003 returned ENOMEM for too-long
+     ** hostnames. Then sanity prevailed (?) and the error was changed
+     ** to NAMETOOLONG, but this breaks konsole .. again.
+     **
+     ** Instead of bailing out with long hostnames, put in partial
+     ** hostnames (the first UT_HOSTSIZE characters) instead.
+     */
+  char hostnamebuffer[MAXHOSTNAMELEN+1];
+  memset(hostnamebuffer,0,MAXHOSTNAMELEN+1);
+  if (gethostname(hostnamebuffer, MAXHOSTNAMELEN) == -1)
+  {
+     if ( (errno==ENOMEM) || (errno==ENAMETOOLONG) ) {
+       /* ignore it, but very odd */
+     }
+     else {
+       /* Not much chance of this being visible anywhere ... */
+       perror("konsole:gethostname");
+       abort();
+     }
+  }
+  /* Copy hostname, possibly only partially */
+  memset(l_struct.ut_host,0,UT_HOSTSIZE);
+  strncpy(l_struct.ut_host,hostnamebuffer,UT_HOSTSIZE);
+  l_struct.ut_host[UT_HOSTSIZE]=0;
+#else
+  /* Non-FreeBSD systems */
   if (gethostname(l_struct.ut_host, UT_HOSTSIZE) == -1) {
-     if (errno != ENOMEM)
+     if  (errno != ENOMEM)
         abort();
      l_struct.ut_host[UT_HOSTSIZE]=0;
   }
+#endif
 
   if (! (str_ptr=ttyname(tt)) ) {
+#ifdef Q_OS_FREEBSD
+    /*
+    ** In FreeBSD, the ttyname() call always returns NULL
+    ** for the kinds of devices (ptys) we have opened,
+    ** so don't abort, use a foolish default value instead.
+    ** The call to login() probably won't work _anyway_,
+    ** since normally users can't update the wtmp file.
+    **
+    ** If we were real sticklers for accuracy, we'd copy the
+    ** code from konsole_grantpty that does it's darndest to
+    ** file out the right tty name.
+    */
+    str_ptr = const_cast<char *>("/dev/konsole");
+#else
     abort();
+#endif
   }
   if (strncmp(str_ptr, "/dev/", 5) == 0)
        str_ptr += 5;
@@ -607,7 +695,7 @@ void TEPty::startPgm(const char* pgm, QV
 // #define CERASE 0177
 // #endif
 
-#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \
defined (__bsdi__) || defined(__APPLE__) +#if defined (Q_OS_FREEBSD) || defined \
(__NetBSD__) || defined (__OpenBSD__) || defined (__bsdi__) || defined(__APPLE__)  \
ioctl(0,TIOCGETA,(char *)&ttmode);  #else
 #   if defined (_HPUX_SOURCE) || defined(__Lynx__)
@@ -621,7 +709,7 @@ void TEPty::startPgm(const char* pgm, QV
       ttmode.c_cc[VINTR] = CTRL('C');
       ttmode.c_cc[VQUIT] = CTRL('\\');
       ttmode.c_cc[VERASE] = 0177;
-#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \
defined (__bsdi__) || defined(__APPLE__) +#if defined (Q_OS_FREEBSD) || defined \
(__NetBSD__) || defined (__OpenBSD__) || defined (__bsdi__) || defined(__APPLE__)  \
ioctl(0,TIOCSETA,(char *)&ttmode);  #else
 #   ifdef _HPUX_SOURCE
Index: konsole_grantpty.c
===================================================================
RCS file: /home/kde/kdebase/konsole/konsole/Attic/konsole_grantpty.c,v
retrieving revision 1.7
diff -u -3 -p -r1.7 konsole_grantpty.c
--- konsole_grantpty.c	2 Sep 2002 01:09:24 -0000	1.7
+++ konsole_grantpty.c	24 Aug 2003 21:44:01 -0000
@@ -40,7 +40,9 @@
 #  include <dirent.h>
 #endif
 
-#define PTY_FILENO 3    /* keep in sync with grantpty */
+#define DEFAULT_PTY_FILENO 3 /* keep in sync with TEPty.cpp */
+int PTY_FILENO = DEFAULT_PTY_FILENO;
+
 #define TTY_GROUP "tty"
 
 int main (int argc, char *argv[])
@@ -52,11 +54,13 @@ int main (int argc, char *argv[])
   uid_t         uid;
   mode_t        mod;
   char*         tty;
+  int           command_fd; /* which fd to use? */
 
   /* check preconditions **************************************************/
-  if (argc != 2 || (strcmp(argv[1],"--grant") && strcmp(argv[1],"--revoke")))
+  if (( (argc != 3) && (argc != 2) /* optional third arg */ ) || 
+    (strcmp(argv[1],"--grant") && strcmp(argv[1],"--revoke")))
   {
-    printf("usage: %s (--grant|--revoke)\n",argv[0]);
+    printf("usage: %s (--grant|--revoke) [fd]\n",argv[0]);
     printf("%s is a helper for\n",argv[0]);
     printf("konsole and not intented to\n");
     printf("be called from the command\n");
@@ -83,6 +87,22 @@ int main (int argc, char *argv[])
     uid = 0;        /* root */
     mod = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
   }
+
+  command_fd = DEFAULT_PTY_FILENO;
+  if (argv[2])
+  {
+    command_fd = atoi(argv[2]);
+  }
+  if (command_fd > 2) /* must be out of stdin,stdout,stderr range */
+  {
+    PTY_FILENO=command_fd;
+  }
+  else
+  {
+    fprintf(stderr,"%s: Bad command fd (seems to be %d)\n",argv[0],command_fd);
+    return 1;
+  }
+  
   /* Get the group ID of the special `tty' group.  */
   p = getgrnam(TTY_GROUP);            /* posix */
   gid = p ? p->gr_gid : getgid ();    /* posix */
@@ -117,6 +137,9 @@ int main (int argc, char *argv[])
           if (dirp->d_fileno != dsb.st_ino)
             continue;
 	  {
+	  /* Else this is the right device file .. any possible memory
+	  ** leak here because two files match is unimportant?
+	  */
 	  int pdlen = strlen(_PATH_DEV), namelen = strlen(dirp->d_name);
 	  pty = malloc(pdlen + namelen + 1);
 	  if (pty) {
Index: main.cpp
===================================================================
RCS file: /home/kde/kdebase/konsole/konsole/main.cpp,v
retrieving revision 1.243.2.3
diff -u -3 -p -r1.243.2.3 main.cpp
--- main.cpp	29 Jun 2003 21:53:11 -0000	1.243.2.3
+++ main.cpp	24 Aug 2003 21:44:02 -0000
@@ -123,6 +123,7 @@ public:
 };
 
 
+extern void TEPtyInit();
 
 /* --| main |------------------------------------------------------ */
 int main(int argc, char* argv[])
@@ -137,6 +138,7 @@ int main(int argc, char* argv[])
   bool scrollbaron = true;
   QCString wname = PACKAGE;
 
+  TEPtyInit();
 
   KAboutData aboutData( PACKAGE, I18N_NOOP("Konsole"),
     VERSION, description, KAboutData::License_GPL_V2,



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic