Skip to content

Fix HTTP status-code when loading invalid tar#34425

Open
thaJeztah wants to merge 1 commit intomoby:masterfrom
thaJeztah:fix-invalid-import-status-code
Open

Fix HTTP status-code when loading invalid tar#34425
thaJeztah wants to merge 1 commit intomoby:masterfrom
thaJeztah:fix-invalid-import-status-code

Conversation

@thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Aug 7, 2017

fixes #34416

Opening for discussion, because this changes the WriteFlusher interface, which is used in various places; also the error-code may need to be more specific based on the actual error.

Before this change:

echo "hello world, I am not a tar" | curl -v --unix-socket  /var/run/docker.sock -H "Content-Type: application/x-tar"  --data-binary @- -X POST http://localhost/v1.29/images/load
*   Trying /var/run/docker.sock...
* Connected to localhost (/Users/sebastiaan/Library/Containers/com.dock) port 80 (#0)
> POST /v1.29/images/load HTTP/1.1
> Host: localhost
> User-Agent: curl/7.51.0
> Accept: */*
> Content-Type: application/x-tar
> Content-Length: 28
>
* upload completely sent off: 28 out of 28 bytes
< HTTP/1.1 200 OK
< Api-Version: 1.31
< Content-Type: application/json
< Date: Mon, 07 Aug 2017 15:11:35 GMT
< Docker-Experimental: true
< Ostype: linux
< Server: Docker/17.07.0-ce-rc1 (linux)
< Transfer-Encoding: chunked
<
{"errorDetail":{"message":"Error processing tar file(exit status 1): unexpected EOF"},"error":"Error processing tar file(exit status 1): unexpected EOF"}
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact

After this change:

/ # echo "hello world, I am not a tar" | curl -v --unix-socket  /var/run/docker.sock -H "Content-Type: application/x-tar"  --data-binary @- -X POST http://localhost/v1.29/images/load
   *   Trying /var/run/docker.sock...
* Connected to localhost (/var/run/docker.sock) port 80 (#0)
> POST /v1.29/images/load HTTP/1.1
> Host: localhost
> User-Agent: curl/7.52.1
> Accept: */*
> Content-Type: application/x-tar
> Content-Length: 28
> 
* upload completely sent off: 28 out of 28 bytes
< HTTP/1.1 400 Bad Request
< Api-Version: 1.36
< Content-Type: application/json
< Docker-Experimental: false
< Ostype: linux
< Server: Docker/dev (linux)
< Date: Fri, 16 Feb 2018 16:21:46 GMT
< Transfer-Encoding: chunked
< 
Api-Version: 1.36
Content-Type: application/json
Docker-Experimental: false
Ostype: linux
Server: Docker/dev (linux)
{"errorDetail":{"message":"Error processing tar file(exit status 1): unexpected EOF"},"error":"Error processing tar file(exit status 1): unexpected EOF"}
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact

@thaJeztah
Copy link
Member Author

ping @cpuguy83 could you have a look if this direction is ok or not?

Copy link
Member

@cpuguy83 cpuguy83 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Importing HTTP in the backend is not what we want.
In the attach code we pass a function to get the write streams rather than passing the actual writers, which allows the backend to return early due to an error without having sent a 200 response header already.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not right.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up changing it due to

moby/daemon/stats.go

Lines 41 to 47 in 22472c8

outStream := config.OutStream
if config.Stream {
wf := ioutils.NewWriteFlusher(outStream)
defer wf.Close()
wf.Flush()
outStream = wf
}

(also a reason I opened this for discussion)

@thaJeztah thaJeztah force-pushed the fix-invalid-import-status-code branch 2 times, most recently from 6a24b31 to 0004b18 Compare August 15, 2017 14:33
@thaJeztah thaJeztah force-pushed the fix-invalid-import-status-code branch from 0004b18 to 1f59db5 Compare August 17, 2017 21:49
@thaJeztah
Copy link
Member Author

ping @cpuguy83 @tonistiigi PTAL

@thaJeztah thaJeztah force-pushed the fix-invalid-import-status-code branch from 1f59db5 to 99e7612 Compare October 11, 2017 22:27
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work? Would LoadImage have already written to the stream and thus already have sent a 200 OK?
We could check output.Flushed(), although I would pretty much expect LoadImage to handle all things on the stream by this point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, can we gate this with a check for !output.Flushed()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I can add that

@thaJeztah
Copy link
Member Author

Does this work? Would LoadImage have already written to the stream and thus already have sent a 200 OK?

Testing other situations: valid tar, but wrong format (export <--> load)

docker run -dit --name foo busybox
docker export foo > exported.tar

With this PR:

$ cat exported.tar | curl -v --unix-socket  /var/run/docker.sock -H "Content-Type: application/x-tar"  --data-binary @- -X POST http://localhost/v1.29/images/load

*   Trying /var/run/docker.sock...
* Connected to localhost (/var/run/docker.sock) port 80 (#0)
> POST /v1.29/images/load HTTP/1.1
> Host: localhost
> User-Agent: curl/7.52.1
> Accept: */*
> Content-Type: application/x-tar
> Content-Length: 1359872
> Expect: 100-continue
> 
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 400 Bad Request
< Api-Version: 1.36
< Content-Type: application/json
< Docker-Experimental: false
< Ostype: linux
< Server: Docker/dev (linux)
< Date: Fri, 19 Jan 2018 16:25:33 GMT
< Transfer-Encoding: chunked
< 
Api-Version: 1.36
Content-Type: application/json
Docker-Experimental: false
Ostype: linux
Server: Docker/dev (linux)
{"errorDetail":{"message":"open /var/lib/docker/tmp/docker-import-641132035/bin/json: no such file or directory"},"error":"open /var/lib/docker/tmp/docker-import-641132035/bin/json: no such file or directory"}
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact

Doing the same on Docker 18.01:

$ cat exported.tar | curl -v --unix-socket  /var/run/docker.sock -H "Content-Type: application/x-tar"  --data-binary @- -X POST http://localhost/v1.29/images/load

*   Trying /var/run/docker.sock...
* Connected to localhost (/var/run/docker.sock) port 80 (#0)
> POST /v1.29/images/load HTTP/1.1
> Host: localhost
> User-Agent: curl/7.57.0
> Accept: */*
> Content-Type: application/x-tar
> Content-Length: 1359872
> Expect: 100-continue
> 
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< Api-Version: 1.35
< Content-Type: application/json
< Docker-Experimental: false
< Ostype: linux
< Server: Docker/18.01.0-ce (linux)
< Date: Fri, 19 Jan 2018 16:43:37 GMT
< Transfer-Encoding: chunked
< 
{"errorDetail":{"message":"open /var/lib/docker/tmp/docker-import-640654783/bin/json: no such file or directory"},"error":"open /var/lib/docker/tmp/docker-import-640654783/bin/json: no such file or directory"}
* Connection #0 to host localhost left intact

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errdefs.InvalidParameter(err)

@thaJeztah thaJeztah force-pushed the fix-invalid-import-status-code branch from 99e7612 to fa8fbbe Compare February 16, 2018 16:22
@thaJeztah
Copy link
Member Author

ping @cpuguy83 updated 👍

@thaJeztah
Copy link
Member Author

thaJeztah commented Feb 16, 2018

For some reason, the CLI doesn't print the error message with this change; only difference between before/after is the status code:

diff --git a/before b/after
index 0493ca6..149e900 100644
--- a/before
+++ b/after
@@ -1,13 +1,14 @@
 * upload completely sent off: 28 out of 28 bytes
-< HTTP/1.1 200 OK
+< HTTP/1.1 400 Bad Request
 < Api-Version: 1.36
 < Content-Type: application/json
-< Date: Fri, 16 Feb 2018 16:51:16 GMT
-< Docker-Experimental: true
+< Docker-Experimental: false
 < Ostype: linux
-< Server: Docker/18.02.0-ce (linux)
+< Server: Docker/dev (linux)
+< Date: Fri, 16 Feb 2018 16:50:38 GMT
 < Transfer-Encoding: chunked
 < 
 {"errorDetail":{"message":"Error processing tar file(exit status 1): unexpected EOF"},"error":"Error processing tar file(exit status 1): unexpected EOF"}
+* Curl_http_done: called premature == 0
 * Connection #0 to host localhost left intact

But with this change, the actual error is not printed:

echo "fooasdsddsdas" | docker load
Error response from daemon: 

Wondering if it's an issue in the CLI and it stops early on a 400 status?

@AkihiroSuda
Copy link
Member

Wondering if it's an issue in the CLI and it stops early on a 400 status?

Is it safer to keep the current behavior for ensuring compatibility?

@thaJeztah thaJeztah force-pushed the fix-invalid-import-status-code branch from a09c1c5 to 924450d Compare October 25, 2018 16:09
@olljanat
Copy link
Contributor

@thaJeztah CI looks failing to:

18:40:58 These files import internal code: (either directly or indirectly)
18:40:58  - pkg/chrootarchive/archive_unix.go imports github.com/docker/docker/errdefs
18:40:58 
18:40:59 Build step 'Execute shell' marked build as failure

@derek derek bot added the status/failing-ci Indicates that the PR in its current state fails the test suite label Dec 22, 2018
@thaJeztah thaJeztah added the kind/bugfix PR's that fix bugs label Oct 10, 2019
@thaJeztah thaJeztah force-pushed the fix-invalid-import-status-code branch 3 times, most recently from 2cacd95 to a06ba87 Compare April 23, 2021 10:36
Before this change:

    echo "hello world, I am not a tar" | curl -v --unix-socket  /var/run/docker.sock -H "Content-Type: application/x-tar"  --data-binary @- -X POST http://localhost/v1.29/images/load
    *   Trying /var/run/docker.sock...
    * Connected to localhost (/Users/sebastiaan/Library/Containers/com.dock) port 80 (#0)
    > POST /v1.29/images/load HTTP/1.1
    > Host: localhost
    > User-Agent: curl/7.51.0
    > Accept: */*
    > Content-Type: application/x-tar
    > Content-Length: 28
    >
    * upload completely sent off: 28 out of 28 bytes
    < HTTP/1.1 200 OK
    < Api-Version: 1.31
    < Content-Type: application/json
    < Date: Mon, 07 Aug 2017 15:11:35 GMT
    < Docker-Experimental: true
    < Ostype: linux
    < Server: Docker/17.07.0-ce-rc1 (linux)
    < Transfer-Encoding: chunked
    <
    {"errorDetail":{"message":"Error processing tar file(exit status 1): unexpected EOF"},"error":"Error processing tar file(exit status 1): unexpected EOF"}
    * Curl_http_done: called premature == 0
    * Connection #0 to host localhost left intact

After this change:

    echo "hello world, I am not a tar" | curl -v --unix-socket  /var/run/docker.sock -H "Content-Type: application/x-tar"  --data-binary @- http://localhost/v1.29/images/load
    *   Trying /var/run/docker.sock...
    * Connected to localhost (/var/run/docker.sock) port 80 (#0)
    > POST /v1.29/images/load HTTP/1.1
    > Host: localhost
    > User-Agent: curl/7.55.0
    > Accept: */*
    > Content-Type: application/x-tar
    > Content-Length: 28
    >
    * upload completely sent off: 28 out of 28 bytes
    < HTTP/1.1 400 Bad Request
    < Api-Version: 1.32
    < Content-Type: application/json
    < Docker-Experimental: false
    < Ostype: linux
    < Server: Docker/17.06.0-dev (linux)
    < Date: Thu, 17 Aug 2017 11:14:55 GMT
    < Transfer-Encoding: chunked
    <
    Api-Version: 1.32
    Content-Type: application/json
    Docker-Experimental: false
    Ostype: linux
    Server: Docker/17.06.0-dev (linux)
    {"errorDetail":{"message":"Error processing tar file(exit status 1): unexpected EOF"},"error":"Error processing tar file(exit status 1): unexpected EOF"}

Attempting to import an "export" image using "docker load":

    docker export somecontainer > foo.tar
    cat foo.tar | curl -v --unix-socket  /var/run/docker.sock -H "Content-Type: application/x-tar"  --data-binary @- http://localhost/v1.29/images/load
    *   Trying /var/run/docker.sock...
    * Connected to localhost (/var/run/docker.sock) port 80 (#0)
    > POST /v1.29/images/load HTTP/1.1
    > Host: localhost
    > User-Agent: curl/7.55.0
    > Accept: */*
    > Content-Type: application/x-tar
    > Content-Length: 5910528
    > Expect: 100-continue
    >
    < HTTP/1.1 100 Continue
    * We are completely uploaded and fine
    < HTTP/1.1 400 Bad Request
    < Api-Version: 1.32
    < Content-Type: application/json
    < Docker-Experimental: false
    < Ostype: linux
    < Server: Docker/17.06.0-dev (linux)
    < Date: Thu, 17 Aug 2017 12:34:02 GMT
    < Transfer-Encoding: chunked
    <
    Api-Version: 1.32
    Content-Type: application/json
    Docker-Experimental: false
    Ostype: linux
    Server: Docker/17.06.0-dev (linux)
    {"errorDetail":{"message":"open /var/lib/docker/tmp/docker-import-708284929/bin/json: no such file or directory"},"error":"open /var/lib/docker/tmp/docker-import-708284929/bin/json: no such file or directory"}

Signed-off-by: Sebastiaan van Stijn <[email protected]>
@thaJeztah thaJeztah force-pushed the fix-invalid-import-status-code branch from a06ba87 to 7518ec9 Compare November 12, 2021 09:48
@thaJeztah
Copy link
Member Author

Hmm.. good call; looks like we have some fixing to do with the ppc64le and s390x builds (they're disabled by default now, but were started on this)

ppc64le

[2021-11-12T09:51:47.615Z]  > [criu 2/2] RUN --mount=type=cache,sharing=locked,id=moby-criu-aptlib,target=/var/lib/apt     --mount=type=cache,sharing=locked,id=moby-criu-aptcache,target=/var/cache/apt         echo 'deb https://download.opensuse.org/repositories/devel:/tools:/criu/Debian_11/ /' > /etc/apt/sources.list.d/criu.list         && apt-get update         && apt-get install -y --no-install-recommends criu         && install -D /usr/sbin/criu /build/criu:
[2021-11-12T09:51:47.615Z] #46 7.620 Reading package lists...
[2021-11-12T09:51:47.615Z] #46 12.62 Reading package lists...
[2021-11-12T09:51:47.615Z] #46 17.28 Building dependency tree...
[2021-11-12T09:51:47.615Z] #46 18.13 Reading state information...
[2021-11-12T09:51:47.615Z] #46 18.30 Package criu is not available, but is referred to by another package.
[2021-11-12T09:51:47.615Z] #46 18.30 This may mean that the package is missing, has been obsoleted, or
[2021-11-12T09:51:47.615Z] #46 18.30 is only available from another source
[2021-11-12T09:51:47.615Z] #46 18.30
[2021-11-12T09:51:47.615Z] #46 18.85 E: Package 'criu' has no installation candidate

s390x

[2021-11-12T09:54:16.489Z] + sudo modprobe ip6table_filter
[2021-11-12T09:54:16.489Z] sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
script returned exit code 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api API kind/bugfix PR's that fix bugs status/failing-ci Indicates that the PR in its current state fails the test suite status/2-code-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Status code images load API returns is misleading

6 participants