Bug#635549: foomatic-filters 4.0.5-6+squeeze1 stable-security upload for CVE-2011-2964
Hi Moritz,
(CC'ing #635549 as it was mentionned there and team@s.d.o as per [0])
First of all, sorry for the delay.
I have been preparing a stable-security upload for foomatic-filters,
reportedly vulnerable to CVE-2011-2964 in its version currently in
stable.
(By the way, given that there is _no_ C version of foomatic-rip in
lenny's foomatic-filters, I think that lenny is not affected by
CVE-2011-2964; it is by CVE-2011-2697 though, I'll see what I can do on
that side.)
The Ubuntu folks have already uploaded a fix for this specific issue
[1], so I have just taken their patch. debdiff and patch are attached,
proposed changelog entry is below, please comment.
foomatic-filters (4.0.5-6+squeeze1) stable-security; urgency=high
* Fix CVE-2011-2964
"foomaticrip.c in foomatic-rip in foomatic-filters allows remote
attackers
to execute arbitrary code via a crafted *FoomaticRIPCommandLine
field in
a .ppd file."
- Import debian/patches/CVE-2011-2964.patch from Ubuntu maverick's
4.0.5-0ubuntu3.1, enhance its DEP-3 headers.
Cheers,
OdyX
[0] http://www.debian.org/security/faq#contact
[1]
https://launchpad.net/ubuntu/maverick/+source/foomatic-filters/4.0.5-0ubuntu3.1
and
http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/maverick/foomatic-filters/maverick-security/view/head:/debian/patches/CVE-2011-2964.patchdiff -Nru foomatic-filters-4.0.5/debian/changelog foomatic-filters-4.0.5/debian/changelog
--- foomatic-filters-4.0.5/debian/changelog 2010-11-10 10:10:04.000000000 +0100
+++ foomatic-filters-4.0.5/debian/changelog 2012-01-04 11:25:56.000000000 +0100
@@ -1,3 +1,14 @@
+foomatic-filters (4.0.5-6+squeeze1) stable-security; urgency=high
+
+ * Fix CVE-2011-2964
+ "foomaticrip.c in foomatic-rip in foomatic-filters allows remote attackers
+ to execute arbitrary code via a crafted *FoomaticRIPCommandLine field in
+ a .ppd file."
+ - Import debian/patches/CVE-2011-2964.patch from Ubuntu maverick's
+ 4.0.5-0ubuntu3.1, enhance its DEP-3 headers.
+
+ -- Didier Raboud <odyx@debian.org> Wed, 04 Jan 2012 11:14:59 +0100
+
foomatic-filters (4.0.5-6) unstable; urgency=low
[ Till Kamppeter ]
diff -Nru foomatic-filters-4.0.5/debian/patches/CVE-2011-2964.patch foomatic-filters-4.0.5/debian/patches/CVE-2011-2964.patch
--- foomatic-filters-4.0.5/debian/patches/CVE-2011-2964.patch 1970-01-01 01:00:00.000000000 +0100
+++ foomatic-filters-4.0.5/debian/patches/CVE-2011-2964.patch 2012-01-04 11:10:31.000000000 +0100
@@ -0,0 +1,224 @@
+Description: fix arbitrary code execution via crafted PPD file
+ .
+ From upstream changelog entry:
+ .
+ foomaticrip.c: SECURITY FIX: It was possible to make CUPS executing
+ arbitrary commands as the system user "lp" when foomatic-rip was
+ used as CUPS filter. Fixed by not parsing named options (like
+ "--ppd lj.ppd") when foomatic-rip is running as CUPS filter, as
+ CUPS does not supply named options to their filters.
+
+Author: Till Kamppeter <till.kamppeter@gmail.com>
+Acked-by: Marc Deslauriers <marc.deslauriers@ubuntu.com>
+Origin: upstream, http://bzr.linuxfoundation.org/loggerhead/openprinting/foomatic/foomatic-filters/revision/252
+Bug-CVE: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-2964
+Last-Update: 2011-07-24
+
+Index: foomatic-filters-4.0.5/foomaticrip.c
+===================================================================
+--- foomatic-filters-4.0.5.orig/foomaticrip.c 2010-08-10 06:08:04.000000000 -0400
++++ foomatic-filters-4.0.5/foomaticrip.c 2011-08-03 11:23:00.551600057 -0400
+@@ -1230,8 +1230,11 @@
+ }
+
+ /* Check for LPRng first so we do not pick up bogus ppd files by the -ppd option */
+- if (arglist_remove_flag(arglist, "--lprng"))
+- spooler = SPOOLER_LPRNG;
++ if (spooler != SPOOLER_CUPS && spooler != SPOOLER_PPR &&
++ spooler != SPOOLER_PPR_INT) {
++ if (arglist_remove_flag(arglist, "--lprng"))
++ spooler = SPOOLER_LPRNG;
++ }
+
+ /* 'PRINTCAP_ENTRY' environment variable is : LPRng
+ the :ppd=/path/to/ppdfile printcap entry should be used */
+@@ -1253,96 +1256,104 @@
+ }
+ }
+
+- /* PPD file name given via the command line
+- allow duplicates, and use the last specified one */
+- if (spooler != SPOOLER_LPRNG) {
+- while ((str = arglist_get_value(arglist, "-p"))) {
+- strncpy(job->ppdfile, str, 256);
+- arglist_remove(arglist, "-p");
++ /* CUPS calls foomatic-rip only with 5 or 6 positional parameters,
++ not with named options, like for example "-p <string>". Also PPR
++ does not used named options. */
++ if (spooler != SPOOLER_CUPS && spooler != SPOOLER_PPR &&
++ spooler != SPOOLER_PPR_INT) {
++ /* Check for LPD/GNUlpr by typical options which the spooler puts onto
++ the filter's command line (options "-w": text width, "-l": text
++ length, "-i": indent, "-x", "-y": graphics size, "-c": raw printing,
++ "-n": user name, "-h": host name) */
++ if ((str = arglist_get_value(arglist, "-h"))) {
++ if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG)
++ spooler = SPOOLER_LPD;
++ strncpy(job->host, str, 127);
++ job->host[127] = '\0';
++ arglist_remove(arglist, "-h");
+ }
+- }
+- while ((str = arglist_get_value(arglist, "--ppd"))) {
+- strncpy(job->ppdfile, str, 256);
+- arglist_remove(arglist, "--ppd");
+- }
+-
+- /* Check for LPD/GNUlpr by typical options which the spooler puts onto
+- the filter's command line (options "-w": text width, "-l": text
+- length, "-i": indent, "-x", "-y": graphics size, "-c": raw printing,
+- "-n": user name, "-h": host name) */
+- if ((str = arglist_get_value(arglist, "-h"))) {
+- if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG)
+- spooler = SPOOLER_LPD;
+- strncpy(job->host, str, 127);
+- job->host[127] = '\0';
+- arglist_remove(arglist, "-h");
+- }
+- if ((str = arglist_get_value(arglist, "-n"))) {
+- if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG)
+- spooler = SPOOLER_LPD;
+-
+- strncpy(job->user, str, 127);
+- job->user[127] = '\0';
+- arglist_remove(arglist, "-n");
+- }
+- if (arglist_remove(arglist, "-w") ||
+- arglist_remove(arglist, "-l") ||
+- arglist_remove(arglist, "-x") ||
+- arglist_remove(arglist, "-y") ||
+- arglist_remove(arglist, "-i") ||
+- arglist_remove_flag(arglist, "-c")) {
++ if ((str = arglist_get_value(arglist, "-n"))) {
+ if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG)
+ spooler = SPOOLER_LPD;
+- }
+- /* LPRng delivers the option settings via the "-Z" argument */
+- if ((str = arglist_get_value(arglist, "-Z"))) {
+- spooler = SPOOLER_LPRNG;
+- dstrcatf(job->optstr, "%s ", str);
+- arglist_remove(arglist, "-Z");
+- }
+- /* Job title and options for stock LPD */
+- if ((str = arglist_get_value(arglist, "-j")) || (str = arglist_get_value(arglist, "-J"))) {
+- strncpy_omit(job->title, str, 128, omit_shellescapes);
+- if (spooler == SPOOLER_LPD)
+- dstrcatf(job->optstr, "%s ", job->title);
+- if (!arglist_remove(arglist, "-j"))
+- arglist_remove(arglist, "-J");
+- }
+- /* Check for CPS */
+- if (arglist_remove_flag(arglist, "--cps") > 0)
+- spooler = SPOOLER_CPS;
+-
+- /* Options for spooler-less printing, CPS, or PDQ */
+- while ((str = arglist_get_value(arglist, "-o"))) {
+- strncpy_omit(tmp, str, 1024, omit_shellescapes);
+- dstrcatf(job->optstr, "%s ", tmp);
+- arglist_remove(arglist, "-o");
+- /* If we don't print as PPR RIP or as CPS filter, we print
+- without spooler (we check for PDQ later) */
+- if (spooler != SPOOLER_PPR && spooler != SPOOLER_CPS)
+- spooler = SPOOLER_DIRECT;
+- }
+
+- /* Printer for spooler-less printing or PDQ */
+- if ((str = arglist_get_value(arglist, "-d"))) {
+- strncpy_omit(job->printer, str, 256, omit_shellescapes);
+- arglist_remove(arglist, "-d");
+- }
++ strncpy(job->user, str, 127);
++ job->user[127] = '\0';
++ arglist_remove(arglist, "-n");
++ }
++ if (arglist_remove(arglist, "-w") ||
++ arglist_remove(arglist, "-l") ||
++ arglist_remove(arglist, "-x") ||
++ arglist_remove(arglist, "-y") ||
++ arglist_remove(arglist, "-i") ||
++ arglist_remove_flag(arglist, "-c")) {
++ if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG)
++ spooler = SPOOLER_LPD;
++ }
++ /* LPRng delivers the option settings via the "-Z" argument */
++ if ((str = arglist_get_value(arglist, "-Z"))) {
++ spooler = SPOOLER_LPRNG;
++ dstrcatf(job->optstr, "%s ", str);
++ arglist_remove(arglist, "-Z");
++ }
++ /* Job title and options for stock LPD */
++ if ((str = arglist_get_value(arglist, "-j")) || (str = arglist_get_value(arglist, "-J"))) {
++ strncpy_omit(job->title, str, 128, omit_shellescapes);
++ if (spooler == SPOOLER_LPD)
++ dstrcatf(job->optstr, "%s ", job->title);
++ if (!arglist_remove(arglist, "-j"))
++ arglist_remove(arglist, "-J");
++ }
+
+- /* Printer for spooler-less printing, PDQ, or LPRng */
+- if ((str = arglist_get_value(arglist, "-P"))) {
+- strncpy_omit(job->printer, str, 256, omit_shellescapes);
+- arglist_remove(arglist, "-P");
+- }
++ /* Check for CPS */
++ if (arglist_remove_flag(arglist, "--cps") > 0)
++ spooler = SPOOLER_CPS;
++
++ /* PPD file name given via the command line
++ allow duplicates, and use the last specified one */
++ if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG &&
++ spooler != SPOOLER_LPD) {
++ while ((str = arglist_get_value(arglist, "-p"))) {
++ strncpy(job->ppdfile, str, 256);
++ arglist_remove(arglist, "-p");
++ }
++ while ((str = arglist_get_value(arglist, "--ppd"))) {
++ strncpy(job->ppdfile, str, 256);
++ arglist_remove(arglist, "--ppd");
++ }
++ }
+
+- /* Were we called from a PDQ wrapper? */
+- if (arglist_remove_flag(arglist, "--pdq"))
+- spooler = SPOOLER_PDQ;
+-
+- /* Were we called to build the PDQ driver declaration file? */
+- genpdqfile = check_pdq_file(arglist);
+- if (genpdqfile)
+- spooler = SPOOLER_PDQ;
++ /* Options for spooler-less printing, CPS, or PDQ */
++ while ((str = arglist_get_value(arglist, "-o"))) {
++ strncpy_omit(tmp, str, 1024, omit_shellescapes);
++ dstrcatf(job->optstr, "%s ", tmp);
++ arglist_remove(arglist, "-o");
++ /* If we don't print as PPR RIP or as CPS filter, we print
++ without spooler (we check for PDQ later) */
++ if (spooler != SPOOLER_PPR && spooler != SPOOLER_CPS)
++ spooler = SPOOLER_DIRECT;
++ }
++
++ /* Printer for spooler-less printing or PDQ */
++ if ((str = arglist_get_value(arglist, "-d"))) {
++ strncpy_omit(job->printer, str, 256, omit_shellescapes);
++ arglist_remove(arglist, "-d");
++ }
++
++ /* Printer for spooler-less printing, PDQ, or LPRng */
++ if ((str = arglist_get_value(arglist, "-P"))) {
++ strncpy_omit(job->printer, str, 256, omit_shellescapes);
++ arglist_remove(arglist, "-P");
++ }
++
++ /* Were we called from a PDQ wrapper? */
++ if (arglist_remove_flag(arglist, "--pdq"))
++ spooler = SPOOLER_PDQ;
++
++ /* Were we called to build the PDQ driver declaration file? */
++ genpdqfile = check_pdq_file(arglist);
++ if (genpdqfile)
++ spooler = SPOOLER_PDQ;
++ }
+
+ /* spooler specific initialization */
+ switch (spooler) {
+
diff -Nru foomatic-filters-4.0.5/debian/patches/series foomatic-filters-4.0.5/debian/patches/series
--- foomatic-filters-4.0.5/debian/patches/series 2010-11-10 10:11:03.000000000 +0100
+++ foomatic-filters-4.0.5/debian/patches/series 2012-01-04 11:04:11.000000000 +0100
@@ -1,2 +1,3 @@
strncpy-tochar-use-isempty.patch
unhtmlify-segfault.patch
+CVE-2011-2964.patch
Description: fix arbitrary code execution via crafted PPD file
.
From upstream changelog entry:
.
foomaticrip.c: SECURITY FIX: It was possible to make CUPS executing
arbitrary commands as the system user "lp" when foomatic-rip was
used as CUPS filter. Fixed by not parsing named options (like
"--ppd lj.ppd") when foomatic-rip is running as CUPS filter, as
CUPS does not supply named options to their filters.
Author: Till Kamppeter <till.kamppeter@gmail.com>
Acked-by: Marc Deslauriers <marc.deslauriers@ubuntu.com>
Origin: upstream, http://bzr.linuxfoundation.org/loggerhead/openprinting/foomatic/foomatic-filters/revision/252
Bug-CVE: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-2964
Last-Update: 2011-07-24
Index: foomatic-filters-4.0.5/foomaticrip.c
===================================================================
--- foomatic-filters-4.0.5.orig/foomaticrip.c 2010-08-10 06:08:04.000000000 -0400
+++ foomatic-filters-4.0.5/foomaticrip.c 2011-08-03 11:23:00.551600057 -0400
@@ -1230,8 +1230,11 @@
}
/* Check for LPRng first so we do not pick up bogus ppd files by the -ppd option */
- if (arglist_remove_flag(arglist, "--lprng"))
- spooler = SPOOLER_LPRNG;
+ if (spooler != SPOOLER_CUPS && spooler != SPOOLER_PPR &&
+ spooler != SPOOLER_PPR_INT) {
+ if (arglist_remove_flag(arglist, "--lprng"))
+ spooler = SPOOLER_LPRNG;
+ }
/* 'PRINTCAP_ENTRY' environment variable is : LPRng
the :ppd=/path/to/ppdfile printcap entry should be used */
@@ -1253,96 +1256,104 @@
}
}
- /* PPD file name given via the command line
- allow duplicates, and use the last specified one */
- if (spooler != SPOOLER_LPRNG) {
- while ((str = arglist_get_value(arglist, "-p"))) {
- strncpy(job->ppdfile, str, 256);
- arglist_remove(arglist, "-p");
+ /* CUPS calls foomatic-rip only with 5 or 6 positional parameters,
+ not with named options, like for example "-p <string>". Also PPR
+ does not used named options. */
+ if (spooler != SPOOLER_CUPS && spooler != SPOOLER_PPR &&
+ spooler != SPOOLER_PPR_INT) {
+ /* Check for LPD/GNUlpr by typical options which the spooler puts onto
+ the filter's command line (options "-w": text width, "-l": text
+ length, "-i": indent, "-x", "-y": graphics size, "-c": raw printing,
+ "-n": user name, "-h": host name) */
+ if ((str = arglist_get_value(arglist, "-h"))) {
+ if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG)
+ spooler = SPOOLER_LPD;
+ strncpy(job->host, str, 127);
+ job->host[127] = '\0';
+ arglist_remove(arglist, "-h");
}
- }
- while ((str = arglist_get_value(arglist, "--ppd"))) {
- strncpy(job->ppdfile, str, 256);
- arglist_remove(arglist, "--ppd");
- }
-
- /* Check for LPD/GNUlpr by typical options which the spooler puts onto
- the filter's command line (options "-w": text width, "-l": text
- length, "-i": indent, "-x", "-y": graphics size, "-c": raw printing,
- "-n": user name, "-h": host name) */
- if ((str = arglist_get_value(arglist, "-h"))) {
- if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG)
- spooler = SPOOLER_LPD;
- strncpy(job->host, str, 127);
- job->host[127] = '\0';
- arglist_remove(arglist, "-h");
- }
- if ((str = arglist_get_value(arglist, "-n"))) {
- if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG)
- spooler = SPOOLER_LPD;
-
- strncpy(job->user, str, 127);
- job->user[127] = '\0';
- arglist_remove(arglist, "-n");
- }
- if (arglist_remove(arglist, "-w") ||
- arglist_remove(arglist, "-l") ||
- arglist_remove(arglist, "-x") ||
- arglist_remove(arglist, "-y") ||
- arglist_remove(arglist, "-i") ||
- arglist_remove_flag(arglist, "-c")) {
+ if ((str = arglist_get_value(arglist, "-n"))) {
if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG)
spooler = SPOOLER_LPD;
- }
- /* LPRng delivers the option settings via the "-Z" argument */
- if ((str = arglist_get_value(arglist, "-Z"))) {
- spooler = SPOOLER_LPRNG;
- dstrcatf(job->optstr, "%s ", str);
- arglist_remove(arglist, "-Z");
- }
- /* Job title and options for stock LPD */
- if ((str = arglist_get_value(arglist, "-j")) || (str = arglist_get_value(arglist, "-J"))) {
- strncpy_omit(job->title, str, 128, omit_shellescapes);
- if (spooler == SPOOLER_LPD)
- dstrcatf(job->optstr, "%s ", job->title);
- if (!arglist_remove(arglist, "-j"))
- arglist_remove(arglist, "-J");
- }
- /* Check for CPS */
- if (arglist_remove_flag(arglist, "--cps") > 0)
- spooler = SPOOLER_CPS;
-
- /* Options for spooler-less printing, CPS, or PDQ */
- while ((str = arglist_get_value(arglist, "-o"))) {
- strncpy_omit(tmp, str, 1024, omit_shellescapes);
- dstrcatf(job->optstr, "%s ", tmp);
- arglist_remove(arglist, "-o");
- /* If we don't print as PPR RIP or as CPS filter, we print
- without spooler (we check for PDQ later) */
- if (spooler != SPOOLER_PPR && spooler != SPOOLER_CPS)
- spooler = SPOOLER_DIRECT;
- }
- /* Printer for spooler-less printing or PDQ */
- if ((str = arglist_get_value(arglist, "-d"))) {
- strncpy_omit(job->printer, str, 256, omit_shellescapes);
- arglist_remove(arglist, "-d");
- }
+ strncpy(job->user, str, 127);
+ job->user[127] = '\0';
+ arglist_remove(arglist, "-n");
+ }
+ if (arglist_remove(arglist, "-w") ||
+ arglist_remove(arglist, "-l") ||
+ arglist_remove(arglist, "-x") ||
+ arglist_remove(arglist, "-y") ||
+ arglist_remove(arglist, "-i") ||
+ arglist_remove_flag(arglist, "-c")) {
+ if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG)
+ spooler = SPOOLER_LPD;
+ }
+ /* LPRng delivers the option settings via the "-Z" argument */
+ if ((str = arglist_get_value(arglist, "-Z"))) {
+ spooler = SPOOLER_LPRNG;
+ dstrcatf(job->optstr, "%s ", str);
+ arglist_remove(arglist, "-Z");
+ }
+ /* Job title and options for stock LPD */
+ if ((str = arglist_get_value(arglist, "-j")) || (str = arglist_get_value(arglist, "-J"))) {
+ strncpy_omit(job->title, str, 128, omit_shellescapes);
+ if (spooler == SPOOLER_LPD)
+ dstrcatf(job->optstr, "%s ", job->title);
+ if (!arglist_remove(arglist, "-j"))
+ arglist_remove(arglist, "-J");
+ }
- /* Printer for spooler-less printing, PDQ, or LPRng */
- if ((str = arglist_get_value(arglist, "-P"))) {
- strncpy_omit(job->printer, str, 256, omit_shellescapes);
- arglist_remove(arglist, "-P");
- }
+ /* Check for CPS */
+ if (arglist_remove_flag(arglist, "--cps") > 0)
+ spooler = SPOOLER_CPS;
+
+ /* PPD file name given via the command line
+ allow duplicates, and use the last specified one */
+ if (spooler != SPOOLER_GNULPR && spooler != SPOOLER_LPRNG &&
+ spooler != SPOOLER_LPD) {
+ while ((str = arglist_get_value(arglist, "-p"))) {
+ strncpy(job->ppdfile, str, 256);
+ arglist_remove(arglist, "-p");
+ }
+ while ((str = arglist_get_value(arglist, "--ppd"))) {
+ strncpy(job->ppdfile, str, 256);
+ arglist_remove(arglist, "--ppd");
+ }
+ }
- /* Were we called from a PDQ wrapper? */
- if (arglist_remove_flag(arglist, "--pdq"))
- spooler = SPOOLER_PDQ;
-
- /* Were we called to build the PDQ driver declaration file? */
- genpdqfile = check_pdq_file(arglist);
- if (genpdqfile)
- spooler = SPOOLER_PDQ;
+ /* Options for spooler-less printing, CPS, or PDQ */
+ while ((str = arglist_get_value(arglist, "-o"))) {
+ strncpy_omit(tmp, str, 1024, omit_shellescapes);
+ dstrcatf(job->optstr, "%s ", tmp);
+ arglist_remove(arglist, "-o");
+ /* If we don't print as PPR RIP or as CPS filter, we print
+ without spooler (we check for PDQ later) */
+ if (spooler != SPOOLER_PPR && spooler != SPOOLER_CPS)
+ spooler = SPOOLER_DIRECT;
+ }
+
+ /* Printer for spooler-less printing or PDQ */
+ if ((str = arglist_get_value(arglist, "-d"))) {
+ strncpy_omit(job->printer, str, 256, omit_shellescapes);
+ arglist_remove(arglist, "-d");
+ }
+
+ /* Printer for spooler-less printing, PDQ, or LPRng */
+ if ((str = arglist_get_value(arglist, "-P"))) {
+ strncpy_omit(job->printer, str, 256, omit_shellescapes);
+ arglist_remove(arglist, "-P");
+ }
+
+ /* Were we called from a PDQ wrapper? */
+ if (arglist_remove_flag(arglist, "--pdq"))
+ spooler = SPOOLER_PDQ;
+
+ /* Were we called to build the PDQ driver declaration file? */
+ genpdqfile = check_pdq_file(arglist);
+ if (genpdqfile)
+ spooler = SPOOLER_PDQ;
+ }
/* spooler specific initialization */
switch (spooler) {
Reply to: