Open viniarck opened 2 years ago
@viniarck I'm very glad you found this! I've pushed commit fe44385 to fix the issues on PR #175 as a workaround for this. In the future, we can also leverage MongoDB direct queries and maybe even remove the self.circuits
local copy. Looking into mef_eline remain code, I couldn't find other places where this vulnerability is present (except circuit_scheduler, which is also referred as part of the evc.as_dict()
call):
> egrep "for .*self\..*" * -R
main.py: for circuit in tuple(self.circuits.values()):
main.py: for circuit in tuple(self.circuits.values()):
main.py: for evc in self.circuits.copy().values():
main.py: for evc in self.circuits.copy().values():
models/evc.py: for attribute in self.required_attributes:
models/evc.py: sc.as_dict() for sc in self.circuit_scheduler
models/evc.py: for dpid, flows in self._prepare_nni_flows(path).items():
models/evc.py: for dpid, flows in self._prepare_uni_flows(path, skip_in=True).items():
models/evc.py: for use_path in self.discover_new_paths():
models/evc.py: for use_path in self.get_failover_path_candidates():
models/evc.py: for incoming, outcoming in self.links_zipped(path):
models/evc.py: for dpid, flows in self._prepare_nni_flows(path).items():
models/evc.py: for link, trace1, trace2 in zip(self.current_path,
Please let me know if you wanna leave the issue open for handling this remaining code or even refactor to leverage MongoDB.
: for dpid, flows in self._prepare_nni_flows(path).items(): models/evc.py: for dpid, flows in self._prepare_uni_flows(path, skip_in=True).items(): models/evc.py: for use_path in self.discover_new_paths(): models/evc.py: for use_path in self.get_failover_path_candidates(): models/evc.py: for incoming, outcoming in self.links_zipped(path): models/evc.py: for dpid, flows in self._prepare_nni_flows(path).items(): models/evc.py: for link, trace1, trace2 in zip(self.current_path,
@italovalcy, sounds good, I agree, shallow copy should be good for now, and then in a next opportunity try to offload more things to MongoDB. It's up to you if you'd rather use this issue for this future opportunity on MongoDB or map a new one. I also didn't find any other points than the ones you've posted here, on models/evc.py several points is passign the same ref but it's not getting inserted again from what I followed, so, it seems safe. Thanks for patching this.
It turns out that
self.circuits
is also vulnerable toRuntimeError: dictionary changed size
, see this https://github.com/kytos-ng/mef_eline/pull/175#discussion_r943970302 for more info. There are more points in the code where this can happen, I'll point them out later for completeness.To facilitate to reproduce the issue:
time.sleep
on parts of the code whereself.circuits
is being iterated on without any locks or shallow copy, and then you have to force an insertion by creating a new circuit just so the iterated collection would change its size, for instance if you add thistime.sleep
:"handle_link_down before sleep..."
after you simulate a link down, if you try to create a new circuit you should get the traceback: