Bug 295611 - iptables setup broken with non-modular kernels
Summary: iptables setup broken with non-modular kernels
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: iptables
Version: 8
Hardware: All
OS: Linux
low
high
Target Milestone: ---
Assignee: Thomas Woerner
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2007-09-19 00:55 UTC by Linus Torvalds
Modified: 2007-11-30 22:12 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2007-09-24 16:11:05 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)
Suggested fix to /etc/init.d/iptables script (902 bytes, patch)
2007-09-22 19:16 UTC, Linus Torvalds
no flags Details | Diff
Init script patch (4.42 KB, patch)
2007-09-24 12:18 UTC, Thomas Woerner
no flags Details | Diff
An even simpler patch that seems to match what the bahaviour should be.. (420 bytes, patch)
2007-09-24 16:49 UTC, Linus Torvalds
no flags Details | Diff

Description Linus Torvalds 2007-09-19 00:55:44 UTC
Description of problem:

The new init.d/iptables script is totally confused by a kernel with the iptables
support compiled in (or by an early loading of the modules).

The reason? The "start" case will decide that iptables has already been set up,
and doesn't bother doing it again.

Version-Release number of selected component (if applicable):

iptables-1.3.8-2.1.fc8


How reproducible:

100% reproducible.

Steps to Reproduce:
1. Compile a kernel with the necessary filtering modules compiled in, or
   load the modules by hand in single-user mode
2. Go into multi-user mode, which runs "/etc/rc.d/rc5.d/S26iptables start"
3. Notice how no iptables has been set up!
  
Actual results:
Empty iptables - with the associated security issues

Expected results:
Properly set up firewall

Additional info:
This worked before, including in Fedora 7

In Fedora7, the iptables "start)" case looks like this:

    start)
        stop
        start
        RETVAL=$?
        ;;

but in Fedora8-test2 it now looks like this:

    start)
        [ $running -eq 0 ] && exit 0
        start
        RETVAL=$?
        ;;

and the "$running" has been set by the return value of "status", which will be a
success if there is already a table listed in PROC_IPTABLES_NAMES due to the
modules being compiled in.

I realize that this only happens when people compile their own kernels, but it's
still a major security hole. When iptables starts, it should fill in the
firewall, not decide to do nothing.

You can "fix" it by running "S26iptables restart", which will avoid the buggy
test for "the firewall already exists".

BTW, I think Fedora 7 was a *lot* safer in starting iptables *before* it started
networking. The move from S08 -> S26 seems to be a recipe for security disasters.

Comment 1 Thomas Woerner 2007-09-19 17:17:30 UTC
The init-script is S08 again. There was a wrong requirement to local_fs in the
lsb header.

Comment 2 Linus Torvalds 2007-09-22 19:15:08 UTC
Thanks, the S08->S26 switch was fixed in iptables-1.3.8-3.fc8,
but the basic problem with the lack of actual setup still remains.

You should be able to reproduce this even on a modular kernel by
just setting IPTABLES_MODULES_UNLOAD to "no" instead of "yes",
and then doing

         S08iptables stop
         S08iptables start

because now the "start" will incorrectly think that the firewall is
already set up, so it will not set the firewall up!

NOTE! This is *different* from

          S08iptables restart

which will work fine, because "restart" will do an unconditional start,
it's just plain "start" that is broken, because it has a totally wrong
check for whether the firewall is actually up and running or not!

I'll attach a suggested patch to this bugzilla entry (I only did it for
the iptables script, but ip6tables has the same bug).

Comment 3 Linus Torvalds 2007-09-22 19:16:57 UTC
Created attachment 203201 [details]
Suggested fix to /etc/init.d/iptables script

Here's a patch that looks sane, and I verified that it fixes
the problem for me.

Comment 4 Thomas Woerner 2007-09-24 12:18:34 UTC
Created attachment 204061 [details]
Init script patch

Hello Linus,
please have a look at the attached patch and test if it is working for you.
Thanks, Thomas

Comment 5 Linus Torvalds 2007-09-24 15:13:54 UTC
This makes it work for me, but I wonder why you selected the much more
complex and broken patch that still seems to think that "modules loaded"
has something to do with whether the firewall rules have been set up or
not?

But the fact that you then add special tests for "if it's compiled in,
don't bother with the idiotic tests" at least makes it *work*. But why
do those incorrect tests in the first place? What does "modules loaded"
have to do with anything, really?

But yes, my particular bug is fixed. 

The ip6tables script needs the same loving attention.

Comment 6 Thomas Woerner 2007-09-24 16:11:05 UTC
The "idiotic tests" are needed to be able to start and stop the firewall if it
was not configured with the init script. "iptables -L" loads the netfilter
modules and is often used to check if there is a firewall active.
The expected behaviour of "service iptables stop" is to stop the firewall, even
if only "iptables -L" was used. "service iptables start" should start the
firewall, even if there was a "iptables -L" call before. Your patch did not work
with this.

BTW: The ip6tables script is generated out of the iptables script.

Fixed in rawhide in package iptables-1.3.8-4 or newer.

Comment 7 Linus Torvalds 2007-09-24 16:41:15 UTC
If so, the real problem is that you're trying to re-use the same test
for two *totally* different things.

You seem to think that both "stop" and "start" should use the same
"running" test, but then you say that they have two totally different
behaviors. No wonder the script is broken.

So on "start" you should *only* check whether it was already running,
i.e. whether the lockfile exists. It does not matter whether the firewall
was active or not. 

But you're also saying that "stop" should do something even if it was
*not* running. See? You're trying to use the same "$running" for both
cases, and all the trouble seems to come from that basic mistake. So
why do it?

So I'll attach an even simpler patch that actually matches what you seem
to say that the behaviour should be.

Comment 8 Linus Torvalds 2007-09-24 16:49:06 UTC
Created attachment 204311 [details]
An even simpler patch that seems to match what the bahaviour should be..

So why not something like this instead?

This just says:
 - start (and "try-restart") should *only* happen when the lock-file doesn't
   exist (ie it isn't already running). It has nothing to do with whether
   modules are loaded or not, or indeed anything else.
 - stop should stop the firewall and unload the modules if they are there,
   and that in turn has nothing to do with whether the lock-file exists or
   not.

In other words, you cannot - and must not - try to use the same logic (just
reversed) for the two cases, since the two simply aren't mirror images!

Trying to use the same (reversed) test is what caused problems, and is what
made "compiled in" vs "modular" appear to be different. But they aren't
really different at all, what is different is that "start" and "stop" are
simply not mirror events according to you!

I don't really care, since your patch did work for me, but it seems much too
complex and fragile.

Btw, the older Fedora scripts worked fine, and they were even simpler, since
"start" just always did a restart, and "stop" just did a stop - with no
conditionals at all. I'm not sure why that was so bad either, and was changed
in the first place?

Comment 9 Thomas Woerner 2007-09-26 16:28:08 UTC
Fixed in rawhide in package iptables-1.3.8-4.1 or newer.

Thanks for the simple solution :-)


Note You need to log in before you can comment on or make changes to this bug.