ldx / python-iptables

Python bindings for iptables
730 stars 183 forks source link

Segmentation fault occure when rule.create_target() is called when using table._cache() #247

Closed hetii closed 4 years ago

hetii commented 6 years ago

Hello I test such code:

import iptc

def case_1():
    print("Stage 1:")
    table = iptc.Table('nat')
    table.refresh()
    chain = iptc.Chain(table, "PREROUTING")
    # close table *nat* and coresponding socets.
    table.close()

    print("Stage 2:")
    # Notice - I get here a *filter* table not *nat*
    table = iptc.Table("filter")
    #table._cache.clear()  # Without this error occure in rule.create_target # ----\
    table.refresh()                                                          #     |
    chain = iptc.Chain(table, "FORWARD")                                     #     |
    rule = iptc.Rule(chain=chain)                                            #     |
    print("So far, so good...")                                              #     |
    rule.create_target("ACCEPT") # <--- Here segmentation fault occure!!! <--------/
    print("End...")

if __name__ == '__main__':
    print("IPTC version: %s" % iptc.version.__version__)
    case_1()

The result is:

IPTC version: 0.13.0
Stage 1:
Stage 2:
So far, so good...
segmentation fault (core dumped)

But when use table._cache.clear() all is fine:

IPTC version: 0.13.0
Stage 1:
Stage 2:
So far, so good...
End...

@ldx General I notice that internal _cache() produce a lot issues. Could you explain what is a purpose of it? Why not simply close table after each transaction and reopen it when needed?

P.S. I also notice that removing table that is closed from cache, also solve the problem, so maybe it should be default behavior?

table.close()
table._cache.pop(table.name)

or

class Table(iptc.Table):
    def _free(self, *args, **kwargs):
        if self.name in self._cache:
            # print("Remove from cache: %s" % self.name)
            self._cache.pop(self.name)
        super(Table, self)._free(*args, **kwargs)
ldx commented 4 years ago

@hetii you can remove table.close() from case1(), that will fix the issue.