ceph/0009-fix-CVE-2022-0670.patch
2022-11-15 10:51:40 +08:00

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