[Pkg-electronics-commits] [pcb-rnd] 01/01: security patch from upstream

Bdale Garbee bdale at moszumanska.debian.org
Mon Sep 18 00:56:51 UTC 2017


This is an automated email from the git hooks/post-receive script.

bdale pushed a commit to tag debian/1.2.5-2
in repository pcb-rnd.

commit 84c208a5c9eab2eda03431516d2e452383410ae4
Author: Bdale Garbee <bdale at gag.com>
Date:   Sun Sep 17 18:23:45 2017 -0600

    security patch from upstream
---
 debian/changelog             |   7 ++
 debian/patches/exec-bug.diff | 253 +++++++++++++++++++++++++++++++++++++++++++
 debian/patches/series        |   1 +
 3 files changed, 261 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index c9c3f16..f7afe89 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+pcb-rnd (1.2.5-2) unstable; urgency=high
+
+  * security patch from upstream to eliminate execution of code from a 
+    maliciously formed design file
+
+ -- Bdale Garbee <bdale at gag.com>  Sun, 17 Sep 2017 18:23:29 -0600
+
 pcb-rnd (1.2.5-1) unstable; urgency=medium
 
   * New upstream version
diff --git a/debian/patches/exec-bug.diff b/debian/patches/exec-bug.diff
new file mode 100644
index 0000000..406b018
--- /dev/null
+++ b/debian/patches/exec-bug.diff
@@ -0,0 +1,253 @@
+diff --git a/src/conf.c b/src/conf.c
+index 17bfb41..92449d4 100644
+--- a/src/conf.c
++++ b/src/conf.c
+@@ -1869,3 +1869,65 @@ void conf_setf(conf_role_t role, const char *path, int idx, const char *fmt, ...
+ 
+ 	free(tmp);
+ }
++
++int pcb_conf_cmd_is_safe_(const char *path_, const char *value, const char **val_out, int msg)
++{
++	const char *reason;
++	conf_native_t *nd;
++	char *path, *s;
++
++	if (val_out != NULL)
++		*val_out = NULL;
++
++	if (value == NULL)
++		goto accept;
++
++	path = pcb_strdup(path_);
++	for(s = path; *s != '\0'; s++)
++		if (*s == '.')
++			*s = '/';
++	nd = conf_get_field(path);
++	free(path);
++
++	if (nd == NULL) {
++		if (msg)
++			pcb_message(PCB_MSG_ERROR, "pcb_conf_cmd_is_safe(): invalid node path '%s' (looks like an internal error)\n", path_);
++		return 0;
++	}
++
++	if (nd->array_size > 1) {
++		if (msg)
++			pcb_message(PCB_MSG_ERROR, "pcb_conf_cmd_is_safe(): invalid node path '%s' (it is an array)\n", path_);
++		return 0;
++	}
++
++	switch(conf_lookup_role(nd->prop[0].src)) {
++		/* these are considered safe, because: */
++		case CFR_INTERNAL: /* the attacker would have access to the source code and compilation, could place system() anyway */
++		case CFR_SYSTEM:   /* system admin - lets trust them */
++		case CFR_USER:     /* user config is written by the user, attackers have no better chance to overwrite that than overwriting the the shell's rc */
++		case CFR_CLI:      /* command line arguments: the user specified those; who has access to that potentially has access to the shell anyway */
++			goto accept;
++
++		/* these are considered unsafe, because: */
++		case CFR_DEFAULTPCB: /* the default pcb path may be manipulated; the user has the chance to specify the command path setting from safe config files */
++			reason = "default pcb"; break;
++		case CFR_ENV: /* env vars may be inherited from who-knows-where */
++			reason = "env var"; break;
++		case CFR_PROJECT: /* malicous file prepared by the attacker */
++			reason = "project file"; break;
++		case CFR_DESIGN: /* malicous file prepared by the attacker */
++			reason = "board file"; break;
++		default:
++			reason = "unknown source";
++	}
++
++	if (msg)
++		pcb_message(PCB_MSG_ERROR, "pcb_conf_cmd_is_safe(): refusing to use the value of '%s' because it is from unsafe source %s\n", path_, reason);
++	return 0;
++
++	accept:;
++	if (val_out != NULL)
++		*val_out = value;
++	return 1;
++}
+diff --git a/src/conf.h b/src/conf.h
+index e1b62ec..8e2a143 100644
+--- a/src/conf.h
++++ b/src/conf.h
+@@ -366,4 +366,10 @@ const char *conf_get_user_conf_name();
+ /* Determine the file name of the project file - project_fn and pcb_fn can be NULL */
+ const char *conf_get_project_conf_name(const char *project_fn, const char *pcb_fn, const char **out_project_fn);
+ 
++/* Return 1 if the config node named in path is considered safe enough
++   to specify a command to execute - e.g. an attacker shouldn't be able to
++   inject commands in design files sent */
++int pcb_conf_cmd_is_safe_(const char *path, const char *value, const char **val_out, int msg);
++#define pcb_conf_cmd_is_safe(path, val_out, msg) pcb_conf_cmd_is_safe_(#path, conf_core.path, val_out, msg)
++
+ #endif
+diff --git a/src/plug_io.c b/src/plug_io.c
+index b51a284..9251b49 100644
+--- a/src/plug_io.c
++++ b/src/plug_io.c
+@@ -48,6 +48,7 @@
+ #include <string.h>
+ 
+ #include "change.h"
++#include "conf.h"
+ #include "data.h"
+ #include "error.h"
+ #include "plug_io.h"
+@@ -896,13 +897,17 @@ int pcb_write_pipe(const char *Filename, pcb_bool thePcb, const char *fmt, pcb_b
+ 	int result;
+ 	const char *p;
+ 	static gds_t command;
++	const char *save_cmd;
+ 
+ 	if (PCB_EMPTY_STRING_P(conf_core.rc.save_command))
+ 		return pcb_write_pcb_file(Filename, thePcb, fmt, pcb_false, elem_only);
+ 
++	if (!pcb_conf_cmd_is_safe(rc.save_command, &save_cmd, 1))
++		return -1;
++
+ 	/* setup commandline */
+ 	gds_truncate(&command,0);
+-	for (p = conf_core.rc.save_command; *p; p++) {
++	for (p = save_cmd; *p; p++) {
+ 		/* copy character if not special or add string to command */
+ 		if (!(p[0] == '%' && p[1] == 'f'))
+ 			gds_append(&command, *p);
+diff --git a/src_plugins/fp_fs/fp_fs.c b/src_plugins/fp_fs/fp_fs.c
+index 4d6d153..d592f55 100644
+--- a/src_plugins/fp_fs/fp_fs.c
++++ b/src_plugins/fp_fs/fp_fs.c
+@@ -464,7 +464,9 @@ static FILE *fp_fs_fopen(pcb_plug_fp_t *ctx, const char *path, const char *name,
+ {
+ 	char *basename, *params, *fullname;
+ 	FILE *f = NULL;
+-	const char *libshell = conf_core.rc.library_shell;
++	const char *libshell;
++
++	pcb_conf_cmd_is_safe(rc.library_shell, &libshell, 1);
+ 
+ 	fctx->field[F_IS_PARAMETRIC].i = pcb_fp_dupname(name, &basename, &params);
+ 	if (basename == NULL)
+diff --git a/src_plugins/import_netlist/import_netlist.c b/src_plugins/import_netlist/import_netlist.c
+index 27c3af3..60f5a9e 100644
+--- a/src_plugins/import_netlist/import_netlist.c
++++ b/src_plugins/import_netlist/import_netlist.c
+@@ -58,13 +58,16 @@ static int ReadNetlist(const char *filename)
+ 	int i, j, lines, kind;
+ 	pcb_bool continued;
+ 	int used_popen = 0;
++	const char *ratcmd;
+ 
+ 	if (!filename)
+ 		return (1);									/* nothing to do */
+ 
+ 	pcb_message(PCB_MSG_INFO, _("Importing PCB netlist %s\n"), filename);
+ 
+-	if (PCB_EMPTY_STRING_P(conf_core.rc.rat_command)) {
++	pcb_conf_cmd_is_safe(rc.rat_command, &ratcmd, 1);
++
++	if (PCB_EMPTY_STRING_P(ratcmd)) {
+ 		fp = fopen(filename, "r");
+ 		if (!fp) {
+ 			pcb_message(PCB_MSG_ERROR, "Cannot open %s for reading", filename);
+diff --git a/src_plugins/io_pcb/parse_l.c b/src_plugins/io_pcb/parse_l.c
+index b8bf493..7d46b23 100644
+--- a/src_plugins/io_pcb/parse_l.c
++++ b/src_plugins/io_pcb/parse_l.c
+@@ -2516,6 +2516,7 @@ do { \
+ int io_pcb_ParsePCB(pcb_plug_io_t *ctx, pcb_board_t *Ptr, const char *Filename, conf_role_t settings_dest)
+ {
+ 	int retval;
++	const char *fcmd;
+ 	yy_parse_tags = 0;
+ 	yyPCB = Ptr;
+ 	yyData = NULL;
+@@ -2524,10 +2525,15 @@ int io_pcb_ParsePCB(pcb_plug_io_t *ctx, pcb_board_t *Ptr, const char *Filename,
+ 	yyFontkitValid = NULL;
+ 	yyElement = NULL;
+ 	yy_settings_dest = settings_dest;
++
++	if (!pcb_conf_cmd_is_safe(rc.file_command, &fcmd, 1))
++		return -1;
++
+ 	if (settings_dest != CFR_invalid)
+ 		conf_reset(settings_dest, Filename);
+ 	pcb_setlocale(LC_ALL, "C"); /* make sure numerics are read predictably */
+-	retval = Parse(NULL, conf_core.rc.file_command, conf_core.rc.file_path, Filename);
++
++	retval = Parse(NULL, fcmd, conf_core.rc.file_path, Filename);
+ 	pcb_setlocale(LC_ALL, "");
+ 	if ((settings_dest != CFR_invalid) && (retval == 0)) {
+ 		/* overwrite settings from the flags, mark them not-to-save */
+@@ -2593,6 +2599,7 @@ int io_pcb_ParsePCB(pcb_plug_io_t *ctx, pcb_board_t *Ptr, const char *Filename,
+ int io_pcb_ParseFont(pcb_plug_io_t *ctx, pcb_font_t *Ptr, const char *Filename)
+ {
+ 	int r = 0, valid;
++	const char *fcmd;
+ 	yy_parse_tags = 1;
+ 	yyPCB = NULL;
+ 	yyFont = Ptr;
+@@ -2600,8 +2607,11 @@ int io_pcb_ParseFont(pcb_plug_io_t *ctx, pcb_font_t *Ptr, const char *Filename)
+ 	yyElement = NULL;
+ 	yyFontReset = pcb_false;
+ 
++	if (!pcb_conf_cmd_is_safe(rc.font_command, &fcmd, 1))
++		return -1;
++
+ 	yy_settings_dest = CFR_invalid;
+-	r = Parse(NULL, conf_core.rc.font_command, NULL, Filename);
++	r = Parse(NULL, fcmd, NULL, Filename);
+ 	if (r == 0) {
+ #ifdef DEBUG
+ 		pcb_message(PCB_MSG_DEBUG, "Found %s in %s\n", Filename, conf_core.rc.font_command);
+diff --git a/src_plugins/io_pcb/parse_l.l b/src_plugins/io_pcb/parse_l.l
+index 66bc301..76174be 100644
+--- a/src_plugins/io_pcb/parse_l.l
++++ b/src_plugins/io_pcb/parse_l.l
+@@ -375,6 +375,7 @@ do { \
+ int io_pcb_ParsePCB(pcb_plug_io_t *ctx, pcb_board_t *Ptr, const char *Filename, conf_role_t settings_dest)
+ {
+ 	int retval;
++	const char *fcmd;
+ 	yy_parse_tags = 0;
+ 	yyPCB = Ptr;
+ 	yyData = NULL;
+@@ -383,10 +384,15 @@ int io_pcb_ParsePCB(pcb_plug_io_t *ctx, pcb_board_t *Ptr, const char *Filename,
+ 	yyFontkitValid = NULL;
+ 	yyElement = NULL;
+ 	yy_settings_dest = settings_dest;
++
++	if (!pcb_conf_cmd_is_safe(rc.file_command, &fcmd, 1))
++		return -1;
++
+ 	if (settings_dest != CFR_invalid)
+ 		conf_reset(settings_dest, Filename);
+ 	pcb_setlocale(LC_ALL, "C"); /* make sure numerics are read predictably */
+-	retval = Parse(NULL, conf_core.rc.file_command, conf_core.rc.file_path, Filename);
++
++	retval = Parse(NULL, fcmd, conf_core.rc.file_path, Filename);
+ 	pcb_setlocale(LC_ALL, "");
+ 	if ((settings_dest != CFR_invalid) && (retval == 0)) {
+ 		/* overwrite settings from the flags, mark them not-to-save */
+@@ -452,6 +458,7 @@ int io_pcb_ParsePCB(pcb_plug_io_t *ctx, pcb_board_t *Ptr, const char *Filename,
+ int io_pcb_ParseFont(pcb_plug_io_t *ctx, pcb_font_t *Ptr, const char *Filename)
+ {
+ 	int r = 0, valid;
++	const char *fcmd;
+ 	yy_parse_tags = 1;
+ 	yyPCB = NULL;
+ 	yyFont = Ptr;
+@@ -459,8 +466,11 @@ int io_pcb_ParseFont(pcb_plug_io_t *ctx, pcb_font_t *Ptr, const char *Filename)
+ 	yyElement = NULL;
+ 	yyFontReset = pcb_false;
+ 
++	if (!pcb_conf_cmd_is_safe(rc.font_command, &fcmd, 1))
++		return -1;
++
+ 	yy_settings_dest = CFR_invalid;
+-	r = Parse(NULL, conf_core.rc.font_command, NULL, Filename);
++	r = Parse(NULL, fcmd, NULL, Filename);
+ 	if (r == 0) {
+ #ifdef DEBUG
+ 		pcb_message(PCB_MSG_DEBUG, "Found %s in %s\n", Filename, conf_core.rc.font_command);
diff --git a/debian/patches/series b/debian/patches/series
index e69de29..b477798 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -0,0 +1 @@
+exec-bug.diff

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-electronics/pcb-rnd.git



More information about the Pkg-electronics-commits mailing list