Hello,

I am uploading a 0-day NMU for this bug based on Anthony's patch, after
review.  The full changeset for the NMU is attached.

Thanks,
-- 
Steve Langasek
postmodern programmer
diff -u imms-2.0.1/debian/changelog imms-2.0.1/debian/changelog
--- imms-2.0.1/debian/changelog
+++ imms-2.0.1/debian/changelog
@@ -1,3 +1,14 @@
+imms (2.0.1-3.1) unstable; urgency=high
+
+  * Non-maintainer upload.
+  * High-urgency upload for sarge-targetted RC bugfix
+  * Use pipe() and execlp() directly instead of popen() when calling
+    sox, to avoid arbitrary command execution attacks when acting on
+    files with untrusted names downloaded from the network.
+    Closes: #292777.
+
+ -- Steve Langasek <[EMAIL PROTECTED]>  Sat,  5 Feb 2005 04:58:12 -0800
+
 imms (2.0.1-3) unstable; urgency=low
 
   * Applied patch from Andreas Jochens to fix a build problem on 64 bit
only in patch2:
unchanged:
--- imms-2.0.1.orig/analyzer/analyzer.cc
+++ imms-2.0.1/analyzer/analyzer.cc
@@ -1,5 +1,7 @@
-#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <unistd.h>
+#include <stdio.h>
 #include <iostream>
 #include <string>
 #include <fstream>
@@ -44,17 +46,53 @@
         return -4;
     }
 
-    ostringstream command;
-    command << "nice -n 15 sox \"" << path << "\" -t .raw -w -u -c 1 -r "
-        << SAMPLERATE << " -";
-#ifdef DEBUG
-    cout << "analyzer: Executing: " << command.str() << endl;
-#endif
-    FILE *p = popen(command.str().c_str(), "r");
+       // Do a popen the long way to avoid the shell.
+       int p_fds[2];
+       if (-1 == pipe(p_fds))
+       {
+               cerr << "analyzer: Could not open pipe: " << strerror(errno)
+                    << endl;
+               return -2;
+       }
+       
+       int child_pid = fork();
+       if (child_pid == -1)
+       {
+               cerr << "analyzer: Could not fork: " << strerror(errno) << endl;
+               return -2;
+       } 
+       else if (child_pid == 0)
+       {
+               ostringstream sample_rate;
+               sample_rate << SAMPLERATE;
+
+               if (-1 == dup2(p_fds[1], STDOUT_FILENO))
+               {
+                       cerr << "analyzer: Could not dup2: " << strerror(errno) 
<< endl;
+                       return -2;
+               }
+               if (-1 == nice(15))
+               {
+                       cerr << "analyzer: could not renice: " << 
strerror(errno) << endl;
+                       return -2;
+               }
+               if (-1 == execlp("sox", "sox", path.c_str(), "-t", ".raw", "-w",
+                                            "-u", "-c", "1", "-r", 
sample_rate.str().c_str(),
+                                            "-", (char*)NULL))
+               {
+                   cerr << "could not exec sox: " << strerror(errno) << endl;
+                   return -2;
+               }
+       } 
+       
+       // The child performed an exec above, so we only get here if we're
+       // the parent.
+       close(p_fds[1]); // otherwise, read wont fail.
+       FILE *p = fdopen(p_fds[0], "r");
 
     if (!p)
     {
-        cerr << "analyzer: Could not open pipe!" << endl;
+        cerr << "analyzer: Could not fdopen pipe!" << endl;
         return -2;
     }
 
@@ -77,10 +115,7 @@
         SpectrumAnalyzer analyzer(path);
 
         if (analyzer.is_known())
-        {
-            cout << "analyzer: Already analyzed - skipping." << endl;
-            return 1;
-        }
+            throw std::string("analyzer: Already analyzed - skipping.");
 
         while (fread(indata + OVERLAP, sizeof(sample_t), READSIZE, p)
                 == READSIZE)
@@ -106,7 +141,22 @@
     }
     catch (std::string &s) { cerr << s << endl; }
 
-    pclose(p);
+       fclose(p);
+       kill(child_pid, SIGKILL); // make sure
+       int sox_status;
+       if (-1 == waitpid(child_pid, &sox_status, 0))
+               cerr << "WARNING: waitpid failed: " << strerror(errno) << endl;
+
+       if (WIFEXITED(sox_status) && 0 != WEXITSTATUS(sox_status))
+       {
+               cerr << "WARNING: sox exited with unclean status "
+                    << WEXITSTATUS(sox_status) << ".\n";
+       }
+       else if (WIFSIGNALED(sox_status) && SIGKILL != WTERMSIG(sox_status))
+       {
+               cerr << "WARNING: sox exited on signal " << WTERMSIG(sox_status)
+                    << ".\n";
+       }
 
     return 0;
 }

Attachment: signature.asc
Description: Digital signature

Reply via email to