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 - msab...@suse.com + +- 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 <g...@omer.io> Omer Cohen <g...@omerc.net> Eric Yang <windfa...@gmail.com> Eric Yang <windfa...@users.noreply.github.com> Nikita Tarasov <nik...@mygento.ru> Nikita <luckyr...@users.noreply.github.com> +Misty Stanley-Jones <mi...@docker.com> Misty Stanley-Jones <mi...@apache.org> 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 <dee...@gmail.com> Aaron Lehmann <aaron.lehm...@docker.com> Aaron Schlesinger <aschlesin...@deis.com> Aaron Vinson <avinson.pub...@gmail.com> @@ -18,10 +17,11 @@ Andrey Kostov <kostov.and...@gmail.com> Andy Goldstein <agold...@redhat.com> Anis Elleuch <vadme...@gmail.com> -Anton Tiurin <noxi...@yandex.ru> Antonio Mercado <amerc...@thinknode.com> Antonio Murdaca <run...@redhat.com> +Anton Tiurin <noxi...@yandex.ru> Anusha Ragunathan <anu...@docker.com> +a-palchikov <dee...@gmail.com> Arien Holthuizen <aholthui...@schubergphilis.com> Arnaud Porterie <arnaud.porte...@docker.com> Arthur Baars <art...@semmle.com> @@ -46,9 +46,9 @@ Dave Trombley <dave.tromb...@gmail.com> Dave Tucker <d...@docker.com> David Lawrence <david.lawre...@docker.com> +davidli <wenquan...@hp.com> David Verhasselt <da...@crowdway.com> David Xia <d...@spotify.com> -davidli <wenquan...@hp.com> Dejan Golja <de...@golja.org> Derek McGowan <de...@mcgstyle.net> Diogo Mónica <diogo.mon...@gmail.com> @@ -68,8 +68,8 @@ Gleb Schukin <gschu...@ptsecurity.com> harche <p.hars...@gmail.com> Henri Gomez <henri.go...@gmail.com> -Hu Keping <hukep...@huawei.com> Hua Wang <wanghua.hum...@gmail.com> +Hu Keping <hukep...@huawei.com> HuKeping <hukep...@huawei.com> Ian Babrou <ibob...@gmail.com> igayoso <igay...@gmail.com> @@ -86,21 +86,21 @@ Joao Fernandes <joao.fernan...@docker.com> John Mulhausen <j...@docker.com> John Starks <josta...@microsoft.com> +Jonathan Boulle <jonathanbou...@gmail.com> Jon Johnson <jonjohn...@google.com> Jon Poler <jonathan.po...@apcera.com> -Jonathan Boulle <jonathanbou...@gmail.com> Jordan Liggitt <jligg...@redhat.com> Josh Chorlton <josh.chorl...@docker.com> Josh Hawn <josh.h...@docker.com> Julien Fernandez <julien.fernan...@gmail.com> -Ke Xu <leonhart...@gmail.com> Keerthan Mala <km...@engineyard.com> Kelsey Hightower <kelsey.highto...@gmail.com> Kenneth Lim <kennethli...@gmail.com> Kenny Leung <kle...@google.com> -Li Yi <denverd...@gmail.com> -Liu Hua <sdu....@huawei.com> +Ke Xu <leonhart...@gmail.com> liuchang0812 <liuchang0...@gmail.com> +Liu Hua <sdu....@huawei.com> +Li Yi <denverd...@gmail.com> Lloyd Ramey <lnr0...@gmail.com> Louis Kottmann <louis.kottm...@gmail.com> Luke Carpenter <x...@rubynerd.net> @@ -108,15 +108,14 @@ Mary Anthony <m...@docker.com> Matt Bentley <mbent...@mbentley.net> Matt Duch <m...@learnmetrics.com> +Matthew Green <gree...@live.co.uk> Matt Moore <mattm...@google.com> Matt Robenolt <m...@ydekproductions.com> -Matthew Green <gree...@live.co.uk> Michael Prokop <m...@grml.org> Michal Minar <mimi...@redhat.com> Michal Minář <mimi...@redhat.com> Mike Brown <brow...@us.ibm.com> Miquel Sabaté <msab...@suse.com> -Misty Stanley-Jones <mi...@apache.org> Misty Stanley-Jones <mi...@docker.com> Morgan Bauer <mba...@us.ibm.com> moxiegirl <m...@docker.com> @@ -165,17 +164,18 @@ Tony Holdstock-Brown <t...@docker.com> Trevor Pounds <trevor.pou...@gmail.com> Troels Thomsen <tro...@thomsen.io> -Victor Vieux <vi...@docker.com> Victoria Bialas <victoria.bia...@docker.com> +Victor Vieux <vi...@docker.com> Vincent Batts <vba...@redhat.com> Vincent Demeester <vinc...@sbr.pm> Vincent Giersch <vincent.gier...@ovh.net> -W. Trevor King <wk...@tremily.us> weiyuan.yl <weiyuan...@alibaba-inc.com> +W. Trevor King <wk...@tremily.us> xg.song <xg.s...@venusource.com> xiekeyang <xiekey...@huawei.com> Yann ROBERT <yann.rob...@anantaplex.fr> yaoyao.xyy <yaoyao....@alibaba-inc.com> +yixi zhang <y...@memsql.com> yuexiao-wang <wang.yuex...@zte.com.cn> yuzou <zou...@huawei.com> zhouhaibing089 <zhouhaibing...@gmail.com> 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"