Workaround for OpenCL runtimes which do accept -I parameter in the OpenCL kernel...
[hashcat.git] / src / hashcat.c
index 492e52d..c702d12 100644 (file)
@@ -6147,6 +6147,22 @@ int main (int argc, char **argv)
 
   umask (077);
 
+  /**
+   * There's some buggy OpenCL runtime that do not support -I.
+   * A workaround is to chdir() to the OpenCL folder,
+   * then compile the kernels,
+   * then chdir() back to where we came from so we need to save it first
+   */
+
+  char cwd[1024];
+
+  if (getcwd (cwd, sizeof (cwd) - 1) == NULL)
+  {
+    log_error ("ERROR: getcwd(): %s", strerror (errno));
+
+    return -1;
+  }
+
   /**
    * Real init
    */
@@ -6547,6 +6563,65 @@ int main (int argc, char **argv)
 
   myfree (exec_path);
 
+  /**
+   * There's alot of problem related to bad support -I parameters when building the kernel.
+   * Each OpenCL runtime handles it slightly different.
+   * The most problematic is with new AMD drivers on Windows, which can not handle quote characters!
+   * The best workaround found so far is to modify the TMP variable (only inside hashcat process) before the runtime is load
+   */
+
+  char cpath[1024] = { 0 };
+
+  #if _WIN
+
+  snprintf (cpath, sizeof (cpath) - 1, "%s\\OpenCL\\", shared_dir);
+
+  char *cpath_real = mymalloc (MAX_PATH);
+
+  if (GetFullPathName (cpath, MAX_PATH, cpath_real, NULL) == 0)
+  {
+    log_error ("ERROR: %s: %s", cpath, "GetFullPathName()");
+
+    return -1;
+  }
+
+  #else
+
+  snprintf (cpath, sizeof (cpath) - 1, "%s/OpenCL/", shared_dir);
+
+  char *cpath_real = mymalloc (PATH_MAX);
+
+  if (realpath (cpath, cpath_real) == NULL)
+  {
+    log_error ("ERROR: %s: %s", cpath, strerror (errno));
+
+    return -1;
+  }
+
+  #endif
+
+  if (getenv ("TMP") == NULL)
+  {
+    char tmp[1000];
+
+    snprintf (tmp, sizeof (tmp) - 1, "TMP=%s", cpath_real);
+
+    putenv (tmp);
+  }
+
+  #if _WIN
+
+  naive_replace (cpath_real, '\\', '/');
+
+  // not escaping here, windows using quotes later
+  // naive_escape (cpath_real, PATH_MAX,  ' ', '\\');
+
+  #else
+
+  naive_escape (cpath_real, PATH_MAX,  ' ', '\\');
+
+  #endif
+
   /**
    * kernel cache, we need to make sure folder exist
    */
@@ -14095,9 +14170,13 @@ int main (int argc, char **argv)
 
         if (CL_err != CL_SUCCESS)
         {
-          log_error ("ERROR: clGetDeviceIDs(): %s\n", val2cstr_cl (CL_err));
+          //log_error ("ERROR: clGetDeviceIDs(): %s\n", val2cstr_cl (CL_err));
 
-          return -1;
+          //return -1;
+
+          // Silently ignore at this point, it will be reused later and create a note for the user at that point
+
+          continue;
         }
 
         for (uint platform_devices_id = 0; platform_devices_id < platform_devices_cnt; platform_devices_id++)
@@ -14161,15 +14240,6 @@ int main (int argc, char **argv)
 
       cl_platform_id platform = platforms[platform_id];
 
-      CL_err = hc_clGetDeviceIDs (data.ocl, platform, CL_DEVICE_TYPE_ALL, DEVICES_MAX, platform_devices, &platform_devices_cnt);
-
-      if (CL_err != CL_SUCCESS)
-      {
-        log_error ("ERROR: clGetDeviceIDs(): %s\n", val2cstr_cl (CL_err));
-
-        return -1;
-      }
-
       char platform_vendor[INFOSZ] = { 0 };
 
       CL_err = hc_clGetPlatformInfo (data.ocl, platform, CL_PLATFORM_VENDOR, sizeof (platform_vendor), platform_vendor, NULL);
@@ -14224,7 +14294,18 @@ int main (int argc, char **argv)
         platform_vendor_id = VENDOR_ID_GENERIC;
       }
 
