Hello community,
here is the log from the commit of package docker-distribution for
openSUSE:Factory checked in at 2017-07-23 12:14:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/docker-distribution (Old)
and /work/SRC/openSUSE:Factory/.docker-distribution.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "docker-distribution"
Sun Jul 23 12:14:07 2017 rev:14 rq:511821 version:2.6.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/docker-distribution/docker-distribution.changes
2017-06-13 16:10:15.724440159 +0200
+++
/work/SRC/openSUSE:Factory/.docker-distribution.new/docker-distribution.changes
2017-07-23 12:14:13.941164481 +0200
@@ -1,0 +2,16 @@
+Fri Jul 21 10:48:11 UTC 2017 - [email protected]
+
+- Updated to 2.6.2
+
+This release is a special security release to address an issue allowing
+an attacker to force arbitrarily-sized memory allocations in a registry
+instance through the manifest endpoint. The problem has been mitigated
+by limiting the size of reads for image manifest content.
+
+Details for mitigation are in 29fa466
+
+CVE-2017-11468 has been assigned for this issue.
+
+Fixes bsc#1049850
+
+-------------------------------------------------------------------
Old:
----
distribution-2.6.1.tar.xz
New:
----
distribution-2.6.2.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ docker-distribution.spec ++++++
--- /var/tmp/diff_new_pack.UxFRxd/_old 2017-07-23 12:14:14.561076914 +0200
+++ /var/tmp/diff_new_pack.UxFRxd/_new 2017-07-23 12:14:14.561076914 +0200
@@ -17,7 +17,7 @@
Name: docker-distribution
-Version: 2.6.1
+Version: 2.6.2
Release: 0
Summary: The Docker toolset to pack, ship, store, and deliver content
License: Apache-2.0
++++++ _service ++++++
--- /var/tmp/diff_new_pack.UxFRxd/_old 2017-07-23 12:14:14.609070135 +0200
+++ /var/tmp/diff_new_pack.UxFRxd/_new 2017-07-23 12:14:14.609070135 +0200
@@ -3,8 +3,8 @@
<param name="url">https://github.com/docker/distribution.git</param>
<param name="scm">git</param>
<param name="exclude">.git</param>
- <param name="versionformat">2.6.1</param>
- <param name="revision">v2.6.1</param>
+ <param name="versionformat">2.6.2</param>
+ <param name="revision">v2.6.2</param>
</service>
<service name="recompress" mode="disabled">
<param name="file">distribution-*.tar</param>
++++++ distribution-2.6.1.tar.xz -> distribution-2.6.2.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.1/.mailmap
new/distribution-2.6.2/.mailmap
--- old/distribution-2.6.1/.mailmap 2017-04-06 01:18:07.000000000 +0200
+++ new/distribution-2.6.2/.mailmap 2017-07-20 23:12:45.000000000 +0200
@@ -16,3 +16,4 @@
Omer Cohen <[email protected]> Omer Cohen <[email protected]>
Eric Yang <[email protected]> Eric Yang <[email protected]>
Nikita Tarasov <[email protected]> Nikita <[email protected]>
+Misty Stanley-Jones <[email protected]> Misty Stanley-Jones <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.1/AUTHORS
new/distribution-2.6.2/AUTHORS
--- old/distribution-2.6.1/AUTHORS 2017-04-06 01:18:07.000000000 +0200
+++ new/distribution-2.6.2/AUTHORS 2017-07-20 23:12:45.000000000 +0200
@@ -1,4 +1,3 @@
-a-palchikov <[email protected]>
Aaron Lehmann <[email protected]>
Aaron Schlesinger <[email protected]>
Aaron Vinson <[email protected]>
@@ -18,10 +17,11 @@
Andrey Kostov <[email protected]>
Andy Goldstein <[email protected]>
Anis Elleuch <[email protected]>
-Anton Tiurin <[email protected]>
Antonio Mercado <[email protected]>
Antonio Murdaca <[email protected]>
+Anton Tiurin <[email protected]>
Anusha Ragunathan <[email protected]>
+a-palchikov <[email protected]>
Arien Holthuizen <[email protected]>
Arnaud Porterie <[email protected]>
Arthur Baars <[email protected]>
@@ -46,9 +46,9 @@
Dave Trombley <[email protected]>
Dave Tucker <[email protected]>
David Lawrence <[email protected]>
+davidli <[email protected]>
David Verhasselt <[email protected]>
David Xia <[email protected]>
-davidli <[email protected]>
Dejan Golja <[email protected]>
Derek McGowan <[email protected]>
Diogo Mónica <[email protected]>
@@ -68,8 +68,8 @@
Gleb Schukin <[email protected]>
harche <[email protected]>
Henri Gomez <[email protected]>
-Hu Keping <[email protected]>
Hua Wang <[email protected]>
+Hu Keping <[email protected]>
HuKeping <[email protected]>
Ian Babrou <[email protected]>
igayoso <[email protected]>
@@ -86,21 +86,21 @@
Joao Fernandes <[email protected]>
John Mulhausen <[email protected]>
John Starks <[email protected]>
+Jonathan Boulle <[email protected]>
Jon Johnson <[email protected]>
Jon Poler <[email protected]>
-Jonathan Boulle <[email protected]>
Jordan Liggitt <[email protected]>
Josh Chorlton <[email protected]>
Josh Hawn <[email protected]>
Julien Fernandez <[email protected]>
-Ke Xu <[email protected]>
Keerthan Mala <[email protected]>
Kelsey Hightower <[email protected]>
Kenneth Lim <[email protected]>
Kenny Leung <[email protected]>
-Li Yi <[email protected]>
-Liu Hua <[email protected]>
+Ke Xu <[email protected]>
liuchang0812 <[email protected]>
+Liu Hua <[email protected]>
+Li Yi <[email protected]>
Lloyd Ramey <[email protected]>
Louis Kottmann <[email protected]>
Luke Carpenter <[email protected]>
@@ -108,15 +108,14 @@
Mary Anthony <[email protected]>
Matt Bentley <[email protected]>
Matt Duch <[email protected]>
+Matthew Green <[email protected]>
Matt Moore <[email protected]>
Matt Robenolt <[email protected]>
-Matthew Green <[email protected]>
Michael Prokop <[email protected]>
Michal Minar <[email protected]>
Michal Minář <[email protected]>
Mike Brown <[email protected]>
Miquel Sabaté <[email protected]>
-Misty Stanley-Jones <[email protected]>
Misty Stanley-Jones <[email protected]>
Morgan Bauer <[email protected]>
moxiegirl <[email protected]>
@@ -165,17 +164,18 @@
Tony Holdstock-Brown <[email protected]>
Trevor Pounds <[email protected]>
Troels Thomsen <[email protected]>
-Victor Vieux <[email protected]>
Victoria Bialas <[email protected]>
+Victor Vieux <[email protected]>
Vincent Batts <[email protected]>
Vincent Demeester <[email protected]>
Vincent Giersch <[email protected]>
-W. Trevor King <[email protected]>
weiyuan.yl <[email protected]>
+W. Trevor King <[email protected]>
xg.song <[email protected]>
xiekeyang <[email protected]>
Yann ROBERT <[email protected]>
yaoyao.xyy <[email protected]>
+yixi zhang <[email protected]>
yuexiao-wang <[email protected]>
yuzou <[email protected]>
zhouhaibing089 <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.1/docs/architecture.md
new/distribution-2.6.2/docs/architecture.md
--- old/distribution-2.6.1/docs/architecture.md 1970-01-01 01:00:00.000000000
+0100
+++ new/distribution-2.6.2/docs/architecture.md 2017-07-20 23:12:45.000000000
+0200
@@ -0,0 +1,52 @@
+---
+published: false
+---
+
+# Architecture
+
+## Design
+**TODO(stevvooe):** Discuss the architecture of the registry, internally and
externally, in a few different deployment scenarios.
+
+### Eventual Consistency
+
+> **NOTE:** This section belongs somewhere, perhaps in a design document. We
+> are leaving this here so the information is not lost.
+
+Running the registry on eventually consistent backends has been part of the
+design from the beginning. This section covers some of the approaches to
+dealing with this reality.
+
+There are a few classes of issues that we need to worry about when
+implementing something on top of the storage drivers:
+
+1. Read-After-Write consistency (see this [article on
+
s3](http://shlomoswidler.com/2009/12/read-after-write-consistency-in-amazon.html)).
+2. [Write-Write
Conflicts](http://en.wikipedia.org/wiki/Write%E2%80%93write_conflict).
+
+In reality, the registry must worry about these kinds of errors when doing the
+following:
+
+1. Accepting data into a temporary upload file may not have latest data block
+ yet (read-after-write).
+2. Moving uploaded data into its blob location (write-write race).
+3. Modifying the "current" manifest for given tag (write-write race).
+4. A whole slew of operations around deletes (read-after-write, delete-write
+ races, garbage collection, etc.).
+
+The backend path layout employs a few techniques to avoid these problems:
+
+1. Large writes are done to private upload directories. This alleviates most
+ of the corruption potential under multiple writers by avoiding multiple
+ writers.
+2. Constraints in storage driver implementations, such as support for writing
+ after the end of a file to extend it.
+3. Digest verification to avoid data corruption.
+4. Manifest files are stored by digest and cannot change.
+5. All other non-content files (links, hashes, etc.) are written as an atomic
+ unit. Anything that requires additions and deletions is broken out into
+ separate "files". Last writer still wins.
+
+Unfortunately, one must play this game when trying to build something like
+this on top of eventually consistent storage systems. If we run into serious
+problems, we can wrap the storagedrivers in a shared consistency layer but
+that would increase complexity and hinder registry cluster performance.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.1/registry/handlers/blobupload.go
new/distribution-2.6.2/registry/handlers/blobupload.go
--- old/distribution-2.6.1/registry/handlers/blobupload.go 2017-04-06
01:18:07.000000000 +0200
+++ new/distribution-2.6.2/registry/handlers/blobupload.go 2017-07-20
23:12:45.000000000 +0200
@@ -179,8 +179,8 @@
// TODO(dmcgowan): support Content-Range header to seek and write range
- if err := copyFullPayload(w, r, buh.Upload, buh, "blob PATCH",
&buh.Errors); err != nil {
- // copyFullPayload reports the error if necessary
+ if err := copyFullPayload(w, r, buh.Upload, -1, buh, "blob PATCH"); err
!= nil {
+ buh.Errors = append(buh.Errors,
errcode.ErrorCodeUnknown.WithDetail(err.Error()))
return
}
@@ -218,8 +218,8 @@
return
}
- if err := copyFullPayload(w, r, buh.Upload, buh, "blob PUT",
&buh.Errors); err != nil {
- // copyFullPayload reports the error if necessary
+ if err := copyFullPayload(w, r, buh.Upload, -1, buh, "blob PUT"); err
!= nil {
+ buh.Errors = append(buh.Errors,
errcode.ErrorCodeUnknown.WithDetail(err.Error()))
return
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.1/registry/handlers/helpers.go
new/distribution-2.6.2/registry/handlers/helpers.go
--- old/distribution-2.6.1/registry/handlers/helpers.go 2017-04-06
01:18:07.000000000 +0200
+++ new/distribution-2.6.2/registry/handlers/helpers.go 2017-07-20
23:12:45.000000000 +0200
@@ -6,7 +6,6 @@
"net/http"
ctxu "github.com/docker/distribution/context"
- "github.com/docker/distribution/registry/api/errcode"
)
// closeResources closes all the provided resources after running the target
@@ -23,7 +22,9 @@
// copyFullPayload copies the payload of an HTTP request to destWriter. If it
// receives less content than expected, and the client disconnected during the
// upload, it avoids sending a 400 error to keep the logs cleaner.
-func copyFullPayload(responseWriter http.ResponseWriter, r *http.Request,
destWriter io.Writer, context ctxu.Context, action string, errSlice
*errcode.Errors) error {
+//
+// The copy will be limited to `limit` bytes, if limit is greater than zero.
+func copyFullPayload(responseWriter http.ResponseWriter, r *http.Request,
destWriter io.Writer, limit int64, context ctxu.Context, action string) error {
// Get a channel that tells us if the client disconnects
var clientClosed <-chan bool
if notifier, ok := responseWriter.(http.CloseNotifier); ok {
@@ -32,8 +33,13 @@
ctxu.GetLogger(context).Warnf("the ResponseWriter does not
implement CloseNotifier (type: %T)", responseWriter)
}
+ var body = r.Body
+ if limit > 0 {
+ body = http.MaxBytesReader(responseWriter, body, limit)
+ }
+
// Read in the data, if any.
- copied, err := io.Copy(destWriter, r.Body)
+ copied, err := io.Copy(destWriter, body)
if clientClosed != nil && (err != nil || (r.ContentLength > 0 && copied
< r.ContentLength)) {
// Didn't receive as much content as expected. Did the client
// disconnect during the request? If so, avoid returning a 400
@@ -58,7 +64,6 @@
if err != nil {
ctxu.GetLogger(context).Errorf("unknown error reading request
payload: %v", err)
- *errSlice = append(*errSlice,
errcode.ErrorCodeUnknown.WithDetail(err))
return err
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.1/registry/handlers/images.go
new/distribution-2.6.2/registry/handlers/images.go
--- old/distribution-2.6.1/registry/handlers/images.go 2017-04-06
01:18:07.000000000 +0200
+++ new/distribution-2.6.2/registry/handlers/images.go 2017-07-20
23:12:45.000000000 +0200
@@ -22,8 +22,9 @@
// These constants determine which architecture and OS to choose from a
// manifest list when downconverting it to a schema1 manifest.
const (
- defaultArch = "amd64"
- defaultOS = "linux"
+ defaultArch = "amd64"
+ defaultOS = "linux"
+ maxManifestBodySize = 4 << 20
)
// imageManifestDispatcher takes the request context and builds the
@@ -241,8 +242,9 @@
}
var jsonBuf bytes.Buffer
- if err := copyFullPayload(w, r, &jsonBuf, imh, "image manifest PUT",
&imh.Errors); err != nil {
+ if err := copyFullPayload(w, r, &jsonBuf, maxManifestBodySize, imh,
"image manifest PUT"); err != nil {
// copyFullPayload reports the error if necessary
+ imh.Errors = append(imh.Errors,
v2.ErrorCodeManifestInvalid.WithDetail(err.Error()))
return
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.1/registry/storage/blobstore.go
new/distribution-2.6.2/registry/storage/blobstore.go
--- old/distribution-2.6.1/registry/storage/blobstore.go 2017-04-06
01:18:07.000000000 +0200
+++ new/distribution-2.6.2/registry/storage/blobstore.go 2017-07-20
23:12:45.000000000 +0200
@@ -27,7 +27,7 @@
return nil, err
}
- p, err := bs.driver.GetContent(ctx, bp)
+ p, err := getContent(ctx, bs.driver, bp)
if err != nil {
switch err.(type) {
case driver.PathNotFoundError:
@@ -37,7 +37,7 @@
return nil, err
}
- return p, err
+ return p, nil
}
func (bs *blobStore) Open(ctx context.Context, dgst digest.Digest)
(distribution.ReadSeekCloser, error) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.1/registry/storage/io.go
new/distribution-2.6.2/registry/storage/io.go
--- old/distribution-2.6.1/registry/storage/io.go 1970-01-01
01:00:00.000000000 +0100
+++ new/distribution-2.6.2/registry/storage/io.go 2017-07-20
23:12:45.000000000 +0200
@@ -0,0 +1,71 @@
+package storage
+
+import (
+ "errors"
+ "io"
+ "io/ioutil"
+
+ "github.com/docker/distribution/context"
+ "github.com/docker/distribution/registry/storage/driver"
+)
+
+const (
+ maxBlobGetSize = 4 << 20
+)
+
+func getContent(ctx context.Context, driver driver.StorageDriver, p string)
([]byte, error) {
+ r, err := driver.Reader(ctx, p, 0)
+ if err != nil {
+ return nil, err
+ }
+
+ return readAllLimited(r, maxBlobGetSize)
+}
+
+func readAllLimited(r io.Reader, limit int64) ([]byte, error) {
+ r = limitReader(r, limit)
+ return ioutil.ReadAll(r)
+}
+
+// limitReader returns a new reader limited to n bytes. Unlike io.LimitReader,
+// this returns an error when the limit reached.
+func limitReader(r io.Reader, n int64) io.Reader {
+ return &limitedReader{r: r, n: n}
+}
+
+// limitedReader implements a reader that errors when the limit is reached.
+//
+// Partially cribbed from net/http.MaxBytesReader.
+type limitedReader struct {
+ r io.Reader // underlying reader
+ n int64 // max bytes remaining
+ err error // sticky error
+}
+
+func (l *limitedReader) Read(p []byte) (n int, err error) {
+ if l.err != nil {
+ return 0, l.err
+ }
+ if len(p) == 0 {
+ return 0, nil
+ }
+ // If they asked for a 32KB byte read but only 5 bytes are
+ // remaining, no need to read 32KB. 6 bytes will answer the
+ // question of the whether we hit the limit or go past it.
+ if int64(len(p)) > l.n+1 {
+ p = p[:l.n+1]
+ }
+ n, err = l.r.Read(p)
+
+ if int64(n) <= l.n {
+ l.n -= int64(n)
+ l.err = err
+ return n, err
+ }
+
+ n = int(l.n)
+ l.n = 0
+
+ l.err = errors.New("storage: read exceeds limit")
+ return n, l.err
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.1/version/version.go
new/distribution-2.6.2/version/version.go
--- old/distribution-2.6.1/version/version.go 2017-04-06 01:18:07.000000000
+0200
+++ new/distribution-2.6.2/version/version.go 2017-07-20 23:12:45.000000000
+0200
@@ -8,4 +8,4 @@
// the latest release tag by hand, always suffixed by "+unknown". During
// build, it will be replaced by the actual version. The value here will be
// used if the registry is run after a go get based install.
-var Version = "v2.6.0+unknown"
+var Version = "v2.6.2+unknown"