|
|
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 |
|