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

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