components/openstack/glance/patches/03-CVE-2014-0162.patch
branchs11-update
changeset 4072 db0cec748ec0
parent 4067 4be1f488dda8
child 4094 78203277f011
equal deleted inserted replaced
4067:4be1f488dda8 4072:db0cec748ec0
     1 This proposed upstream patch addresses CVE-2014-0162 and is tracked
       
     2 under Launchpad bug 1298698. Although it's been addressed in Icehouse
       
     3 2014.1, the patch below is still not yet released for Havana.
       
     4 
       
     5 commit 13069a4017d36a549576a21ca3ec5b15c411effc
       
     6 Author: Zhi Yan Liu <[email protected]>
       
     7 Date:   Sat Mar 29 03:35:35 2014 +0800
       
     8 
       
     9     To prevent remote code injection on Sheepdog store
       
    10     
       
    11     Change-Id: Iae92eaf9eb023f36a1bab7c20ea41c985f2bf51b
       
    12     Signed-off-by: Zhi Yan Liu <[email protected]>
       
    13 
       
    14 diff --git a/glance/store/sheepdog.py b/glance/store/sheepdog.py
       
    15 index d10aea7..2f75441 100644
       
    16 --- a/glance/store/sheepdog.py
       
    17 +++ b/glance/store/sheepdog.py
       
    18 @@ -25,6 +25,7 @@ from glance.common import exception
       
    19  from glance.openstack.common import excutils
       
    20  import glance.openstack.common.log as logging
       
    21  from glance.openstack.common import processutils
       
    22 +from glance.openstack.common import uuidutils
       
    23  import glance.store
       
    24  import glance.store.base
       
    25  import glance.store.location
       
    26 @@ -32,7 +33,7 @@ import glance.store.location
       
    27  
       
    28  LOG = logging.getLogger(__name__)
       
    29  
       
    30 -DEFAULT_ADDR = 'localhost'
       
    31 +DEFAULT_ADDR = '127.0.0.1'
       
    32  DEFAULT_PORT = '7000'
       
    33  DEFAULT_CHUNKSIZE = 64  # in MiB
       
    34  
       
    35 @@ -63,18 +64,14 @@ class SheepdogImage:
       
    36          self.chunk_size = chunk_size
       
    37  
       
    38      def _run_command(self, command, data, *params):
       
    39 -        cmd = ("collie vdi %(command)s -a %(addr)s -p %(port)s %(name)s "
       
    40 -               "%(params)s" %
       
    41 -               {"command": command,
       
    42 -                "addr": self.addr,
       
    43 -                "port": self.port,
       
    44 -                "name": self.name,
       
    45 -                "params": " ".join(map(str, params))})
       
    46 +        cmd = ["collie", "vdi"]
       
    47 +        cmd.extend(command)
       
    48 +        cmd.extend(["-a", self.addr, "-p", self.port, self.name])
       
    49 +        cmd.extend(params)
       
    50  
       
    51          try:
       
    52 -            return processutils.execute(
       
    53 -                cmd, process_input=data, shell=True)[0]
       
    54 -        except processutils.ProcessExecutionError as exc:
       
    55 +            return processutils.execute(*cmd, process_input=data)[0]
       
    56 +        except (processutils.ProcessExecutionError, OSError) as exc:
       
    57              LOG.error(exc)
       
    58              raise glance.store.BackendException(exc)
       
    59  
       
    60 @@ -84,7 +81,7 @@ class SheepdogImage:
       
    61  
       
    62          Sheepdog Usage: collie vdi list -r -a address -p port image
       
    63          """
       
    64 -        out = self._run_command("list -r", None)
       
    65 +        out = self._run_command(["list", "-r"], None)
       
    66          return long(out.split(' ')[3])
       
    67  
       
    68      def read(self, offset, count):
       
    69 @@ -94,7 +91,7 @@ class SheepdogImage:
       
    70  
       
    71          Sheepdog Usage: collie vdi read -a address -p port image offset len
       
    72          """
       
    73 -        return self._run_command("read", None, str(offset), str(count))
       
    74 +        return self._run_command(["read"], None, str(offset), str(count))
       
    75  
       
    76      def write(self, data, offset, count):
       
    77          """
       
    78 @@ -103,7 +100,7 @@ class SheepdogImage:
       
    79  
       
    80          Sheepdog Usage: collie vdi write -a address -p port image offset len
       
    81          """
       
    82 -        self._run_command("write", data, str(offset), str(count))
       
    83 +        self._run_command(["write"], data, str(offset), str(count))
       
    84  
       
    85      def create(self, size):
       
    86          """
       
    87 @@ -111,7 +108,7 @@ class SheepdogImage:
       
    88  
       
    89          Sheepdog Usage: collie vdi create -a address -p port image size
       
    90          """
       
    91 -        self._run_command("create", None, str(size))
       
    92 +        self._run_command(["create"], None, str(size))
       
    93  
       
    94      def delete(self):
       
    95          """
       
    96 @@ -119,7 +116,7 @@ class SheepdogImage:
       
    97  
       
    98          Sheepdog Usage: collie vdi delete -a address -p port image
       
    99          """
       
   100 -        self._run_command("delete", None)
       
   101 +        self._run_command(["delete"], None)
       
   102  
       
   103      def exist(self):
       
   104          """
       
   105 @@ -127,7 +124,7 @@ class SheepdogImage:
       
   106  
       
   107          Sheepdog Usage: collie vdi list -r -a address -p port image
       
   108          """
       
   109 -        out = self._run_command("list -r", None)
       
   110 +        out = self._run_command(["list", "-r"], None)
       
   111          if not out:
       
   112              return False
       
   113          else:
       
   114 @@ -138,7 +135,7 @@ class StoreLocation(glance.store.location.StoreLocation):
       
   115      """
       
   116      Class describing a Sheepdog URI. This is of the form:
       
   117  
       
   118 -        sheepdog://image
       
   119 +        sheepdog://image-id
       
   120  
       
   121      """
       
   122  
       
   123 @@ -149,10 +146,14 @@ class StoreLocation(glance.store.location.StoreLocation):
       
   124          return "sheepdog://%s" % self.image
       
   125  
       
   126      def parse_uri(self, uri):
       
   127 -        if not uri.startswith('sheepdog://'):
       
   128 -            raise exception.BadStoreUri(uri, "URI must start with %s://" %
       
   129 -                                        'sheepdog')
       
   130 -        self.image = uri[11:]
       
   131 +        valid_schema = 'sheepdog://'
       
   132 +        if not uri.startswith(valid_schema):
       
   133 +            raise exception.BadStoreUri(_("URI must start with %s://") %
       
   134 +                                        valid_schema)
       
   135 +        self.image = uri[len(valid_schema):]
       
   136 +        if not uuidutils.is_uuid_like(self.image):
       
   137 +            raise exception.BadStoreUri(_("URI must contains well-formated "
       
   138 +                                          "image id"))
       
   139  
       
   140  
       
   141  class ImageIterator(object):
       
   142 @@ -192,7 +193,7 @@ class Store(glance.store.base.Store):
       
   143  
       
   144          try:
       
   145              self.chunk_size = CONF.sheepdog_store_chunk_size * 1024 * 1024
       
   146 -            self.addr = CONF.sheepdog_store_address
       
   147 +            self.addr = CONF.sheepdog_store_address.strip()
       
   148              self.port = CONF.sheepdog_store_port
       
   149          except cfg.ConfigFileValueError as e:
       
   150              reason = _("Error in store configuration: %s") % e
       
   151 @@ -200,10 +201,18 @@ class Store(glance.store.base.Store):
       
   152              raise exception.BadStoreConfiguration(store_name='sheepdog',
       
   153                                                    reason=reason)
       
   154  
       
   155 +        if ' ' in self.addr:
       
   156 +            reason = (_("Invalid address configuration of sheepdog store: %s")
       
   157 +                      % self.addr)
       
   158 +            LOG.error(reason)
       
   159 +            raise exception.BadStoreConfiguration(store_name='sheepdog',
       
   160 +                                                  reason=reason)
       
   161 +
       
   162          try:
       
   163 -            processutils.execute("collie", shell=True)
       
   164 -        except processutils.ProcessExecutionError as exc:
       
   165 -            reason = _("Error in store configuration: %s") % exc
       
   166 +            cmd = ["collie", "vdi", "list", "-a", self.addr, "-p", self.port]
       
   167 +            processutils.execute(*cmd)
       
   168 +        except Exception as e:
       
   169 +            reason = _("Error in store configuration: %s") % e
       
   170              LOG.error(reason)
       
   171              raise exception.BadStoreConfiguration(store_name='sheepdog',
       
   172                                                    reason=reason)
       
   173 diff --git a/glance/tests/unit/test_sheepdog_store.py b/glance/tests/unit/test_sheepdog_store.py
       
   174 index 8eef86b..bea7e29 100644
       
   175 --- a/glance/tests/unit/test_sheepdog_store.py
       
   176 +++ b/glance/tests/unit/test_sheepdog_store.py
       
   177 @@ -57,4 +57,5 @@ class TestStore(base.StoreClearingUnitTest):
       
   178                            'fake_image_id',
       
   179                            utils.LimitingReader(StringIO.StringIO('xx'), 1),
       
   180                            2)
       
   181 -        self.assertEqual(called_commands, ['list -r', 'create', 'delete'])
       
   182 +        self.assertEqual([['list', '-r'], ['create'], ['delete']],
       
   183 +                         called_commands)
       
   184 diff --git a/glance/tests/unit/test_store_location.py b/glance/tests/unit/test_store_location.py
       
   185 index 7eec171..2464ebb 100644
       
   186 --- a/glance/tests/unit/test_store_location.py
       
   187 +++ b/glance/tests/unit/test_store_location.py
       
   188 @@ -52,7 +52,7 @@ class TestStoreLocation(base.StoreClearingUnitTest):
       
   189              'rbd://imagename',
       
   190              'rbd://fsid/pool/image/snap',
       
   191              'rbd://%2F/%2F/%2F/%2F',
       
   192 -            'sheepdog://imagename',
       
   193 +            'sheepdog://244e75f1-9c69-4167-9db7-1aa7d1973f6c',
       
   194              'cinder://12345678-9012-3455-6789-012345678901',
       
   195          ]
       
   196  
       
   197 @@ -367,15 +367,18 @@ class TestStoreLocation(base.StoreClearingUnitTest):
       
   198          """
       
   199          Test the specific StoreLocation for the Sheepdog store
       
   200          """
       
   201 -        uri = 'sheepdog://imagename'
       
   202 +        uri = 'sheepdog://244e75f1-9c69-4167-9db7-1aa7d1973f6c'
       
   203          loc = glance.store.sheepdog.StoreLocation({})
       
   204          loc.parse_uri(uri)
       
   205 -        self.assertEqual('imagename', loc.image)
       
   206 +        self.assertEqual('244e75f1-9c69-4167-9db7-1aa7d1973f6c', loc.image)
       
   207  
       
   208 -        bad_uri = 'sheepdog:/image'
       
   209 +        bad_uri = 'sheepdog:/244e75f1-9c69-4167-9db7-1aa7d1973f6c'
       
   210          self.assertRaises(exception.BadStoreUri, loc.parse_uri, bad_uri)
       
   211  
       
   212 -        bad_uri = 'http://image'
       
   213 +        bad_uri = 'http://244e75f1-9c69-4167-9db7-1aa7d1973f6c'
       
   214 +        self.assertRaises(exception.BadStoreUri, loc.parse_uri, bad_uri)
       
   215 +
       
   216 +        bad_uri = 'image; name'
       
   217          self.assertRaises(exception.BadStoreUri, loc.parse_uri, bad_uri)
       
   218  
       
   219      def test_cinder_store_good_location(self):