Hi, uploading a 0-day NMU to fix this bug. debdiff is attached and will be also archived on: http://people.debian.org/~nion/nmu-diff/comix-3.6.4-1_3.6.4-1.1.patch
Kind regards Nico -- Nico Golde - http://www.ngolde.de - [EMAIL PROTECTED] - GPG: 0x73647CFF For security reasons, all text in this mail is double-rot13 encrypted.
diff -u comix-3.6.4/debian/changelog comix-3.6.4/debian/changelog
--- comix-3.6.4/debian/changelog
+++ comix-3.6.4/debian/changelog
@@ -1,3 +1,15 @@
+comix (3.6.4-1.1) unstable; urgency=high
+
+ * Non-maintainer upload by the Security Team.
+ * Apply patch by Mamoru Tasaka to fix arbitrary code execution
+ via crafted file names because of passing the filename directly
+ to string concatenation used in os.popen (CVE-2008-1568; Closes: #462840).
+ * Apply patch by Mamoru Tasaka to use empfile.mkdtemp() to enable comix
+ for multi-user environments and thus prevent a race condition in /tmp
+ without a real security impact (Closes: #462836).
+
+ -- Nico Golde <[EMAIL PROTECTED]> Thu, 03 Apr 2008 00:49:49 +0200
+
comix (3.6.4-1) unstable; urgency=low
* New upstream release
only in patch2:
unchanged:
--- comix-3.6.4.orig/mime/comicthumb
+++ comix-3.6.4/mime/comicthumb
@@ -22,6 +22,10 @@
import StringIO
import re
import shutil
+
+import subprocess
+import tempfile
+
try:
import Image
except:
@@ -48,9 +52,13 @@
sys.exit(1)
# temp directory needed for multiple archives
-if not os.path.exists('/tmp/comicthumb/'):
- os.makedirs('/tmp/comicthumb/')
- os.chmod('/tmp/comicthumb/', 0700)
+#if not os.path.exists('/tmp/comicthumb/'):
+# os.makedirs('/tmp/comicthumb/')
+# os.chmod('/tmp/comicthumb/', 0700)
+_tmp_dir = tempfile.mkdtemp(prefix='comixthumb', suffix=os.sep,
+ dir = '/tmp')
+_tmp_dir += "/"
+
# return the first image in the list
def first_image (filelist):
@@ -101,10 +109,10 @@
else:
subarchive = first_archive(zipfiles)
if subarchive:
- output = open("/tmp/comicthumb/archive%d" % (depth), "wb")
+ output = open( _tmp_dir + "archive%d" % (depth), "wb")
output.write(zip.read(subarchive))
output.close()
- return get_image("/tmp/comicthumb/archive%d" % (depth),
+ return get_image( _tmp_dir + "archive%d" % (depth),
depth + 1)
elif tarfile.is_tarfile(compressed_file):
TYPE = TYPE or 'cbt'
@@ -119,10 +127,10 @@
else:
subarchive = first_archive(tarfiles)
if subarchive:
- output = open("/tmp/comicthumb/archive%d" % (depth), "wb")
+ output = open( _tmp_dir + "archive%d" % (depth), "wb")
output.write(tar.extractfile(subarchive).read())
output.close()
- return get_image("/tmp/comicthumb/archive%d" % (depth),
+ return get_image( _tmp_dir + "archive%d" % (depth),
depth + 1)
elif open(compressed_file, 'rb').read(4) == 'Rar!':
TYPE = TYPE or 'cbr'
@@ -138,20 +146,36 @@
if not rar:
print "You must install unrar or rar to thumbnail RAR archives."
sys.exit(1)
- rarfiles = os.popen('%s vb "%s"' % (rar, compressed_file)).readlines()
+ #rarfiles = os.popen('%s vb "%s"' % (rar, compressed_file)).readlines()
+ rarfiles = subprocess.Popen([rar, 'vb', compressed_file],
+ stdout=subprocess.PIPE).communicate()[0].splitlines()
for i in range(len(rarfiles)):
rarfiles[i] = rarfiles[i].rstrip("\n")
rarfiles.sort()
cover = guessCover(rarfiles)
if cover:
- picture = StringIO.StringIO(os.popen('%s p -inul -- "%s" "%s"'
- % (rar, compressed_file, cover), "r").read())
+ #picture = StringIO.StringIO(os.popen('%s p -inul -- "%s" "%s"'
+ #% (rar, compressed_file, cover), "r").read())
+ picture = StringIO.StringIO(subprocess.Popen(
+ [rar, 'p', '-inul', '--', compressed_file, cover],
+ stdout=subprocess.PIPE).stdout.read())
else:
subarchive = first_archive(rarfiles)
if subarchive:
- os.popen('%s p -inul -- "%s" "%s" > "/tmp/comicthumb/archive%d"'
- % (rar, compressed_file, subarchive, depth), "r")
- return get_image("/tmp/comicthumb/archive%d" % (depth),
+ #os.popen('%s p -inul -- "%s" "%s" > "/tmp/comicthumb/archive%d"'
+ #% (rar, compressed_file, subarchive, depth), "r")
+ filen = _tmp_dir + "archive%d"%(depth)
+ try:
+ os.remove(filen)
+ except:
+ pass
+ fp = open(filen, 'w')
+ fdp = fp.fileno()
+ subprocess.Popen(
+ [rar, 'p', '-inul', '--', compressed_file, subarchive],
+ stdout = fdp).wait()
+ fp.close()
+ return get_image( _tmp_dir + "archive%d" % (depth),
depth + 1)
return picture
@@ -207,8 +231,8 @@
exit_flag = 1
# remove tempory stuff
-if os.path.isdir('/tmp/comicthumb/'):
- shutil.rmtree('/tmp/comicthumb/')
+if os.path.isdir(_tmp_dir):
+ shutil.rmtree(_tmp_dir)
# and exit
sys.exit(exit_flag)
only in patch2:
unchanged:
--- comix-3.6.4.orig/comix
+++ comix-3.6.4/comix
@@ -44,6 +44,11 @@
import pwd
import cPickle
+import subprocess
+import string
+
+import tempfile
+
try:
import pygtk
pygtk.require('2.0')
@@ -254,6 +259,8 @@
window_height = 0
colour_adjust_signal_kill = False
colour_adjust_dialog_displayed = False
+
+ _tmp_dir = None
def close_application(self, widget, event=None):
@@ -267,8 +274,8 @@
self.prefs['page of last file'] = self.file_number
if os.path.exists(self.base_dir):
shutil.rmtree(self.base_dir)
- if len(os.listdir('/tmp/comix')) == 0:
- shutil.rmtree('/tmp/comix')
+ if len(os.listdir(self._tmp_dir)) == 0:
+ shutil.rmtree(self._tmp_dir)
self.exit = True
# =======================================================
@@ -366,9 +373,9 @@
# =======================================================
if os.path.exists(self.base_dir):
shutil.rmtree(self.base_dir)
- if os.path.isdir('/tmp/comix'):
- if len(os.listdir('/tmp/comix')) == 0:
- shutil.rmtree('/tmp/comix')
+ if os.path.isdir(self._tmp_dir):
+ if len(os.listdir(self._tmp_dir)) == 0:
+ shutil.rmtree(self._tmp_dir)
# =======================================================
@@ -6277,9 +6284,12 @@
archive = tarfile.open(path, 'r')
files = archive.getnames()
elif type == 'rar':
+ #files = \
+ #os.popen(self.rar + ' vb "' + path +
+ #'"').readlines()
files = \
- os.popen(self.rar + ' vb "' + path +
- '"').readlines()
+ subprocess.Popen([self.rar, 'vb', path],
+ stdout=subprocess.PIPE).communicate()[0].splitlines()
files = [file.rstrip('\n') for file in files]
cover = None
files.sort()
@@ -6302,9 +6312,20 @@
break
if cover != None:
if type == 'rar':
- os.popen(self.rar + ' p -inul -- "' + path + '" "' +
- cover + '" > "' + thumb_dir +
- '/temp" 2>/dev/null', "r").close()
+ #os.popen(self.rar + ' p -inul -- "' + path + '" "' +
+ #cover + '" > "' + thumb_dir +
+ #'/temp" 2>/dev/null', "r").close()
+ filen = thumb_dir + '/temp'
+ try:
+ os.remove(filen)
+ except:
+ pass
+ fp = open(filen, 'w')
+ fdp = fp.fileno()
+ p = subprocess.Popen(
+ [self.rar, 'p', '-inul', '--', path,
+ cover ], stdout = fdp).wait()
+ fp.close()
image = Image.open(thumb_dir + '/temp')
os.remove(thumb_dir + '/temp')
elif type == 'zip':
@@ -8010,7 +8031,7 @@
return False
# We don't want to open files from our selves.
- if selection.data.startswith('file:///tmp/comix/'):
+ if selection.data.startswith('file://' + self._tmp_dir):
return
uri = selection.data.strip()
@@ -8733,8 +8754,10 @@
# =======================================================
elif archive_type == 'rar':
if self.rar:
- os.popen(
- self.rar + ' x "' + src_path + '" "' + dst_path + '"')
+ #os.popen(
+ #self.rar + ' x "' + src_path + '" "' + dst_path + '"')
+ subprocess.Popen(
+ [self.rar, 'x', src_path, dst_path],stdout=sys.stdout).wait()
else:
self.statusbar.push(0,
_('Could not find the unrar executable. Please install it if you wish to open RAR archives.'))
@@ -9168,9 +9191,37 @@
self.are_you_sure_dialog.hide()
if response != -5:
return
- os.popen(self.jpegtran + ' -copy all -trim ' + operation +
- ' -outfile "' + self.file[self.file_number] + '" "' +
- self.file[self.file_number] + '"')
+ #os.popen(self.jpegtran + ' -copy all -trim ' + operation +
+ #' -outfile "' + self.file[self.file_number] + '" "' +
+ #self.file[self.file_number] + '"')
+ op = operation.split()
+ op_len = len(op)
+
+ i=1
+ filen = self.file[self.file_number]
+ while (1):
+ tmp_file = filen + '.tmp' + 'z' * i
+ if os.path.exists(tmp_file):
+ i += 1
+ else:
+ break
+
+ # Ugly hack :(
+ if op_len == 2:
+ p = subprocess.Popen(
+ [self.jpegtran, '-copy', 'all', '-trim', op[0], op[1],
+ '-outfile', tmp_file, filen],
+ stdin=sys.stdin, stdout=sys.stdout)
+ else:
+ p = subprocess.Popen(
+ [self.jpegtran, '-copy', 'all', '-trim', op[0],
+ '-outfile', tmp_file, filen],
+ stdin=sys.stdin, stdout=sys.stdout)
+ p.wait()
+ if p.returncode == 0:
+ shutil.copymode(filen, tmp_file)
+ shutil.copy(tmp_file, filen)
+ os.remove(tmp_file)
try:
uri = 'file://' + urllib.pathname2url(self.file[self.file_number])
thumb_path = md5.new()
@@ -10496,15 +10547,20 @@
# The dir is /tmp/comix/<num> where <num> is 1 or higher
# depending on the number of Comix sessions opened.
# =======================================================
- if not os.path.exists('/tmp/comix/'):
- os.makedirs('/tmp/comix/')
- os.chmod('/tmp/comix/', 0700)
+ #if not os.path.exists('/tmp/comix/'):
+ # os.makedirs('/tmp/comix/')
+ # os.chmod('/tmp/comix/', 0700)
+
+ self._tmp_dir = tempfile.mkdtemp(prefix='comix.', suffix=os.sep,
+ dir = '/tmp')
+ self._tmp_dir += "/"
+
dir_number = 1
while 1:
- if not os.path.exists('/tmp/comix/' + str(dir_number)):
- os.mkdir('/tmp/comix/' + str(dir_number))
- os.chmod('/tmp/comix/' + str(dir_number), 0700)
- self.base_dir = '/tmp/comix/' + str(dir_number) + '/'
+ if not os.path.exists(self._tmp_dir + str(dir_number)):
+ os.mkdir(self._tmp_dir + str(dir_number))
+ os.chmod(self._tmp_dir + str(dir_number), 0700)
+ self.base_dir = self._tmp_dir + str(dir_number) + '/'
break
dir_number += 1
pgpTjNXNQ6Ou2.pgp
Description: PGP signature

