In this patch I am extending the rule instantiator to create the comment
node where supported, which is the case for iptables and ip6tables.
Since commands are written in the format
cmd="iptables ...-m comment --comment \"\" "
certain characters ("$`\) in the comment need to be escaped (twice) to
prevent comments from becoming commands themselves or cause other
forms of (bash) substitutions. I have tested this with various input and in
my tests the input made it straight into the comment. A test case for TCK
will be provided separately that tests this.
To prevent consecutive spaces in comments from becoming a single space
(by bash), the IFS variable is now set to an empty string. Also, commands
are now executed using bash's 'eval' command.
Since the regular strchr() function causes a compiler warning when neither
one of the parameters is a constant, I reimplemented this function and
called it _strchr(). Here is the reference to this bug
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36513
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
---
src/nwfilter/nwfilter_ebiptables_driver.c | 68 +++++++++++++++++++++++++++++-
src/nwfilter/nwfilter_ebiptables_driver.h | 3 +
2 files changed, 69 insertions(+), 2 deletions(-)
Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.c
+++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -55,7 +55,7 @@
#define CMD_DEF_PRE "cmd=\""
#define CMD_DEF_POST "\""
#define CMD_DEF(X) CMD_DEF_PRE X CMD_DEF_POST
-#define CMD_EXEC "res=`${cmd}`" CMD_SEPARATOR
+#define CMD_EXEC "res=`eval ${cmd}`" CMD_SEPARATOR
#define CMD_STOPONERR(X) \
X ? "if [ $? -ne 0 ]; then" \
" echo \"Failure to execute command '${cmd}'.\";" \
@@ -291,6 +291,58 @@ printDataTypeAsHex(virNWFilterHashTableP
}
+/* avoiding a compiler warning trough own implementation */
+static const char *
+_strchr(const char *s, int c)
+{
+ while (*s && *s != (char)c)
+ s++;
+ if (*s)
+ return s;
+ return NULL;
+}
+
+
+static char *
+shellEscapeString(const char *data, size_t maxlen,
+ const char *s, bool doubleEscape)
+{
+ char *res;
+ size_t i, j, add = 0, len = strlen(data);
+
+ if (len > maxlen)
+ len = maxlen;
+
+ for (i = 0; i < len; i++) {
+ if (_strchr(s, data[i])) {
+ add += 1;
+ if (doubleEscape)
+ add += 2;
+ }
+ }
+
+ if (VIR_ALLOC_VAR(res, char, len+add+1) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ j = 0;
+ for (i = 0; i < len; i++) {
+ if (_strchr(s, data[i])) {
+ res[j++] = '\\';
+ if (doubleEscape) {
+ res[j++] = '\\';
+ res[j++] = '\\';
+ }
+ }
+ res[j++] = data[i];
+ }
+ res[j] = 0;
+
+ return res;
+}
+
+
static void
ebiptablesRuleInstFree(ebiptablesRuleInstPtr inst)
{
@@ -993,6 +1045,18 @@ iptablesHandleIpHdr(virBufferPtr buf,
}
}
+ if (HAS_ENTRY_ITEM(&ipHdr->dataComment)) {
+ char *cmt = shellEscapeString(ipHdr->dataComment.u.string,
+ IPTABLES_MAX_COMMENT_SIZE,
+ "\"`\\$", true);
+ if (!cmt)
+ goto err_exit;
+ virBufferVSprintf(buf,
+ " -m comment --comment \\\"%s\\\"",
+ cmt);
+ VIR_FREE(cmt);
+ }
+
return 0;
err_exit:
@@ -2211,7 +2275,7 @@ ebiptablesWriteToTempFile(const char *st
char *header;
size_t written;
- virBufferVSprintf(&buf, "#!%s\n", bash_cmd_path);
+ virBufferVSprintf(&buf, "#!%s\nIFS=""\n", bash_cmd_path);
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.h
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.h
+++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.h
@@ -45,4 +45,7 @@ extern virNWFilterTechDriver ebiptables_
# define EBIPTABLES_DRIVER_ID "ebiptables"
+
+# define IPTABLES_MAX_COMMENT_SIZE 256
+
#endif