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 dc7c629..a7f8ab3 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 @@ -1388,6 +1388,9 @@ public static boolean isAclEnabled(Configuration conf) { public static final String NM_DOCKER_CONTAINER_CAPABILITIES = DOCKER_CONTAINER_RUNTIME_PREFIX + "capabilities"; + public static final String DOCKER_WHITE_LIST_VOLUME_MOUNT = + DOCKER_CONTAINER_RUNTIME_PREFIX + "white-list-volume-mount"; + /** These are the default capabilities added by docker. We'll use the same * set here. While these may not be case-sensitive from a docker * perspective, it is best to keep these uppercase. 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 b70a4e1..ef54ded 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; @@ -145,6 +147,9 @@ @InterfaceAudience.Private public static final String ENV_DOCKER_CONTAINER_LOCAL_RESOURCE_MOUNTS = "YARN_CONTAINER_RUNTIME_DOCKER_LOCAL_RESOURCE_MOUNTS"; + @InterfaceAudience.Private + public static final String ENV_DOCKER_CONTAINER_WHITE_LIST_MOUNTS = + "YARN_CONTAINER_RUNTIME_WHITE_LIST_MOUNTS"; static final String CGROUPS_ROOT_DIRECTORY = "/sys/fs/cgroup"; @@ -374,6 +379,35 @@ private boolean allowPrivilegedContainerExecution(Container container) } return true; + +} + private boolean isArbitraryMount(String mount) { + String[] whiteList = YarnConfiguration.DOCKER_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 @@ -481,6 +515,23 @@ public void launchContainer(ContainerRuntimeContext ctx) } } + if (environment.containsKey(ENV_DOCKER_CONTAINER_WHITE_LIST_MOUNTS)) { + String mounts = environment.get( + ENV_DOCKER_CONTAINER_WHITE_LIST_MOUNTS); + if (!mounts.isEmpty()) { + for (String mount : StringUtils.split(mounts)) { + String[] dir = StringUtils.split(mount, ':'); + if (dir.length != 2) { + throw new ContainerExecutionException("Invalid mount : " + + mount); + } + if (!isArbitraryMount(dir[0])) { + runCommand.addMountLocation(dir[0], dir[1] + ":ro"); + } + } + } + } + if (allowPrivilegedContainerExecution(container)) { runCommand.setPrivileged(); }