]> sourceware.org Git - systemtap.git/blobdiff - stap-serverd.cxx
step-prep: on debian/ubuntu machines, attempt "apt-get -y install"
[systemtap.git] / stap-serverd.cxx
index dd7cbadf08bc4b1d67bd80feabb699873e672fef..d556104f754dde5f5e27ac664eb552ecf5b659ef 100644 (file)
@@ -3,7 +3,7 @@
   the data into a temporary file, calls the systemtap translator and
   then transmits the resulting file back to the client.
 
-  Copyright (C) 2011-2014 Red Hat Inc.
+  Copyright (C) 2011-2018 Red Hat Inc.
 
   This file is part of systemtap, and is free software.  You can
   redistribute it and/or modify it under the terms of the GNU General Public
@@ -27,6 +27,7 @@
 #include <climits>
 #include <iostream>
 #include <map>
+#include <thread>
 
 extern "C" {
 #include <unistd.h>
@@ -72,8 +73,6 @@ static PRStatus spawn_and_wait (const vector<string> &argv, int *result,
                                 const char* fd0, const char* fd1, const char* fd2,
                                const char *pwd, const vector<string>& envVec = vector<string> ());
 
-#define MOK_PUBLIC_CERT_NAME "signing_key.x509"
-#define MOK_PUBLIC_CERT_FILE "/" MOK_PUBLIC_CERT_NAME
 #define MOK_PRIVATE_CERT_NAME "signing_key.priv"
 #define MOK_PRIVATE_CERT_FILE "/" MOK_PRIVATE_CERT_NAME
 #define MOK_CONFIG_FILE "/x509.genkey"
@@ -108,8 +107,7 @@ static size_t max_uncompressed_req_size;
 static size_t max_compressed_req_size;
 static string cert_db_path;
 static string stap_options;
-static string uname_r;
-static string kernel_build_tree;
+static map<string,string> kernel_build_tree; // Kernel version -> build tree
 static string arch;
 static string cert_serial_number;
 static string B_options;
@@ -182,16 +180,9 @@ static void
 process_r (const string &arg)
 {
   if (arg[0] == '/') // fully specified path
-    {
-      kernel_build_tree = arg;
-      uname_r = kernel_release_from_build_tree (arg);
-    }
+    kernel_build_tree.insert({kernel_release_from_build_tree(arg), arg});
   else
-    {
-      kernel_build_tree = "/lib/modules/" + arg + "/build";
-      uname_r = arg;
-    }
-  stap_options += " -r " + arg; // Pass the argument to stap directly.
+    kernel_build_tree.insert({arg, "/lib/modules/" + arg + "/build" });
 }
 
 static void
@@ -292,7 +283,7 @@ parse_options (int argc, char **argv)
          if (*num_endptr != '\0')
            fatal (_F("%s: cannot parse number '--max-request-size=%s'", argv[0], optarg));
           else if (maxsize_tmp < 1)
-           fatal (_F("%s: invalid entry: max (uncompressed) request size must not be greater than 0 '--max-request-size=%s'",
+           fatal (_F("%s: invalid entry: max (uncompressed) request size must be greater than 0 '--max-request-size=%s'",
                      argv[0], optarg));
           max_uncompressed_req_size = (size_t) maxsize_tmp; // convert the long to an unsigned
           break;
@@ -301,7 +292,7 @@ parse_options (int argc, char **argv)
          if (*num_endptr != '\0')
            fatal (_F("%s: cannot parse number '--max-compressed-request=%s'", argv[0], optarg));
           else if (maxsize_tmp < 1)
-           fatal (_F("%s: invalid entry: max compressed request size must not be greater than 0 '--max-compressed-request=%s'",
+           fatal (_F("%s: invalid entry: max compressed request size must be greater than 0 '--max-compressed-request=%s'",
                      argv[0], optarg));
           max_compressed_req_size = (size_t) maxsize_tmp; // convert the long to an unsigned
           break;
@@ -632,11 +623,11 @@ create_services (AvahiClient *c)
   if (! avahi_group)
     {
       if (! (avahi_group = avahi_entry_group_new (c, entry_group_callback, NULL)))
-       {
-         server_error (_F("avahi_entry_group_new () failed: %s",
-                          avahi_strerror (avahi_client_errno (c))));
-         return;
-       }
+        {
+          server_error (_F("avahi_entry_group_new () failed: %s",
+          avahi_strerror (avahi_client_errno (c))));
+          return;
+        }
     }
   else
     avahi_entry_group_reset(avahi_group);
@@ -644,89 +635,95 @@ create_services (AvahiClient *c)
   // Contruct the information needed for our service.
   log (_F("Adding Avahi service '%s'", avahi_service_name));
 
-  // Create the txt tags that will be registered with our service.
-  string sysinfo = "sysinfo=" + uname_r + " " + arch;
-  string certinfo = "certinfo=" + cert_serial_number;
-  string version = string ("version=") + CURRENT_CS_PROTOCOL_VERSION;;
-  string optinfo = "optinfo=";
-  string separator;
-  // These option strings already have a leading space.
-  if (! R_option.empty ())
-    {
-      optinfo += R_option.substr(1);
-      separator = " ";
-    }
-  if (! B_options.empty ())
-    {
-      optinfo += separator + B_options.substr(1);
-      separator = " ";
-    }
-  if (! D_options.empty ())
-    {
-      optinfo += separator + D_options.substr(1);
-      separator = " ";
-    }
-  if (! I_options.empty ())
-    optinfo += separator + I_options.substr(1);
-
-  // Create an avahi string list with the info we have so far.
-  vector<string> mok_fingerprints;
-  AvahiStringList *strlst = avahi_string_list_new(sysinfo.c_str (),
-                                                 optinfo.c_str (),
-                                                 version.c_str (),
-                                                 certinfo.c_str (), NULL);
-  if (strlst == NULL)
-    {
-      server_error (_("Failed to allocate string list"));
-      goto fail;
-    }
+  AvahiStringList *strlst = NULL;
+  int ret;
+  for (auto it = kernel_build_tree.cbegin(); it != kernel_build_tree.cend(); ++it)
+    {
+      // Create the txt tags that will be registered with our service.
+      string sysinfo = "sysinfo=" + it->first + " "+ arch;
+      string certinfo = "certinfo=" + cert_serial_number;
+      string version = string ("version=") + CURRENT_CS_PROTOCOL_VERSION;;
+      string optinfo = "optinfo=";
+      string separator;
+      // These option strings already have a leading space.
+      if (! R_option.empty ())
+        {
+          optinfo += R_option.substr(1);
+          separator = " ";
+        }
+      if (! B_options.empty ())
+        {
+          optinfo += separator + B_options.substr(1);
+          separator = " ";
+        }
+      if (! D_options.empty ())
+        {
+          optinfo += separator + D_options.substr(1);
+          separator = " ";
+        }
+      if (! I_options.empty ())
+        optinfo += separator + I_options.substr(1);
+
+      // Create an avahi string list with the info we have so far.
+      vector<string> mok_fingerprints;
+      strlst = avahi_string_list_new(sysinfo.c_str (),
+                                     optinfo.c_str (),
+                                     version.c_str (),
+                                     certinfo.c_str (), NULL);
+      if (strlst == NULL)
+        {
+          server_error (_("Failed to allocate string list"));
+          goto fail;
+        }
 
-  // Add server MOK info, if available.
-  get_server_mok_fingerprints (mok_fingerprints, true, false);
-  if (! mok_fingerprints.empty())
-    {
-      vector<string>::const_iterator it;
-      for (it = mok_fingerprints.begin(); it != mok_fingerprints.end(); it++)
+      // Add server MOK info, if available.
+      get_server_mok_fingerprints (mok_fingerprints, true, false);
+      if (! mok_fingerprints.empty())
         {
-         string tmp = "mok_info=" + *it;
-         strlst = avahi_string_list_add(strlst, tmp.c_str ());
-         if (strlst == NULL)
-           {
-             server_error (_("Failed to add a string to the list"));
-             goto fail;
-           }
-       }
-    }
+          for (auto it = mok_fingerprints.cbegin(); it != mok_fingerprints.cend(); it++)
+            {
+              string tmp = "mok_info=" + *it;
+              strlst = avahi_string_list_add(strlst, tmp.c_str ());
+              if (strlst == NULL)
+                {
+                  server_error (_("Failed to add a string to the list"));
+                  goto fail;
+                }
+            }
+        }
 
-  // We will now add our service to the entry group.
-  // Loop until no collisions.
-  int ret;
-  for (;;) {
-    ret = avahi_entry_group_add_service_strlst (avahi_group,
-                                               AVAHI_IF_UNSPEC,
-                                               AVAHI_PROTO_UNSPEC,
-                                               (AvahiPublishFlags)0,
-                                               avahi_service_name,
-                                               avahi_service_tag,
-                                               NULL, NULL, port, strlst);
-    if (ret == AVAHI_OK)
-      break; // success!
-
-    if (ret == AVAHI_ERR_COLLISION)
-      {
-       // A service name collision with a local service happened.
-       // Pick a new name.
-       if (rename_service () < 0) {
-         // Too many collisions. Message already issued.
-         goto fail;
-       }
-       continue; // try again.
+      // We will now add our service to the entry group.
+      // Loop until no collisions.
+      for (;;) {
+        ret = avahi_entry_group_add_service_strlst (avahi_group,
+                                                    AVAHI_IF_UNSPEC,
+                                                    AVAHI_PROTO_UNSPEC,
+                                                    (AvahiPublishFlags)0,
+                                                    avahi_service_name,
+                                                    avahi_service_tag,
+                                                    NULL, NULL, port, strlst);
+        if (ret == AVAHI_OK)
+          break; // success!
+
+        if (ret == AVAHI_ERR_COLLISION)
+          {
+            // A service name collision with a local service happened.
+            // Pick a new name.
+            if (rename_service () < 0) {
+              // Too many collisions. Message already issued.
+              goto fail;
+            }
+            continue; // try again.
+          }
+
+          server_error (_F("Failed to add %s service: %s",
+              avahi_service_tag, avahi_strerror (ret)));
+          goto fail;
       }
 
-      server_error (_F("Failed to add %s service: %s",
-                      avahi_service_tag, avahi_strerror (ret)));
-      goto fail;
-  }
+      avahi_string_list_free(strlst);
+      strlst = NULL;
+    }
 
   // Tell the server to register the service.
   if ((ret = avahi_entry_group_commit (avahi_group)) < 0)
@@ -734,8 +731,6 @@ create_services (AvahiClient *c)
       server_error (_F("Failed to commit avahi entry group: %s", avahi_strerror (ret)));
       goto fail;
     }
-
-  avahi_string_list_free(strlst);
   return;
 
  fail:
@@ -985,14 +980,13 @@ initialize (int argc, char **argv) {
   // Initial values.
   use_db_password = false;
   port = 0;
-  max_threads = sysconf( _SC_NPROCESSORS_ONLN ); // Default to number of processors
-  max_uncompressed_req_size = 50000; // 50 KB <- default max uncompressed request size
-  max_compressed_req_size = 5000; // 5 KB <- default max compressed request size
+  max_threads = thread::hardware_concurrency(); // Default to number of processors
+  max_uncompressed_req_size = 50000; // 50 KB: default max uncompressed request size
+  max_compressed_req_size = 5000; // 5 KB: default max compressed request size
   keep_temp = false;
   struct utsname utsname;
   uname (& utsname);
-  uname_r = utsname.release;
-  kernel_build_tree = "/lib/modules/" + uname_r + "/build";
+  kernel_build_tree.insert({utsname.release, "/lib/modules/" + string(utsname.release) + "/build"});
   arch = normalize_machine (utsname.machine);
 
   // Parse the arguments. This also starts the server log, if any, and should be done before
@@ -1131,7 +1125,7 @@ readDataFromSocket(PRFileDesc *sslSocket, const char *requestFileName)
 /* Function:  setupSSLSocket()
  *
  * Purpose:  Configure a socket for SSL.
- *
+ * In case of failure, clean up the incoming tcpSocket and/or any partially setup sslSocket.
  *
  */
 static PRFileDesc * 
@@ -1146,8 +1140,7 @@ setupSSLSocket (PRFileDesc *tcpSocket, CERTCertificate *cert, SECKEYPrivateKey *
   if (sslSocket == NULL)
     {
       server_error (_("Could not import socket into SSL"));
-      nssError ();
-      return NULL;
+      goto error;
     }
    
   /* Set the appropriate flags. */
@@ -1155,32 +1148,28 @@ setupSSLSocket (PRFileDesc *tcpSocket, CERTCertificate *cert, SECKEYPrivateKey *
   if (secStatus != SECSuccess)
     {
       server_error (_("Error setting SSL security for socket"));
-      nssError ();
-      return NULL;
+      goto error;
     }
 
   secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
   if (secStatus != SECSuccess)
     {
       server_error (_("Error setting handshake as server for socket"));
-      nssError ();
-      return NULL;
+      goto error;
     }
 
   secStatus = SSL_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE, PR_FALSE);
   if (secStatus != SECSuccess)
     {
       server_error (_("Error setting SSL client authentication mode for socket"));
-      nssError ();
-      return NULL;
+      goto error;
     }
 
   secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
   if (secStatus != SECSuccess)
     {
       server_error (_("Error setting SSL client authentication mode for socket"));
-      nssError ();
-      return NULL;
+      goto error;
     }
 
   /* Set the appropriate callback routines. */
@@ -1188,18 +1177,16 @@ setupSSLSocket (PRFileDesc *tcpSocket, CERTCertificate *cert, SECKEYPrivateKey *
   secStatus = SSL_AuthCertificateHook (sslSocket, myAuthCertificate, CERT_GetDefaultCertDB());
   if (secStatus != SECSuccess)
     {
-      nssError ();
       server_error (_("Error in SSL_AuthCertificateHook"));
-      return NULL;
+      goto error;
     }
 #endif
 #if 0 /* Use the default */
   secStatus = SSL_BadCertHook(sslSocket, (SSLBadCertHandler)myBadCertHandler, &certErr);
   if (secStatus != SECSuccess)
     {
-      nssError ();
       server_error (_("Error in SSL_BadCertHook"));
-      return NULL;
+      goto error;
     }
 #endif
 #if 0 /* no handshake callback */
@@ -1207,8 +1194,7 @@ setupSSLSocket (PRFileDesc *tcpSocket, CERTCertificate *cert, SECKEYPrivateKey *
   if (secStatus != SECSuccess)
     {
       server_error (_("Error in SSL_HandshakeCallback"));
-      nssError ();
-      return NULL;
+      goto error;
     }
 #endif
 
@@ -1218,11 +1204,27 @@ setupSSLSocket (PRFileDesc *tcpSocket, CERTCertificate *cert, SECKEYPrivateKey *
   if (secStatus != SECSuccess)
     {
       server_error (_("Error configuring SSL server"));
-      nssError ();
-      return NULL;
+      goto error;
     }
 
   return sslSocket;
+
+ error:
+  nssError();
+
+  if (sslSocket) {
+    if (PR_Close (sslSocket) != PR_SUCCESS) {
+      server_error (_("Error closing ssl socket"));
+      nssError ();
+    }
+  } else {
+    if (PR_Close (tcpSocket) != PR_SUCCESS) {
+      server_error (_("Error closing tcp/ssl socket"));
+      nssError ();
+    }
+  }
+  
+  return NULL;
 }
 
 #if 0 /* No client authentication (for now) and not authenticating after each transaction.  */
@@ -1497,16 +1499,17 @@ mok_sign_file (std::string &mok_fingerprint,
               const std::string &name,
               std::string stapstderr)
 {
-  vector<string> cmd;
   int rc;
   string mok_directory = mok_path + "/" + mok_fingerprint;
 
-  cmd.clear();
-  cmd.push_back (kernel_build_tree + "/scripts/sign-file");
-  cmd.push_back ("sha512");
-  cmd.push_back (mok_directory + MOK_PRIVATE_CERT_FILE);
-  cmd.push_back (mok_directory + MOK_PUBLIC_CERT_FILE);
-  cmd.push_back (name);
+  vector<string> cmd
+    {
+      kernel_build_tree + "/scripts/sign-file",
+      "sha512",
+      mok_directory + MOK_PRIVATE_CERT_FILE,
+      mok_directory + MOK_PUBLIC_CERT_FILE,
+      name
+    };
 
   rc = stap_system (0, cmd);
   if (rc != 0) 
@@ -1527,23 +1530,22 @@ mok_sign_file (std::string &mok_fingerprint,
 static void
 filter_response_file (const string &file_name, const string &responseDirName)
 {
-  vector<string> cmd;
+  // Filter the server's home directory name (unless it is "/")
+  string dir = get_home_directory();
+  if (dir != "/")
+    {
+      string swap = string ("s,") + get_home_directory () + ",<server>,g";
+      vector<string> cmd { "sed", "-i", swap, file_name };
+      (void) stap_system (0, cmd);
+    }
 
-  // Filter the server's home directory name
-  cmd.clear();
-  cmd.push_back ("sed");
-  cmd.push_back ("-i");
-  cmd.push_back (string ("s,") + get_home_directory () + ",<server>,g");
-  cmd.push_back (file_name);
-  (void) stap_system (0, cmd);
-
-  // Filter the server's response directory name
-  cmd.clear();
-  cmd.push_back ("sed");
-  cmd.push_back ("-i");
-  cmd.push_back (string ("s,") + responseDirName + ",<server>,g");
-  cmd.push_back (file_name);
-  (void) stap_system (0, cmd);
+  // Filter the server's response directory name (unless it is "/")
+  if (responseDirName != "/")
+    {
+      string swap = string ("s,") + responseDirName + ",<server>,g";
+      vector<string> cmd = { "sed", "-i", swap, file_name };
+      (void) stap_system (0, cmd);
+    }
 }
 
 static privilege_t
@@ -1613,6 +1615,7 @@ generate_mok(string &mok_fingerprint)
   char tmpdir[PATH_MAX] = { '\0' };
   string public_cert_path, private_cert_path, destdir;
   mode_t old_umask;
+  int retlen;
 
   mok_fingerprint.clear ();
 
@@ -1637,7 +1640,14 @@ generate_mok(string &mok_fingerprint)
     }
 
   // Make a temporary directory to store results in.
-  snprintf (tmpdir, PATH_MAX, "%s/stap-server.XXXXXX", mok_path.c_str ());
+  retlen = snprintf (tmpdir, PATH_MAX, "%s/stap-server.XXXXXX", mok_path.c_str ());
+  if (retlen < 0 || retlen >= PATH_MAX)
+    {
+      server_error (_F("Could not create %s name", "temporary directory"));
+      tmpdir[0] = '\0';
+      goto cleanup;
+    }
+
   if (mkdtemp (tmpdir) == NULL)
     {
       server_error (_F("Could not create temporary directory %s: %s", tmpdir, 
@@ -1649,24 +1659,16 @@ generate_mok(string &mok_fingerprint)
   // Actually generate key using openssl.
   public_cert_path = tmpdir + string (MOK_PUBLIC_CERT_FILE);
   private_cert_path = tmpdir + string (MOK_PRIVATE_CERT_FILE);
-  cmd.push_back ("openssl");
-  cmd.push_back ("req");
-  cmd.push_back ("-new");
-  cmd.push_back ("-nodes");
-  cmd.push_back ("-utf8");
-  cmd.push_back ("-sha256");
-  cmd.push_back ("-days");
-  cmd.push_back ("36500");
-  cmd.push_back ("-batch");
-  cmd.push_back ("-x509");
-  cmd.push_back ("-config");
-  cmd.push_back (config_path);
-  cmd.push_back ("-outform");
-  cmd.push_back ("DER");
-  cmd.push_back ("-out");
-  cmd.push_back (public_cert_path);
-  cmd.push_back ("-keyout");
-  cmd.push_back (private_cert_path);
+
+  cmd =
+    {
+      "openssl", "req", "-new", "-nodes", "-utf8",
+      "-sha256", "-days", "36500", "-batch", "-x509",
+      "-config", config_path,
+      "-outform", "DER",
+      "-out", public_cert_path,
+      "-keyout", private_cert_path
+    };
   rc = stap_system (0, cmd);
   if (rc != 0) 
     {
@@ -1695,10 +1697,7 @@ generate_mok(string &mok_fingerprint)
 
 cleanup:
   // Remove the temporary directory.
-  cmd.clear ();
-  cmd.push_back ("rm");
-  cmd.push_back ("-rf");
-  cmd.push_back (tmpdir);
+  cmd = { "rm", "-rf", tmpdir };
   rc = stap_system (0, cmd);
   if (rc != 0)
     server_error (_("Error in tmpdir cleanup"));
@@ -1721,6 +1720,7 @@ handleRequest (const string &requestDirName, const string &responseDirName, stri
   unsigned u;
   unsigned i;
   FILE* f;
+  int retlen;
 
   // Save the server version. Do this early, so the client knows what version of the server
   // it is dealing with, even if the request is not fully completed.
@@ -1743,6 +1743,29 @@ handleRequest (const string &requestDirName, const string &responseDirName, stri
   // The name of the translator executable.
   stapargv.push_back ((char *)(getenv ("SYSTEMTAP_STAP") ?: STAP_PREFIX "/bin/stap"));
 
+  // Fetch the target kernel version from request and pass flag to stap
+  string kernel_version;
+  filename = requestDirName + "/sysinfo";
+  ifstream versionfile(filename.c_str());
+  if (versionfile >> kernel_version >> kernel_version) // Skip sysinfo: label
+    {
+      if (kernel_build_tree.find(kernel_version) != kernel_build_tree.end())
+        {
+          stapargv.push_back("-r" + kernel_version);
+        }
+      else
+        {
+          log(_F("Target kernel version %s is not supported by this server",
+              kernel_version.c_str()));
+          return;
+        }
+    }
+  else
+    {
+      server_error(_("Unable to read sysinfo"));
+      return;
+    }
+
   /* Transcribe stap_options.  We use plain wordexp(3), since these
      options are coming from the local trusted user, so malicious
      content is not a concern. */
@@ -1776,7 +1799,12 @@ handleRequest (const string &requestDirName, const string &responseDirName, stri
       struct stat st;
       char *arg;
 
-      snprintf (stapargfile, PATH_MAX, "%s/argv%d", requestDirName.c_str (), i);
+      retlen = snprintf (stapargfile, PATH_MAX, "%s/argv%d", requestDirName.c_str (), i);
+      if (retlen < 0 || retlen >= PATH_MAX)
+        {
+          server_error (_F("Error creating %s name", "path"));
+          return;
+        }
 
       rc = stat(stapargfile, & st);
       if (rc) break;
@@ -1882,12 +1910,23 @@ handleRequest (const string &requestDirName, const string &responseDirName, stri
     {
       glob_t globber;
       char pattern[PATH_MAX];
-      snprintf (pattern, PATH_MAX, "%s/*.ko", new_staptmpdir.c_str());
+      int retlen;
+
+      retlen = snprintf (pattern, PATH_MAX, "%s/*.ko", new_staptmpdir.c_str());
+      if (retlen < 0 || retlen >= PATH_MAX)
+        {
+          server_error (_F("Error creating %s name", "pattern"));
+          return;
+        }
+
       rc = glob (pattern, GLOB_ERR, NULL, &globber);
       if (rc)
         server_error (_F("Unable to find a module in %s", new_staptmpdir.c_str()));
       else if (globber.gl_pathc != 1)
-        server_error (_F("Too many modules (%zu) in %s", globber.gl_pathc, new_staptmpdir.c_str()));
+        {
+         server_error (_F("Too many modules (%zu) in %s", globber.gl_pathc, new_staptmpdir.c_str()));
+         globfree(&globber);
+       }
       else
         {
          if (pr_contains (privilege, pr_stapusr)
@@ -1900,7 +1939,7 @@ handleRequest (const string &requestDirName, const string &responseDirName, stri
              // If we signing the module failed, change the staprc to
              // 1, so that the client won't try to run the resulting
              // module, which wouldn't work.
-             if (! mok_sign_file (mok_fingerprint, kernel_build_tree,
+             if (! mok_sign_file (mok_fingerprint, kernel_build_tree[kernel_version],
                                   globber.gl_pathv[0], stapstderr))
                staprc = 1;
            }
@@ -1951,6 +1990,7 @@ handleRequest (const string &requestDirName, const string &responseDirName, stri
              // resulting module, which wouldn't work.
              staprc = 1;
          }
+         globfree(&globber);
         }
     }
 
@@ -1995,7 +2035,7 @@ handleRequest (const string &requestDirName, const string &responseDirName, stri
       // requires signed modules. The error will have been generated
       // above on the systemtap module itself.
       if (! mok_fingerprint.empty ())
-       mok_sign_file (mok_fingerprint, kernel_build_tree, uprobes_response,
+       mok_sign_file (mok_fingerprint, kernel_build_tree[kernel_version], uprobes_response,
                       stapstderr);
     }
 
@@ -2094,25 +2134,20 @@ spawn_and_wait (const vector<string> &argv, int *spawnrc,
 }
 
 /* Given the path to the compressed request file, return 0 if the size of the
- * uncompressed request is within the determined limits. */
+ * uncompressed request is within the determined limit. */
 int
 check_uncompressed_request_size (const char * zip_file)
 {
-  vector<string> args;
   ostringstream result;
 
-  // Check the uncompressed file size.
-  args.push_back("unzip");
-  args.push_back("-Zt");
-  args.push_back(zip_file);
-
+  // Generate the command to heck the uncompressed size
+  vector<string> args { "unzip", "-Zt", zip_file };
   int rc = stap_system_read (0, args, result);
   if (rc != 0)
     {
     server_error (_F("Unable to check the zipefile size. Error code: %d .", rc));
     return rc;
     }
-  log (_F("Result of the unzip -Zt call is:\n%s", result.str().c_str()));
 
   // Parse the result from the unzip call, looking for the third token
   vector<string> toks;
@@ -2159,6 +2194,7 @@ handle_connection (void *arg)
                         copy for each connection.*/
   vector<string>     argv;
   PRInt32            bytesRead;
+  int               retlen;
 
   /* Detatch to avoid a memory leak */
   if(max_threads > 0)
@@ -2208,7 +2244,13 @@ handle_connection (void *arg)
 #endif
 
   secStatus = SECFailure;
-  snprintf(tmpdir, PATH_MAX, "%s/stap-server.XXXXXX", getenv("TMPDIR") ?: "/tmp");
+  retlen = snprintf(tmpdir, PATH_MAX, "%s/stap-server.XXXXXX", getenv("TMPDIR") ?: "/tmp");
+  if (retlen < 0 || retlen >= PATH_MAX)
+    {
+      server_error (_F("Error creating %s name", "temporary directory"));
+      tmpdir[0]=0; /* prevent /bin/rm */
+      goto cleanup;
+    }
   rc1 = mkdtemp(tmpdir);
   if (! rc1)
     {
@@ -2218,9 +2260,20 @@ handle_connection (void *arg)
     }
 
   /* Create a temporary files names and directories.  */
-  snprintf (requestFileName, PATH_MAX, "%s/request.zip", tmpdir);
+  retlen = snprintf (requestFileName, PATH_MAX, "%s/request.zip", tmpdir);
+  if (retlen < 0 || retlen >= PATH_MAX)
+    {
+      server_error (_F("Error creating %s name", "request.zip path"));
+      goto cleanup;
+    }
+
+  retlen = snprintf (requestDirName, PATH_MAX, "%s/request", tmpdir);
+  if (retlen < 0 || retlen >= PATH_MAX)
+    {
+      server_error (_F("Error creating %s name", "request directory path"));
+      goto cleanup;
+    }
 
-  snprintf (requestDirName, PATH_MAX, "%s/request", tmpdir);
   rc = mkdir(requestDirName, 0700);
   if (rc)
     {
@@ -2228,7 +2281,13 @@ handle_connection (void *arg)
       goto cleanup;
     }
 
-  snprintf (responseDirName, PATH_MAX, "%s/response", tmpdir);
+  retlen = snprintf (responseDirName, PATH_MAX, "%s/response", tmpdir);
+  if (retlen < 0 || retlen >= PATH_MAX)
+    {
+      server_error (_F("Error creating %s name", "response directory path"));
+      goto cleanup;
+    }
+
   rc = mkdir(responseDirName, 0700);
   if (rc)
     {
@@ -2238,7 +2297,12 @@ handle_connection (void *arg)
   // Set this early, since it gets used for errors to be returned to the client.
   stapstderr = string(responseDirName) + "/stderr";
 
-  snprintf (responseFileName, PATH_MAX, "%s/response.zip", tmpdir);
+  retlen = snprintf (responseFileName, PATH_MAX, "%s/response.zip", tmpdir);
+  if (retlen < 0 || retlen >= PATH_MAX)
+    {
+      server_error (_F("Error creating %s name", "response.zip path"));
+      goto cleanup;
+    }
 
   /* Read data from the socket.
    * If the user is requesting/requiring authentication, authenticate
@@ -2270,11 +2334,7 @@ handle_connection (void *arg)
 
   /* Unzip the request. */
   secStatus = SECFailure;
-  argv.push_back ("unzip");
-  argv.push_back ("-q");
-  argv.push_back ("-d");
-  argv.push_back (requestDirName);
-  argv.push_back (requestFileName);
+  argv = { "unzip", "-q", "-d", requestDirName, requestFileName };
   rc = stap_system (0, argv);
   if (rc != 0)
     {
@@ -2289,12 +2349,7 @@ handle_connection (void *arg)
 
   /* Zip the response. */
   int ziprc;
-  argv.clear ();
-  argv.push_back ("zip");
-  argv.push_back ("-q");
-  argv.push_back ("-r");
-  argv.push_back (responseFileName);
-  argv.push_back (".");
+  argv = { "zip", "-q", "-r", responseFileName, "." };
   rc = spawn_and_wait (argv, &ziprc, NULL, NULL, NULL, responseDirName);
   if (rc != PR_SUCCESS || ziprc != 0)
     {
@@ -2319,10 +2374,7 @@ cleanup:
        log (_F("Keeping temporary directory %s", tmpdir));
       else
        {
-         argv.clear ();
-         argv.push_back ("rm");
-         argv.push_back ("-r");
-         argv.push_back (tmpdir);
+         argv = { "rm", "-r", tmpdir };
          rc = stap_system (0, argv);
          if (rc != 0)
            server_error (_("Error in tmpdir cleanup"));
@@ -2343,6 +2395,9 @@ cleanup:
        log (_F("Request from [%s]:%d complete", buf, addr.ipv6.port));
     }
 
+  if (privKey)
+    SECKEY_DestroyPrivateKey (privKey); /* Destroy our copy of the private key. */
+  
   /* Increment semephore to indicate this thread is finished. */
   free(t_arg);
   if (max_threads > 0)
@@ -2434,14 +2489,16 @@ accept_connections (PRFileDesc *listenSocket, CERTCertificate *cert)
         fatal(_("No memory available for new thread arg!"));
       t_arg->tcpSocket = tcpSocket;
       t_arg->cert = cert;
-      t_arg->privKey = privKey;
+      t_arg->privKey = SECKEY_CopyPrivateKey(privKey); /* pass by value */
       t_arg->addr = addr;
 
       /* Handle the conncection */
+      int thread_rc = -1;
       if (max_threads > 0)
         /* Create the worker thread and handle the connection. */
-        pthread_create(&tid, NULL, handle_connection, t_arg);
-      else
+        thread_rc = pthread_create(&tid, NULL, handle_connection, t_arg);
+
+      if (thread_rc != 0)
         /* Since max_threads == 0, don't spawn a new thread,
          * just handle in the current thread. */
         handle_connection(t_arg);
@@ -2451,12 +2508,13 @@ accept_connections (PRFileDesc *listenSocket, CERTCertificate *cert)
                                      certUsageSSLServer, NULL/*wincx*/);
       if (secStatus != SECSuccess)
        {
-         // Not an error. Exit the loop so a new cert can be generated.
+         // Not a serious error. Exit the loop so a new cert can be generated.
+          nssError ();
          break;
        }
     }
 
-  SECKEY_DestroyPrivateKey (privKey);
+  SECKEY_DestroyPrivateKey (privKey); /* Safe to destroy, even if thread still running. */
   return SECSuccess;
 }
 
@@ -2690,13 +2748,14 @@ listen ()
       if (check_cert (cert_db_path, server_cert_nickname (), use_db_password) != 0)
        {
          // Message already issued
-         goto done;
+          server_error (_("Cannot check/create certificate, giving up."));
+          goto done;
        }
 
       // Ensure that our certificate is trusted by our local client.
       // Construct the client database path relative to the server database path.
       SECStatus secStatus = add_client_cert (server_cert_file (),
-                                            local_client_cert_db_path ());
+                                            local_client_cert_db_path (), true);
       if (secStatus != SECSuccess)
        {
          // Not fatal. Other clients may trust the server and trust can be added
This page took 0.043815 seconds and 5 git commands to generate.