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

[JENKINS-56114] Correct behavior for Windows Server 2016 with Docker #3914

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 25 additions & 3 deletions core/src/main/java/hudson/FilePath.java
Expand Up @@ -132,6 +132,7 @@
import org.jenkinsci.remoting.RoleSensitive;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.Function;
import org.kohsuke.stapler.Stapler;

import static hudson.FilePath.TarCompression.GZIP;
Expand Down Expand Up @@ -3262,9 +3263,14 @@ public Boolean invoke(@Nonnull File parentFile, @Nonnull VirtualChannel channel)
Path parentAbsolutePath = Util.fileToPath(parentFile.getAbsoluteFile());
Path parentRealPath;
try {
parentRealPath = parentAbsolutePath.toRealPath();
if (Functions.isWindows()) {
parentRealPath = this.relaxedToRealPath(parentAbsolutePath);
} else {
parentRealPath = parentAbsolutePath.toRealPath();
}
}
catch(NoSuchFileException e) {
catch (NoSuchFileException e) {
LOGGER.log(Level.FINE, String.format("Cannot find the real path to the parentFile: %s", parentAbsolutePath), e);
return false;
}

Expand Down Expand Up @@ -3296,10 +3302,11 @@ public Boolean invoke(@Nonnull File parentFile, @Nonnull VirtualChannel channel)
try{
Path child = currentFileAbsolutePath.toRealPath();
if (!child.startsWith(parentRealPath)) {
LOGGER.log(Level.FINE, "Child [{0}] does not start with parent [{1}] => not descendant", new Object[]{ child, parentRealPath });
return false;
}
} catch (NoSuchFileException e) {
// nonexistent file
// nonexistent file / Windows Server 2016 + MSFT docker
Copy link

Choose a reason for hiding this comment

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

I guess this is not the case anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

toRealPath will never work under Windows Server 2016 + MSFT Docker (perhaps other env) when the root is a mounted folder.

// in case this folder / file will be copied somewhere else,
// it becomes the responsibility of that system to check the isDescendant with the existing links
// we are not taking the parentRealPath to avoid possible problem
Expand All @@ -3322,6 +3329,21 @@ public Boolean invoke(@Nonnull File parentFile, @Nonnull VirtualChannel channel)
}
return current;
}

private @Nonnull Path relaxedToRealPath(@Nonnull Path path) throws IOException {
Wadeck marked this conversation as resolved.
Show resolved Hide resolved
try {
return path.toRealPath();
}
catch (IOException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, String.format("relaxedToRealPath cannot use the regular toRealPath on %s, trying with toRealPath(LinkOption.NOFOLLOW_LINKS)", path), e);
}
}

// that's required for specific environment like Windows Server 2016, running MSFT docker
// where the root is a <SYMLINKD>
return path.toRealPath(LinkOption.NOFOLLOW_LINKS);
}
}

private static final SoloFilePathFilter UNRESTRICTED = SoloFilePathFilter.wrap(FilePathFilter.UNRESTRICTED);
Expand Down
6 changes: 5 additions & 1 deletion core/src/main/java/jenkins/util/VirtualFile.java
Expand Up @@ -546,7 +546,11 @@ public Collection<String> list(String includes, String excludes, boolean useDefa

private boolean isIllegalSymlink() {
try {
return !this.isDescendant("");
String myPath = f.toPath().toRealPath().toString();
Wadeck marked this conversation as resolved.
Show resolved Hide resolved
String rootPath = root.toPath().toRealPath().toString();
if (!myPath.equals(rootPath) && !myPath.startsWith(rootPath + File.separatorChar)) {
return true;
}
} catch (IOException x) {
Logger.getLogger(VirtualFile.class.getName()).log(Level.FINE, "could not determine symlink status of " + f, x);
} catch (InvalidPathException x2) {
Expand Down