147 lines
6.4 KiB
Diff
147 lines
6.4 KiB
Diff
From dc4d69d6d10cf1748bbdf971cd118db334991697 Mon Sep 17 00:00:00 2001
|
|
From: Kotresh HR <khiremat@redhat.com>
|
|
Date: Sat, 8 Oct 2022 14:56:08 +0800
|
|
Subject: [PATCH] fix CVE-2022-0670
|
|
Fixes the subvolume discover to use the correct
|
|
metadata file after an upgrade from legacy subvolume
|
|
to v1. The fix makes sure, it doesn't use the
|
|
handcrafted metadata file placed in the subvolume
|
|
root of legacy subvolume.
|
|
|
|
Co-authored-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@cern.ch>
|
|
Co-authored-by: Dan van der Ster <daniel.vanderster@cern.ch>
|
|
Co-authored-by: Ramana Raja <rraja@redhat.com>
|
|
Signed-off-by: Kotresh HR <khiremat@redhat.com>
|
|
(cherry picked from commit 7eba9cab6cfb9a13a84062177d7a0fa228311e13)
|
|
(cherry picked from commit f8c04135150a7fb3c43607b43a8214e0d57547bc)
|
|
Signed-off-by: Kotresh HR <khiremat@redhat.com>
|
|
(cherry picked from commit 5bb46ee690591411d4890b613c6380fced9d04b4)
|
|
|
|
---
|
|
.../operations/versions/metadata_manager.py | 17 +++++++++++---
|
|
.../fs/operations/versions/subvolume_base.py | 23 +++++++++++++++++--
|
|
.../fs/operations/versions/subvolume_v1.py | 2 +-
|
|
3 files changed, 36 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py b/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py
|
|
index 1b6c43278..cb3059e56 100644
|
|
--- a/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py
|
|
+++ b/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py
|
|
@@ -40,16 +40,17 @@ class MetadataManager(object):
|
|
def refresh(self):
|
|
fd = None
|
|
conf_data = StringIO()
|
|
+ log.debug("opening config {0}".format(self.config_path))
|
|
try:
|
|
- log.debug("opening config {0}".format(self.config_path))
|
|
fd = self.fs.open(self.config_path, os.O_RDONLY)
|
|
while True:
|
|
data = self.fs.read(fd, -1, MetadataManager.MAX_IO_BYTES)
|
|
if not len(data):
|
|
break
|
|
conf_data.write(data.decode('utf-8'))
|
|
- conf_data.seek(0)
|
|
- self.config.readfp(conf_data)
|
|
+ except UnicodeDecodeError:
|
|
+ raise MetadataMgrException(-errno.EINVAL,
|
|
+ "failed to decode, erroneous metadata config '{0}'".format(self.config_path))
|
|
except cephfs.ObjectNotFound:
|
|
raise MetadataMgrException(-errno.ENOENT, "metadata config '{0}' not found".format(self.config_path))
|
|
except cephfs.Error as e:
|
|
@@ -58,6 +59,16 @@ class MetadataManager(object):
|
|
if fd is not None:
|
|
self.fs.close(fd)
|
|
|
|
+ conf_data.seek(0)
|
|
+ try:
|
|
+ if sys.version_info >= (3, 2):
|
|
+ self.config.read_file(conf_data)
|
|
+ else:
|
|
+ self.config.readfp(conf_data)
|
|
+ except configparser.Error:
|
|
+ raise MetadataMgrException(-errno.EINVAL, "failed to parse, erroneous metadata config "
|
|
+ "'{0}'".format(self.config_path))
|
|
+
|
|
def flush(self):
|
|
# cull empty sections
|
|
for section in list(self.config.sections()):
|
|
diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py
|
|
index 2840a9f2e..0d183e612 100644
|
|
--- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py
|
|
+++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py
|
|
@@ -5,6 +5,7 @@ import errno
|
|
import logging
|
|
from hashlib import md5
|
|
from typing import Dict, Union
|
|
+from pathlib import Path
|
|
|
|
import cephfs
|
|
|
|
@@ -16,6 +17,7 @@ from ...fs_util import get_ancestor_xattr
|
|
from ...exception import MetadataMgrException, VolumeException
|
|
from .op_sm import SubvolumeOpSm
|
|
from .auth_metadata import AuthMetadataManager
|
|
+from .subvolume_attrs import SubvolumeStates
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
@@ -111,7 +113,7 @@ class SubvolumeBase(object):
|
|
@property
|
|
def state(self):
|
|
""" Subvolume state, one of SubvolumeStates """
|
|
- raise NotImplementedError
|
|
+ raise SubvolumeStates.from_value(self.metadata_mgr.get_global_option(MetadataManager.GLOBAL_META_KEY_STATE))
|
|
|
|
@property
|
|
def subvol_type(self):
|
|
@@ -123,6 +125,15 @@ class SubvolumeBase(object):
|
|
raise NotImplementedError
|
|
|
|
def load_config(self):
|
|
+ try:
|
|
+ self.fs.stat(self.legacy_config_path)
|
|
+ self.legacy_mode = True
|
|
+ except cephfs.Error as e:
|
|
+ pass
|
|
+
|
|
+ log.debug("loding config "
|
|
+ "'{0}' [mode: {1}]".format(self.subvolname, "legacy"
|
|
+ if self.legacy_mode else "new"))
|
|
if self.legacy_mode:
|
|
self.metadata_mgr = MetadataManager(self.fs, self.legacy_config_path, 0o640)
|
|
else:
|
|
@@ -271,8 +282,16 @@ class SubvolumeBase(object):
|
|
self.fs.stat(self.base_path)
|
|
self.metadata_mgr.refresh()
|
|
log.debug("loaded subvolume '{0}'".format(self.subvolname))
|
|
+ subvolpath = self.metadata_mgr.get_global_option(MetadataManager.GLOBAL_META_KEY_PATH)
|
|
+ # subvolume with retained snapshots has enpty path, don't mistake it for
|
|
+ # fabricated metadata.
|
|
+ if (not self.legacy_mode and self.state != SubvolumeStates.STATE_RETAINED and
|
|
+ self.base_path.decode('utf-8') !=(Path(subvolpath).parent)):
|
|
+ raise MetadataMgrException(-errno.ENOENT, 'fabricated .meta')
|
|
except MetadataMgrException as me:
|
|
- if me.errno == -errno.ENOENT and not self.legacy_mode:
|
|
+ if me.errno in (-errno.ENOENT, -errno.EINVAL) and not self.legacy_mode:
|
|
+ log.warn("subvolume '{0}', {1}, "
|
|
+ "assuming legacy_mode".format(self.subvolname, me.error_str))
|
|
self.legacy_mode = True
|
|
self.load_config()
|
|
self.discover()
|
|
diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py
|
|
index d62effd99..39f256638 100644
|
|
--- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py
|
|
+++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py
|
|
@@ -666,7 +666,7 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate):
|
|
|
|
@property
|
|
def state(self):
|
|
- return SubvolumeStates.from_value(self.metadata_mgr.get_global_option(MetadataManager.GLOBAL_META_KEY_STATE))
|
|
+ return super(SubvolumeV1, self).state
|
|
|
|
@state.setter
|
|
def state(self, val):
|
|
--
|
|
2.27.0
|
|
|