Blame SOURCES/libxtables-move-some-code-to-avoid-cautions-in-vfork.patch

9a3fa7
From 0d89bdef1e7f698787967bffed5c413ef0dee761 Mon Sep 17 00:00:00 2001
9a3fa7
From: Phil Sutter <psutter@redhat.com>
9a3fa7
Date: Fri, 15 Mar 2019 17:51:28 +0100
9a3fa7
Subject: [PATCH] libxtables: move some code to avoid cautions in vfork man
9a3fa7
 page
9a3fa7
9a3fa7
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1525980
9a3fa7
Upstream Status: iptables commit 78683093cf4f0
9a3fa7
9a3fa7
commit 78683093cf4f059531e5f929a4884ffaecb8411c
9a3fa7
Author: Dan Wilder <dan.wilder@watchguard.com>
9a3fa7
Date:   Sat Oct 25 00:51:59 2014 +0200
9a3fa7
9a3fa7
    libxtables: move some code to avoid cautions in vfork man page
9a3fa7
9a3fa7
    Running iptables-restore on an embedded platform containing no modprobe program, the following lines in xtables.c lead to corrupted stack frame:
9a3fa7
9a3fa7
     357     switch (vfork()) {
9a3fa7
     358     case 0:
9a3fa7
     359         argv[0] = (char *)modprobe;
9a3fa7
     360         argv[1] = (char *)modname;
9a3fa7
     361         if (quiet) {
9a3fa7
     362             argv[2] = "-q";
9a3fa7
     363             argv[3] = NULL;
9a3fa7
     364         } else {
9a3fa7
     365             argv[2] = NULL;
9a3fa7
     366             argv[3] = NULL;
9a3fa7
     367         }
9a3fa7
     368         execv(argv[0], argv);
9a3fa7
     369
9a3fa7
     370         /* not usually reached */
9a3fa7
     371         exit(1);
9a3fa7
9a3fa7
    modprobe pointed to a non-existant program /sbin/modprobe, so execv()
9a3fa7
    always failed.  Not a problem in itself on our platform, as the kernel
9a3fa7
    modules are pre-loaded before iptables-restore is run, but it took a
9a3fa7
    bit of headscratching to track this down, as a stack frame was
9a3fa7
    corrupted, leading to failures quite a while after the function
9a3fa7
    containing this code had returned!
9a3fa7
9a3fa7
    Relevant caution in man 2 vfork:
9a3fa7
9a3fa7
        "The vfork() function has the same effect as fork(2), except that
9a3fa7
        the behavior is undefined if the process created by vfork() either
9a3fa7
        modifies any data ... or calls any other function before
9a3fa7
        successfully calling _exit(2) or one of the exec(3) family of
9a3fa7
        functions."
9a3fa7
9a3fa7
    Apparently this has not been a problem for us in earlier versions of
9a3fa7
    glibc, maybe because vfork was more like fork, maybe because the
9a3fa7
    stack corruption was innocuous.  Ours is a corner case anyway, as
9a3fa7
    it might not have been a problem had modprobe existed or had
9a3fa7
    modprobe been a symlink to /bin/true.  But it seems odd to disregard
9a3fa7
    man page cautions, and our problem goes away if they are heeded.
9a3fa7
9a3fa7
    Signed-off-by: Florian Westphal <fw@strlen.de>
9a3fa7
9a3fa7
Signed-off-by: Phil Sutter <psutter@redhat.com>
9a3fa7
---
9a3fa7
 libxtables/xtables.c | 16 ++++++----------
9a3fa7
 1 file changed, 6 insertions(+), 10 deletions(-)
9a3fa7
9a3fa7
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
9a3fa7
index cf9a59d5ec095..bca9863acc566 100644
9a3fa7
--- a/libxtables/xtables.c
9a3fa7
+++ b/libxtables/xtables.c
9a3fa7
@@ -352,6 +352,11 @@ int xtables_insmod(const char *modname, const char *modprobe, bool quiet)
9a3fa7
 		modprobe = buf;
9a3fa7
 	}
9a3fa7
 
9a3fa7
+	argv[0] = (char *)modprobe;
9a3fa7
+	argv[1] = (char *)modname;
9a3fa7
+	argv[2] = quiet ? "-q" : NULL;
9a3fa7
+	argv[3] = NULL;
9a3fa7
+
9a3fa7
 	/*
9a3fa7
 	 * Need to flush the buffer, or the child may output it again
9a3fa7
 	 * when switching the program thru execv.
9a3fa7
@@ -360,19 +365,10 @@ int xtables_insmod(const char *modname, const char *modprobe, bool quiet)
9a3fa7
 
9a3fa7
 	switch (vfork()) {
9a3fa7
 	case 0:
9a3fa7
-		argv[0] = (char *)modprobe;
9a3fa7
-		argv[1] = (char *)modname;
9a3fa7
-		if (quiet) {
9a3fa7
-			argv[2] = "-q";
9a3fa7
-			argv[3] = NULL;
9a3fa7
-		} else {
9a3fa7
-			argv[2] = NULL;
9a3fa7
-			argv[3] = NULL;
9a3fa7
-		}
9a3fa7
 		execv(argv[0], argv);
9a3fa7
 
9a3fa7
 		/* not usually reached */
9a3fa7
-		exit(1);
9a3fa7
+		_exit(1);
9a3fa7
 	case -1:
9a3fa7
 		free(buf);
9a3fa7
 		return -1;
9a3fa7
-- 
9a3fa7
2.21.0
9a3fa7