From ff52beb5e263d824f85baf93fe6dbf6e8a421d79 Mon Sep 17 00:00:00 2001 From: Wadeck Follonier Date: Fri, 8 Mar 2019 10:19:07 +0100 Subject: [PATCH] [JENKINS-56114] Correct behavior for Windows Server 2016 with Docker (#3914) * [JENKINS-56114] Correct behavior for Windows Server 2016 with Docker - also adjust the symlink escape hatch * Correct missing space + retrigger build * Improve performance with a check on the logger level * Run the specific code only under Windows * Rename the method as it's used only for Windows (cherry picked from commit 5562b2fec6428b730a7b88ad6390a7ed741ba792) --- core/src/main/java/hudson/FilePath.java | 28 +++++++++++++++++-- .../main/java/jenkins/util/VirtualFile.java | 6 +++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/hudson/FilePath.java b/core/src/main/java/hudson/FilePath.java index ef99223599..0a15f52524 100644 --- a/core/src/main/java/hudson/FilePath.java +++ b/core/src/main/java/hudson/FilePath.java @@ -132,6 +132,7 @@ import org.jenkinsci.remoting.RoleChecker; 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; @@ -3264,9 +3265,14 @@ public final class FilePath implements Serializable { Path parentAbsolutePath = Util.fileToPath(parentFile.getAbsoluteFile()); Path parentRealPath; try { - parentRealPath = parentAbsolutePath.toRealPath(); + if (Functions.isWindows()) { + parentRealPath = this.windowsToRealPath(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; } @@ -3298,10 +3304,11 @@ public final class FilePath implements Serializable { 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 // 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 @@ -3324,6 +3331,21 @@ public final class FilePath implements Serializable { } return current; } + + private @Nonnull Path windowsToRealPath(@Nonnull Path path) throws IOException { + 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 + return path.toRealPath(LinkOption.NOFOLLOW_LINKS); + } } private static final SoloFilePathFilter UNRESTRICTED = SoloFilePathFilter.wrap(FilePathFilter.UNRESTRICTED); diff --git a/core/src/main/java/jenkins/util/VirtualFile.java b/core/src/main/java/jenkins/util/VirtualFile.java index 9d08782198..33aa5b3606 100644 --- a/core/src/main/java/jenkins/util/VirtualFile.java +++ b/core/src/main/java/jenkins/util/VirtualFile.java @@ -546,7 +546,11 @@ public abstract class VirtualFile implements Comparable, Serializab private boolean isIllegalSymlink() { try { - return !this.isDescendant(""); + String myPath = f.toPath().toRealPath().toString(); + 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) {