Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

filepath: Add a stand-alone package for explicit-OS path logic #445

Merged
merged 1 commit into from
Sep 30, 2017

Conversation

wking
Copy link
Contributor

@wking wking commented Aug 17, 2017

As discussed here and later, and based on the Gist I'd created for that comment.

Go's path/filepath has lots of useful path operations, but there is a compile-time decision to select only the logic that applies to your $GOOS. That makes it hard to validate a Windows config from a Linux host (or vice versa) because Go's builtin tools won't tell you whether a path is absolute on the target platform (just whether the path is absolute on your platform). This commit adds a new package to do the same sorts of things but with an explicit OS argument.

In some cases, there's also an explicit workding directory argument. For example, Go's Abs has:

If the path is not absolute it will be joined with the current working directory to turn it into an absolute path.

but that doesn't make sense for a cross-platform Abs call because the real current working directory will be for the wrong platform. Instead, cross-platform calls to Abs and similar should fake a working directory as if they were being called from the other platform.

The Windows implementation is not very complete, with IsAbs definitely missing a lot of stuff; Abs, Clean, and IsAncestor probably missing stuff; and a lack of Windows-path tests. But the current tools are broken for validating Windows configs anyway, so I've left completing Windows support to future work.

Besides adding the new package, I updated the config validation to use the new package where appropriate. For example, checks for absolute hook paths (based on this) now appropriately account for the target platform (although Abs has limited Windows support at the moment, as mentioned above).

