[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#805024: marked as done (jessie-pu: package glance/2014.1.3-12 (CVE-2015-5251))



Your message dated Sat, 23 Jan 2016 13:57:15 +0000
with message-id <1453557435.1835.52.camel@adam-barratt.org.uk>
and subject line 8.3 point release cleanup
has caused the Debian Bug report #805024,
regarding jessie-pu: package glance/2014.1.3-12 (CVE-2015-5251)
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
805024: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=805024
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: jessie
User: release.debian.org@packages.debian.org
Usertags: pu

Dear release team,

I've prepared an update for Glance CVE-2015-5251. The debdiff is attached.
The resulting binaries may be found here:
http://sid.gplhost.com/jessie-proposed-updates/glance/

Please authorize me to upload this to jessie-proposed-updates.

Cheers,

Thomas Goirand (zigo)
diff -Nru glance-2014.1.3/debian/changelog glance-2014.1.3/debian/changelog
--- glance-2014.1.3/debian/changelog	2015-01-29 15:22:59.000000000 +0000
+++ glance-2014.1.3/debian/changelog	2015-11-13 13:30:43.000000000 +0000
@@ -1,3 +1,10 @@
+glance (2014.1.3-12+deb8u1) jessie-proposed-updates; urgency=medium
+
+  * CVE-2015-5251: Glance image status manipulation. Applied upstream patch
+    after rebasing it from Juno to Icehouse (Closes: #799931).
+
+ -- Thomas Goirand <zigo@debian.org>  Fri, 13 Nov 2015 14:22:12 +0100
+
 glance (2014.1.3-12) unstable; urgency=high
 
   * CVE-2014-9623: Glance user storage quota bypass. Applied upstream patch:
diff -Nru glance-2014.1.3/debian/patches/CVE-2015-5251_Prevent_image_status_being_directly_modified_via_v1.patch glance-2014.1.3/debian/patches/CVE-2015-5251_Prevent_image_status_being_directly_modified_via_v1.patch
--- glance-2014.1.3/debian/patches/CVE-2015-5251_Prevent_image_status_being_directly_modified_via_v1.patch	1970-01-01 00:00:00.000000000 +0000
+++ glance-2014.1.3/debian/patches/CVE-2015-5251_Prevent_image_status_being_directly_modified_via_v1.patch	2015-11-13 13:30:43.000000000 +0000
@@ -0,0 +1,171 @@
+Description: Prevent image status being directly modified via v1
+ Users shouldn't be able to change an image's status directly via the v1 API.
+ .
+ Some existing consumers of Glance set the x-image-meta-status header in
+ requests to the Glance API, eg:
+ .
+  https://github.com/openstack/nova/blob/master/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance#L184
+ .
+ We should try to prevent users setting 'status' via v1, but without breaking
+ existing benign API calls such as these.
+ .
+ I've adopted the following approach (which has some prior art in 'protected properties').
+ .
+ If a PUT request is received which contains an x-image-meta-status header:
+ .
+  * The user provided status is ignored if it matches the current image
+    status (this prevents benign calls such as the nova one above from
+    breaking). The usual code (eg 200) will be returned.
+ .
+  * If the user provided status doesn't match the current image status (ie
+    there is a real attempt to change the value) 403 will be returned. This
+    will break any calls which currently intentionally change the status.
+Author: Stuart McLaren <stuart.mclaren@hp.com>
+Date: Tue, 11 Aug 2015 10:37:09 +0000 (+0000)
+X-Git-Url: https://review.openstack.org/gitweb?p=openstack%2Fglance.git;a=commitdiff_plain;h=45be8e1c620c50f3cbca76f561945200a8843bc8
+Bug-Ubuntu: https://bugs.launchpad.net/glance/+bug/1482371
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=799931
+Change-Id: I44fadf32abb57c962b67467091c3f51c1ccc25e6
+Origin: upstream, https://review.openstack.org/#/c/226338/
+Last-Update: 2015-10-13
+
+--- glance-2014.1.3.orig/glance/api/v1/__init__.py
++++ glance-2014.1.3/glance/api/v1/__init__.py
+@@ -21,3 +21,6 @@ SUPPORTED_PARAMS = ('limit', 'marker', '
+ 
+ # Metadata which only an admin can change once the image is active
+ ACTIVE_IMMUTABLE = ('size', 'checksum')
++
++# Metadata which cannot be changed (irrespective of the current image state)
++IMMUTABLE = ('status',)
+--- glance-2014.1.3.orig/glance/api/v1/images.py
++++ glance-2014.1.3/glance/api/v1/images.py
+@@ -53,6 +53,7 @@ LOG = logging.getLogger(__name__)
+ SUPPORTED_PARAMS = glance.api.v1.SUPPORTED_PARAMS
+ SUPPORTED_FILTERS = glance.api.v1.SUPPORTED_FILTERS
+ ACTIVE_IMMUTABLE = glance.api.v1.ACTIVE_IMMUTABLE
++IMMUTABLE = glance.api.v1.IMMUTABLE
+ 
+ CONF = cfg.CONF
+ CONF.import_opt('disk_formats', 'glance.common.config', group='image_format')
+@@ -843,6 +844,14 @@ class Controller(controller.BaseControll
+                                         request=req,
+                                         content_type="text/plain")
+ 
++        for key in IMMUTABLE:
++            if (image_meta.get(key) is not None and
++                    image_meta.get(key) != orig_image_meta.get(key)):
++                msg = _("Forbidden to modify '%s' of image.") % key
++                raise HTTPForbidden(explanation=msg,
++                                    request=req,
++                                    content_type="text/plain")
++
+         # The default behaviour for a PUT /images/<IMAGE_ID> is to
+         # override any properties that were previously set. This, however,
+         # leads to a number of issues for the common use case where a caller
+--- glance-2014.1.3.orig/glance/tests/functional/v1/test_api.py
++++ glance-2014.1.3/glance/tests/functional/v1/test_api.py
+@@ -550,3 +550,92 @@ class TestApi(functional.FunctionalTest)
+         self.assertEqual(len(images), 0)
+ 
+         self.stop_servers()
++
++    def test_status_cannot_be_manipulated_directly(self):
++        self.cleanup()
++        self.start_servers(**self.__dict__.copy())
++        headers = minimal_headers('Image1')
++
++        # Create a 'queued' image
++        http = httplib2.Http()
++        headers = {'Content-Type': 'application/octet-stream',
++                   'X-Image-Meta-Disk-Format': 'raw',
++                   'X-Image-Meta-Container-Format': 'bare'}
++        path = "http://%s:%d/v1/images"; % ("127.0.0.1", self.api_port)
++        response, content = http.request(path, 'POST', headers=headers,
++                                         body=None)
++        self.assertEqual(201, response.status)
++        image = jsonutils.loads(content)['image']
++        self.assertEqual('queued', image['status'])
++
++        # Ensure status of 'queued' image can't be changed
++        path = "http://%s:%d/v1/images/%s"; % ("127.0.0.1", self.api_port,
++                                              image['id'])
++        http = httplib2.Http()
++        headers = {'X-Image-Meta-Status': 'active'}
++        response, content = http.request(path, 'PUT', headers=headers)
++        self.assertEqual(403, response.status)
++        response, content = http.request(path, 'HEAD')
++        self.assertEqual(200, response.status)
++        self.assertEqual('queued', response['x-image-meta-status'])
++
++        # We allow 'setting' to the same status
++        http = httplib2.Http()
++        headers = {'X-Image-Meta-Status': 'queued'}
++        response, content = http.request(path, 'PUT', headers=headers)
++        self.assertEqual(200, response.status)
++        response, content = http.request(path, 'HEAD')
++        self.assertEqual(200, response.status)
++        self.assertEqual('queued', response['x-image-meta-status'])
++
++        # Make image active
++        http = httplib2.Http()
++        headers = {'Content-Type': 'application/octet-stream'}
++        response, content = http.request(path, 'PUT', headers=headers,
++                                         body='data')
++        self.assertEqual(200, response.status)
++        image = jsonutils.loads(content)['image']
++        self.assertEqual('active', image['status'])
++
++        # Ensure status of 'active' image can't be changed
++        http = httplib2.Http()
++        headers = {'X-Image-Meta-Status': 'queued'}
++        response, content = http.request(path, 'PUT', headers=headers)
++        self.assertEqual(403, response.status)
++        response, content = http.request(path, 'HEAD')
++        self.assertEqual(200, response.status)
++        self.assertEqual('active', response['x-image-meta-status'])
++
++        # We allow 'setting' to the same status
++        http = httplib2.Http()
++        headers = {'X-Image-Meta-Status': 'active'}
++        response, content = http.request(path, 'PUT', headers=headers)
++        self.assertEqual(200, response.status)
++        response, content = http.request(path, 'HEAD')
++        self.assertEqual(200, response.status)
++        self.assertEqual('active', response['x-image-meta-status'])
++
++        # Create a 'queued' image, ensure 'status' header is ignored
++        http = httplib2.Http()
++        path = "http://%s:%d/v1/images"; % ("127.0.0.1", self.api_port)
++        headers = {'Content-Type': 'application/octet-stream',
++                   'X-Image-Meta-Status': 'active'}
++        response, content = http.request(path, 'POST', headers=headers,
++                                         body=None)
++        self.assertEqual(201, response.status)
++        image = jsonutils.loads(content)['image']
++        self.assertEqual('queued', image['status'])
++
++        # Create an 'active' image, ensure 'status' header is ignored
++        http = httplib2.Http()
++        path = "http://%s:%d/v1/images"; % ("127.0.0.1", self.api_port)
++        headers = {'Content-Type': 'application/octet-stream',
++                   'X-Image-Meta-Disk-Format': 'raw',
++                   'X-Image-Meta-Status': 'queued',
++                   'X-Image-Meta-Container-Format': 'bare'}
++        response, content = http.request(path, 'POST', headers=headers,
++                                         body='data')
++        self.assertEqual(201, response.status)
++        image = jsonutils.loads(content)['image']
++        self.assertEqual('active', image['status'])
++        self.stop_servers()
+--- glance-2014.1.3.orig/glance/tests/integration/legacy_functional/test_v1_api.py
++++ glance-2014.1.3/glance/tests/integration/legacy_functional/test_v1_api.py
+@@ -357,6 +357,8 @@ class TestApi(base.ApiTest):
+         path = "/v1/images"
+         response, content = self.http.request(path, 'POST', headers=headers)
+         self.assertEqual(response.status, 201)
++        image = jsonutils.loads(content)['image']
++        self.assertEqual('active', image['status'])
+ 
+         # 2. HEAD image-location
+         # Verify image size is zero and the status is active
diff -Nru glance-2014.1.3/debian/patches/series glance-2014.1.3/debian/patches/series
--- glance-2014.1.3/debian/patches/series	2015-01-29 15:22:59.000000000 +0000
+++ glance-2014.1.3/debian/patches/series	2015-11-13 13:30:43.000000000 +0000
@@ -4,3 +4,4 @@
 restrict_client_download_and_delete_files_in_glance-api.patch
 CVE-2015-1195_Prevent_file_swift_config_and_filesystem_schemes.patch
 CVE-2014-9623_Cleanup_chunks_for_deleted_image_that_was_saving_icehouse.patch
+CVE-2015-5251_Prevent_image_status_being_directly_modified_via_v1.patch

--- End Message ---
--- Begin Message ---
Version: 8.3

Hi,

The updates referred to in these bugs were included in today's 8.3
Jessie point release.

Regards,

Adam

--- End Message ---

Reply to: