diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java index 3f84a23..6fc5cbe 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java @@ -1053,6 +1053,10 @@ public static boolean isAclEnabled(Configuration conf) { NM_PREFIX + "log-aggregation.roll-monitoring-interval-seconds"; public static final long DEFAULT_NM_LOG_AGGREGATION_ROLL_MONITORING_INTERVAL_SECONDS = -1; + + public static final String NM_WHITE_LIST_VOLUME_MOUNT = + NM_PREFIX + "white-list-volume-mount"; + /** * Number of threads used in log cleanup. Only applicable if Log aggregation * is disabled diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java index a3aff2f..366366a 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java @@ -48,8 +48,10 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeConstants; import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeContext; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -373,6 +375,35 @@ private boolean allowPrivilegedContainerExecution(Container container) } return true; + +} + private boolean isArbitraryMount(String mount) { + String[] whiteList = YarnConfiguration.NM_WHITE_LIST_VOLUME_MOUNT.split(","); + File child = new File(mount); + for (int i = 0; i < whiteList.length; i++){ + File parent = new File(mount); + if (isSubDirectory(parent, child)){ + return false; + } + } + return true; + } + + private boolean isSubDirectory(File parent, File child){ + try { + parent = parent.getCanonicalFile(); + child = child.getCanonicalFile(); + File parentFile = child; + while (parentFile != null){ + if (parent.equals(parentFile)){ + return true; + } + parentFile = parentFile.getParentFile(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return false; } @VisibleForTesting @@ -384,11 +415,14 @@ protected String validateMount(String mount, java.nio.file.Path path = Paths.get(resource.getKey().toString()); if (!path.isAbsolute()) { throw new ContainerExecutionException("Mount must be absolute: " + - mount); + mount); } if (Files.isSymbolicLink(path)) { throw new ContainerExecutionException("Mount cannot be a symlink: " + - mount); + mount); + } + if (isArbitraryMount(mount)) { + throw new ContainerExecutionException("Mount is not allowed in the white list"); } return path.toString(); }