From 2e2e5401f297545181323b126a69eaa2239afb02 Mon Sep 17 00:00:00 2001 From: Billie Rinaldi Date: Thu, 5 Sep 2019 12:49:16 -0700 Subject: [PATCH] YARN-9718. Fixed yarn.service.am.java.opts shell injection. Contributed by Eric Yang --- .../hadoop/yarn/service/client/ServiceClient.java | 3 +++ .../service/exceptions/RestApiErrorMessages.java | 1 + .../hadoop/yarn/service/utils/ServiceApiUtil.java | 12 ++++++++++++ .../yarn/service/utils/TestServiceApiUtil.java | 6 ++++++ 4 files changed, 22 insertions(+) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java index b7fec77f17..1276022f25 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java @@ -1203,6 +1203,9 @@ private String buildCommandLine(Service app, Configuration conf, jvmOpts += DEFAULT_AM_JVM_XMX; } + // validate possible command injection. + ServiceApiUtil.validateJvmOpts(jvmOpts); + CLI.setJVMOpts(jvmOpts); if (hasSliderAMLog4j) { CLI.sysprop(SYSPROP_LOG4J_CONFIGURATION, YARN_SERVICE_LOG4J_FILENAME); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/exceptions/RestApiErrorMessages.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/exceptions/RestApiErrorMessages.java index 57c6449a98..295f14af09 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/exceptions/RestApiErrorMessages.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/exceptions/RestApiErrorMessages.java @@ -127,4 +127,5 @@ public interface RestApiErrorMessages { " not contain a hostname."; String ERROR_KERBEROS_PRINCIPAL_MISSING = "Kerberos principal or keytab is" + " missing."; + String ERROR_JVM_OPTS = "Invalid character in yarn.service.am.java.opts."; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java index 81f84b4549..3780c99c24 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java @@ -64,6 +64,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static org.apache.hadoop.yarn.service.exceptions.RestApiErrorMessages.ERROR_COMP_DOES_NOT_NEED_UPGRADE; import static org.apache.hadoop.yarn.service.exceptions.RestApiErrorMessages.ERROR_COMP_INSTANCE_DOES_NOT_NEED_UPGRADE; @@ -246,6 +248,16 @@ public static void validateAndResolveService(Service service, } } + public static void validateJvmOpts(String jvmOpts) + throws IllegalArgumentException { + Pattern pattern = Pattern.compile("[!~#?@*&%${}()<>\\[\\]|\"\\/,`;]"); + Matcher matcher = pattern.matcher(jvmOpts); + if (matcher.find()) { + throw new IllegalArgumentException( + RestApiErrorMessages.ERROR_JVM_OPTS); + } + } + public static void validateKerberosPrincipal( KerberosPrincipal kerberosPrincipal) throws IOException { if (!StringUtils.isEmpty(kerberosPrincipal.getPrincipalName())) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/utils/TestServiceApiUtil.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/utils/TestServiceApiUtil.java index 3c9b52448d..a93f3d9279 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/utils/TestServiceApiUtil.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/utils/TestServiceApiUtil.java @@ -766,6 +766,12 @@ public void run() { Assert.assertTrue(thread.isAlive()); } + @Test(expected = IllegalArgumentException.class) + public void testJvmOpts() { + String jvmOpts = "`ping -c 3 example.com`"; + ServiceApiUtil.validateJvmOpts(jvmOpts); + } + public static Service createExampleApplication() { Service exampleApp = new Service();