summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
authorRobert Navarro <crshman@gmail.com>2026-06-18 19:13:04 -0700
committerRobert Navarro <crshman@gmail.com>2026-06-23 21:49:41 -0700
commit368b0468bf4f1eaac8e0b61d0790206048eeb79a (patch)
treec202480d379046f19adb6736d6791f182295d3e7 /src/conf_mode
parente0114625c08a2a9826822958f53724995580716d (diff)
downloadvyos-1x-368b0468bf4f1eaac8e0b61d0790206048eeb79a.tar.gz
vyos-1x-368b0468bf4f1eaac8e0b61d0790206048eeb79a.zip
ipsec: T8975: lock vti-up-down state DB to prevent lost updates under concurrent rekey
The vti-up-down hook and vpn_ipsec.py modify a flat-file DB (/tmp/ipsec_vti_interfaces) through three context managers that do an unlocked read-modify-write. During a coordinated rekey, strongSwan fires the hook for many VTIs concurrently, so the writers lost-update each other: an interface whose up-client add is overwritten is left admin-down while its CHILD_SA stays installed. Serialise all DB access by reusing vyos.utils.locking.Lock. A new _vti_updown_db_lock() context manager wraps the three public context managers, and remove_vti_updown_db() holds the lock across both the DB processing and the os.unlink() to close the create/delete race. Make the helpers absence-safe under the lock so callers no longer compose a separate existence check with a locked operation: open_vti_updown_db_readonly() yields None when the DB does not exist and remove_vti_updown_db() is a no-op when it is absent. Drop the now-redundant unlocked vti_updown_db_exists() pre-checks in vti.py and vpn_ipsec.py and handle the None yield.
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py6
1 files changed, 2 insertions, 4 deletions
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
index 78d5cbe83..be8eeca13 100755
--- a/src/conf_mode/vpn_ipsec.py
+++ b/src/conf_mode/vpn_ipsec.py
@@ -50,7 +50,6 @@ from vyos.utils.network import interface_exists
from vyos.utils.dict import dict_search
from vyos.utils.dict import dict_search_args
from vyos.utils.process import call
-from vyos.utils.vti_updown_db import vti_updown_db_exists
from vyos.utils.vti_updown_db import open_vti_updown_db_for_create_or_update
from vyos.utils.vti_updown_db import remove_vti_updown_db
from vyos import ConfigError
@@ -900,8 +899,7 @@ def apply(ipsec):
systemd_service = 'strongswan.service'
if not ipsec or 'deleted' in ipsec:
call(f'systemctl stop {systemd_service}')
- if vti_updown_db_exists():
- remove_vti_updown_db()
+ remove_vti_updown_db()
else:
call(f'systemctl reload-or-restart {systemd_service}')
if ipsec['enabled_vti_interfaces']:
@@ -909,7 +907,7 @@ def apply(ipsec):
db.removeAllOtherInterfaces(ipsec['enabled_vti_interfaces'])
db.setPersistentInterfaces(ipsec['persistent_vti_interfaces'])
db.commit(lambda interface: ipsec['vti_interface_dicts'][interface])
- elif vti_updown_db_exists():
+ else:
remove_vti_updown_db()
if ipsec:
if ipsec.get('nhrp_exists', False):