Skip to content
This repository has been archived by the owner on Feb 24, 2020. It is now read-only.

common/overlay: allow data directory name with colon character #3505

Merged
merged 1 commit into from
Jan 11, 2017
Merged

common/overlay: allow data directory name with colon character #3505

merged 1 commit into from
Jan 11, 2017

Conversation

ybubnov
Copy link
Contributor

@ybubnov ybubnov commented Jan 3, 2017

This patch provides an sanitizing function used to escape the colon characters in the directory names of the mount command.

According to the Linux documentation https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt it
is used as a separator symbol in case of multi lower-layer mount.

It also provides the unit tests for common/overlay package, that is possible to execute only with superuser privileges.

Fixes #3448

@ghost
Copy link

ghost commented Jan 3, 2017

Can one of the admins verify this patch?

@jonboulle
Copy link
Contributor

@rktbot ok to test

}

func TestMount(t *testing.T) {
if os.Geteuid() != 0 {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, Go syscall wrapper does not allow (due to mentioned in the comments reason) to gain root privileges: syscall/syscall_linux.go#L861. Link to the original issue: golang/go#1435.

Therefore I didn't find anything smarter than run these tests only when they've been launched with superuser privileges.

@jonboulle
Copy link
Contributor

I'm pretty leery of testing actual mounting/overlay behaviour here. What about just splitting out the construction of the mount incantation into a function and testing that instead?

@ybubnov
Copy link
Contributor Author

ybubnov commented Jan 3, 2017

I'm pretty leery of testing actual mounting/overlay behaviour here.

When you say leery, you want me to remove the introduced tests?

What about just splitting out the construction of the mount incantation into a function and testing that instead?

Sure, I will do it.

@jonboulle
Copy link
Contributor

jonboulle commented Jan 3, 2017

When you say leery, you want me to remove the introduced tests?

Sorry, that was a bit vague - I mean I'm not sure it's a good idea for a unit test since it has particular requirements (an overlay-supporting kernel, root permissions) and can be invasive to the host OS (messing with mounts). But come to think of it, maybe it's something we could add to the functional tests? It is nice to have such comprehensive behaviour testing, and the functional tests already have such demands - https://github.com/coreos/rkt/tree/master/tests

@ybubnov
Copy link
Contributor Author

ybubnov commented Jan 3, 2017

Oh I see, thank you. This sounds reasonable to me, I will move that tests into the tests sub-directory.

@ybubnov
Copy link
Contributor Author

ybubnov commented Jan 3, 2017

That is strange, semaphoreci failed on ./tests/install-deps.sh # Setup step: https://semaphoreci.com/coreos/rkt/branches/pull-request-3505/builds/2

I will resubmit the latest changes to trigger the build again.

@jonboulle
Copy link
Contributor

jonboulle commented Jan 3, 2017 via email

@ybubnov
Copy link
Contributor Author

ybubnov commented Jan 3, 2017

Looks the kernel of machines provided by semaphoreci does not support overlayfs (at least one of the existing tests reported this) https://semaphoreci.com/coreos/rkt/branches/pull-request-3505/builds/4:

=== RUN   TestGCAfterUnmount
--- SKIP: TestGCAfterUnmount (0.00s)
	rkt_gc_test.go:84: Overlay fs not supported: overlay entry not present in /proc/filesystems

I added the same check to rkt_mount_overlay_test.go.

@lucab lucab added this to the v1.23.0 milestone Jan 5, 2017
Copy link
Contributor

@s-urbaniak s-urbaniak left a comment

Choose a reason for hiding this comment

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

Just a few nits and a small question.

// The opts returns options for mount system call.
func (cfg *MountCfg) opts() string {
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s",
sanitize(cfg.Lower), sanitize(cfg.Upper), sanitize(cfg.Work))
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a nit to be consistent:

fmt.Sprintf(
    "lowerdir=%s,upperdir=%s,workdir=%s",
    sanitize(cfg.Lower), sanitize(cfg.Upper), sanitize(cfg.Work),
),

return strings.Replace(dir, ":", "\\:", -1)
}

// The opts returns options for mount system call.
Copy link
Contributor

Choose a reason for hiding this comment

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

// opts returns options for mount system call.

@@ -219,6 +219,19 @@ func createTempDirOrPanic(dirName string) string {
return tmpDir
}

// The createFileOrPanic creates an empty file within the given directory
// with a specified name. Panics if file creation fails for any reason.
func createFileOrPanic(dirName, fileName string) string {
Copy link
Contributor

Choose a reason for hiding this comment

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

// createFileOrPanic ...

// The sanitize escapes the colon symbol in order to support the dir names
// with this character, otherwise it will be treated as a separator between
// the directory names.
func sanitize(dir string) string {
Copy link
Contributor

Choose a reason for hiding this comment

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

// sanitize escapes the ...

}

// The opts returns options for mount system call.
func (cfg *MountCfg) opts() string {
Copy link
Contributor

Choose a reason for hiding this comment

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

This could be public, i.e. Opts(), since it has no side-effects.

)

func overlayMount(cfg overlay.MountCfg) error {
// Create a temporary directories with a configured prefix.
Copy link
Contributor

Choose a reason for hiding this comment

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

// Create temporary directories...

// with a specified name. Panics if file creation fails for any reason.
func createFileOrPanic(dirName, fileName string) string {
name := filepath.Join(dirName, fileName)
file, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
Copy link
Contributor

Choose a reason for hiding this comment

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

why not simply os.Create(...)? The only difference would be that it is created using 0666 mode vs 0600, but I don't think that matters here.

Copy link
Contributor Author

@ybubnov ybubnov Jan 5, 2017

Choose a reason for hiding this comment

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

Right, it does not matter in this situation, I initially thought about close-exec flag, but as this function used only in tests this is, probably, not that important as well. So as you proposed, I changed to os.Create function.

@s-urbaniak
Copy link
Contributor

@ybubnov looking good, thanks a lot! Do you mind squashing to one commit? From my side LGTM, handing over to @lucab for final review.

@ybubnov
Copy link
Contributor Author

ybubnov commented Jan 6, 2017

Squashed the changes into the single commit.

@s-urbaniak s-urbaniak requested a review from lucab January 6, 2017 15:22
@lucab
Copy link
Member

lucab commented Jan 10, 2017

Thanks for the patch @ybubnov! I may be wrong, but I think , should be escaped as well. To double-check, can you test a path with an embedded comma and see if it causes a failure?

@ybubnov
Copy link
Contributor Author

ybubnov commented Jan 10, 2017

@lucab, I tested the mount command with coma in the directory names. Without escaping it does not work as well, therefore I slightly modified the patch and added required tests.

@@ -23,6 +23,10 @@ import (
"github.com/hashicorp/errwrap"
)

// sanitizer defines a string translator used to escape colon and coma
Copy link
Member

@lucab lucab Jan 10, 2017

Choose a reason for hiding this comment

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

Minor grammar issue here and in other place in this commit: "comma" (with double m).

"syscall"

"github.com/coreos/rkt/pkg/label"
"github.com/hashicorp/errwrap"
)

// sanitizer defines a string translator used to escape colon and coma
// characters in the directories names.
var sanitizer = strings.NewReplacer(":", "\\:", ",", "\\,")
Copy link
Member

@lucab lucab Jan 10, 2017

Choose a reason for hiding this comment

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

Sorry for not spotting this earlier, but if I understand correctly the \\ (double-slash) in here is just for golang string escaping, right? To make a bit clearer that we are doing the escaping for overlayfs here, would you mind changing this into raw strings with a single slash?

{MountCfg{"/tmp/test,1", "/tmp/test,2", "/tmp/test,3", "", ""},
"lowerdir=/tmp/test\\,1,upperdir=/tmp/test\\,2,workdir=/tmp/test\\,3"},
{MountCfg{"/tmp/,1,1", "/tmp/,,2", "/tmp/,3,", "", ""},
"lowerdir=/tmp/\\,1\\,1,upperdir=/tmp/\\,\\,2,workdir=/tmp/\\,3\\,"},
Copy link
Member

Choose a reason for hiding this comment

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

Same for the double-slash, escaping and raw strings here.

// characters in the directories names.
var sanitizer = strings.NewReplacer(":", "\\:", ",", "\\,")
var sanitizer = strings.NewReplacer(`:`, `\:`, `,`, `\,`)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I redefined all characters as raw strings for the sake of consistency.

Copy link
Member

Choose a reason for hiding this comment

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

ack, fine.

@lucab
Copy link
Member

lucab commented Jan 10, 2017

I'm fine with this now, thanks. Just squash the changes together in the first single commit and we should be ready to go!

@ybubnov
Copy link
Contributor Author

ybubnov commented Jan 10, 2017

Thanks, squashed the changes into the single commit.

This patch provides an sanitizing function used to escape the colon
characters in the directory names of the mount command.

According to the Linux documentation
https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt it
is used as a separator symbol in case of multi lower-layer mount.

Separates the mount options rendering, thus make it possible to write
pure unit tests for common/overlay package. Functional tests, that
validates common/overlay.Mount function moved to the "tests"
sub-directory.
@ybubnov
Copy link
Contributor Author

ybubnov commented Jan 11, 2017

It seems, introduced changes are constantly causing the failure of the TestAppUserGroup:

23:30:39 --- FAIL: TestAppUserGroup (119.08s)
...
23:30:39 		Sending SIGTERM to remaining processes...
23:30:39 		Sending SIGKILL to remaining processes...
23:30:39 		Container rkt-6ad75081-ecc6-499a-8db7-33851d34d370 failed with error code 226.
23:30:39 	rkt_tests.go:141: rkt terminated with unexpected status 226, expected 0
23:30:39 		Output:
23:30:39 		[]

I don't know if it is a known issue: #3477, or caused by new code.

@lucab
Copy link
Member

lucab commented Jan 11, 2017

No worry, that is a known ephemeral test failure we are currently chasing, unrelated to your PR.

Copy link
Member

@lucab lucab left a comment

Choose a reason for hiding this comment

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

LGTM

@jonboulle
Copy link
Contributor

@ybubnov thanks so much for your work here!

@lucab lucab merged commit 4de6e93 into rkt:master Jan 11, 2017
@ybubnov ybubnov deleted the escape-colon-in-overlay-directory-names branch January 11, 2017 13:02
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants