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