-      const uint platform_skipped = ((opencl_platforms_filter & (1 << platform_id)) == 0);
+      uint platform_skipped = ((opencl_platforms_filter & (1 << platform_id)) == 0);
+
+      CL_err = hc_clGetDeviceIDs (data.ocl, platform, CL_DEVICE_TYPE_ALL, DEVICES_MAX, platform_devices, &platform_devices_cnt);
+
+      if (CL_err != CL_SUCCESS)
+      {
+        //log_error ("ERROR: clGetDeviceIDs(): %s\n", val2cstr_cl (CL_err));
+
+        //return -1;
+
+        platform_skipped = 2;
+      }
 
       if ((benchmark == 1 || quiet == 0) && (algorithm_pos == 0))
       {
@@ -14240,15 +14321,21 @@ int main (int argc, char **argv)
 
             log_info (line);
           }
-          else
+          else if (platform_skipped == 1)
           {
             log_info ("OpenCL Platform #%u: %s, skipped", platform_id + 1, platform_vendor);
             log_info ("");
           }
+          else if (platform_skipped == 2)
+          {
+            log_info ("OpenCL Platform #%u: %s, skipped! No OpenCL compatible devices found", platform_id + 1, platform_vendor);
+            log_info ("");
+          }
         }
       }
 
       if (platform_skipped == 1) continue;
+      if (platform_skipped == 2) continue;
 
       for (uint platform_devices_id = 0; platform_devices_id < platform_devices_cnt; platform_devices_id++)
       {
@@ -16062,46 +16149,19 @@ int main (int argc, char **argv)
        * default building options
        */
 
-      char cpath[1024] = { 0 };
-
-      char build_opts[1024] = { 0 };
-
-      #if _WIN
-
-      snprintf (cpath, sizeof (cpath) - 1, "%s\\OpenCL\\", shared_dir);
-
-      char *cpath_real = mymalloc (MAX_PATH);
-
-      if (GetFullPathName (cpath, MAX_PATH, cpath_real, NULL) == 0)
+      if (chdir (cpath_real) == -1)
       {
-        log_error ("ERROR: %s: %s", cpath, "GetFullPathName()");
+        log_error ("ERROR: %s: %s", cpath_real, strerror (errno));
 
         return -1;
       }
 
-      naive_replace (cpath_real, '\\', '/');
-
-      // not escaping here, windows has quotes
+      char build_opts[1024] = { 0 };
 
+      #if _WIN
       snprintf (build_opts, sizeof (build_opts) - 1, "-I \"%s\"", cpath_real);
-
       #else
-
-      snprintf (cpath, sizeof (cpath) - 1, "%s/OpenCL/", shared_dir);
-
-      char *cpath_real = mymalloc (PATH_MAX);
-
-      if (realpath (cpath, cpath_real) == NULL)
-      {
-        log_error ("ERROR: %s: %s", cpath, strerror (errno));
-
-        return -1;
-      }
-
-      naive_escape (cpath_real, PATH_MAX,  ' ', '\\');
-
       snprintf (build_opts, sizeof (build_opts) - 1, "-I %s", cpath_real);
-
       #endif
 
       // include check
@@ -16131,15 +16191,11 @@ int main (int argc, char **argv)
 
       for (int i = 0; i < files_cnt; i++)
       {
-        char path[1024] = { 0 };
-
-        snprintf (path, sizeof (path) - 1, "%s/%s", cpath_real, files_names[i]);
-
-        FILE *fd = fopen (path, "r");
+        FILE *fd = fopen (files_names[i], "r");
 
         if (fd == NULL)
         {
-          log_error ("ERROR: %s: fopen(): %s", path, strerror (errno));
+          log_error ("ERROR: %s: fopen(): %s", files_names[i], strerror (errno));
 
           return -1;
         }
@@ -16150,7 +16206,7 @@ int main (int argc, char **argv)
 
         if (n != 1)
         {
-          log_error ("ERROR: %s: fread(): %s", path, strerror (errno));
+          log_error ("ERROR: %s: fread(): %s", files_names[i], strerror (errno));
 
           return -1;
         }
@@ -16158,8 +16214,6 @@ int main (int argc, char **argv)
         fclose (fd);
       }
 
-      myfree (cpath_real);
-
       // we don't have sm_* on vendors not NV but it doesn't matter
 
       char build_opts_new[1024] = { 0 };
@@ -16707,6 +16761,15 @@ int main (int argc, char **argv)
         local_free (kernel_sources);
       }
 
+      // return back to the folder we came from initially (workaround)
+
+      if (chdir (cwd) == -1)
+      {
+        log_error ("ERROR: %s: %s", cwd, strerror (errno));
+
+        return -1;
+      }
+
       // some algorithm collide too fast, make that impossible
 
       if (benchmark == 1)