There are still a number of config validation checks that use Go's stock filepath, because they're based around actual filesystem access (e.g. reading config.json off the disk, asserting that root.path exists on the disk, etc.). Some of those will need logic to convert between path platforms (which I'm leaving to future work). For example, if root.path is formed for another platform, then:

  • If root.path is absolute (on the target platform), there's no way to check whether root.path exists inside the bundle.
  • If root.path is relative, we should be converting it from the target platform to the host platform before joining it to our bundle path. For example, with a Windows bundle in /foo on a Linux host where root.path is bar\baz, then runtime-tools should be checking for the root directory in /foo/bar/baz, not in /foo/bar\baz. The root.path example is somewhat guarded by the bundle requirement for siblinghood, but I'd rather enforce siblinghood independently from existence, since the spec has separate requirements for both.

@liangchenye
Copy link
Member

liangchenye commented Aug 24, 2017

LGTM
I tested it locally, it works. But can you add filepath to Makefile so travis will test it automatically? @wking

The validation directory is not used for unit test, we had to add directory like filepath to Makefile by hand.

Approved with PullApprove

@wking
Copy link
Contributor Author

wking commented Aug 24, 2017 via email

@liangchenye
Copy link
Member

liangchenye commented Aug 25, 2017

LGTM
@mrunalp @Mashimiao @q384566678

Approved with PullApprove

@Mashimiao
Copy link

I think this cause a regression. Before this PR we can check whether windows mounts are nested, but now we can't any more.

@wking
Copy link
Contributor Author

wking commented Aug 25, 2017 via email

@Mashimiao
Copy link

I don't think tha's IsAncestor's problem, it's Abs()'s problem. I think we can check whether a windows path is absolute or not as https://github.com/opencontainers/runtime-tools/blob/master/validate/validate.go#L843

@wking
Copy link
Contributor Author

wking commented Aug 30, 2017 via email

@Mashimiao
Copy link

Mashimiao commented Aug 31, 2017 via email

@wking
Copy link
Contributor Author

wking commented Aug 31, 2017

No, it should be here...

Ah, so maybe copy part of that into IsAbs, and then replace our current pathValid calls with IsAbs?

@Mashimiao
Copy link

Mashimiao commented Aug 31, 2017 via email

Go's path/filepath has lots of useful path operations, but there is a
compile-time decision to select only the logic that applies to your
$GOOS.  That makes it hard to validate a Windows config from a Linux
host (or vice versa) because Go's builtin tools won't tell you whether
a path is absolute on the target platform (just whether the path is
absolute on *your* platform).  This commit adds a new package to do
the same sorts of things but with an explicit OS argument.

In some cases, there's also an explicit workding directory argument.
For example, Go's Abs has [1]:

  If the path is not absolute it will be joined with the current
  working directory to turn it into an absolute path.

but that doesn't make sense for a cross-platform Abs call because
the real current working directory will be for the wrong platform.
Instead, cross-platform calls to Abs and similar should fake a working
directory as if they were being called from the other platform.

The Windows implementation is not very complete, with IsAbs definitely
missing a lot of stuff; Abs, Clean, and IsAncestor probably missing
stuff; and a lack of Windows-path tests.  But the current tools are
broken for validating Windows configs anyway, so I've left completing
Windows support to future work.  The regular expression I've used is
similar to what we used to use in pathValid, but has been adjusted
based on [2]:

  The absolute path has the following format:

    LocalDrive:\Path\FileName

I've assumed that c:\a is absolute as well, even though it doesn't
quite match the above pattern.  And I no longer test for colons,
question marks, and other reserved characters [3], although it would
be easy to add checks for that as well if we wanted.

Besides adding the new package, I updated the config validation to use
the new package where appropriate.  For example checks for absolute
hook paths (based on [4]) now appropriately account for the target
platform (although Abs has limited Windows support at the moment, as
mentioned above).

There are still a number of config validation checks that use Go's
stock filepath, because they're based around actual filesystem access
(e.g. reading config.json off the disk, asserting that root.path
exists on the disk, etc.).  Some of those will need logic to convert
between path platforms (which I'm leaving to future work).  For
example, if root.path is formed for another platform, then:

* If root.path is absolute (on the target platform), there's no way to
  check whether root.path exists inside the bundle.

* If root.path is relative, we should be converting it from the target
  platform to the host platform before joining it to our bundle path.
  For example, with a Windows bundle in "/foo" on a Linux host where
  root.path is "bar\baz", then runtime-tools should be checking for
  the root directory in /foo/bar/baz, not in /foo/bar\baz.  The
  root.path example is somewhat guarded by the bundle requirement for
  siblinghood [5], but I'd rather enforce siblinghood independently
  from existence [6], since the spec has separate requirements for
  both.

I'm not clear on why we were using pathValid for mount sources on
Windows.  We've been doing that since 4dcd484 (validate: add mounts
whether nested check, 2016-10-25, opencontainers#256, [7]), but I see no
absolute-path requirement in the spec [8], which only forbids UNC
paths and mapped drives for source (which we don't yet have tooling to
detect).  Perhaps the idea was just to check for paths which contained
reserved characters?  In any case, I think source handling on Windows
should not involve IsAbs and should be addressed more thoroughly in
future work.

[1]: https://golang.org/pkg/path/filepath/#Abs
[2]: https://technet.microsoft.com/en-us/library/ee692607.aspx
[3]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#naming_conventions
[4]: https://github.com/opencontainers/runtime-spec/blame/v1.0.0/config.md#L375
[5]: https://github.com/opencontainers/runtime-spec/blame/v1.0.0/bundle.md#L17-L19
[6]: https://github.com/opencontainers/runtime-spec/blame/v1.0.0/config.md#L43
[7]: https://github.com/opencontainers/runtime-tools/pull/256/files#diff-8351286f57eb81e245c9c99c07f3b34fR413
[8]: https://github.com/opencontainers/runtime-spec/blob/v1.0.0/config.md#mounts

Signed-off-by: W. Trevor King <wking@tremily.us>
@wking
Copy link
Contributor Author

wking commented Aug 31, 2017 via email

@Mashimiao
Copy link

Mashimiao commented Sep 26, 2017

LGTM

Approved with PullApprove

@wking
Copy link
Contributor Author

wking commented Sep 29, 2017

@liangchenye, still look good to you?

@liangchenye
Copy link
Member

I'll review the changes @wking .

@liangchenye
Copy link
Member

liangchenye commented Sep 30, 2017

LGTM

Approved with PullApprove

@liangchenye liangchenye merged commit 2302d4c into opencontainers:master Sep 30, 2017
@wking wking deleted the explicit-os-filepath branch October 2, 2017 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants