Bläddra i källkod

[8.x] Add Hdfs patcher to replace deprecated Subject method (#119781)

Lorenzo Dematté 9 månader sedan
förälder
incheckning
1d7872be05

+ 9 - 2
plugins/repository-hdfs/hadoop-client-api/src/patcher/java/org/elasticsearch/hdfs/patch/HdfsClassPatcher.java

@@ -22,12 +22,19 @@ import java.util.function.Function;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
+import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
+import static org.objectweb.asm.ClassWriter.COMPUTE_MAXS;
+
 public class HdfsClassPatcher {
     static final Map<String, Function<ClassWriter, ClassVisitor>> patchers = Map.of(
         "org/apache/hadoop/util/ShutdownHookManager.class",
         ShutdownHookManagerPatcher::new,
         "org/apache/hadoop/util/Shell.class",
-        ShellPatcher::new
+        ShellPatcher::new,
+        "org/apache/hadoop/security/UserGroupInformation.class",
+        SubjectGetSubjectPatcher::new,
+        "org/apache/hadoop/security/authentication/client/KerberosAuthenticator.class",
+        SubjectGetSubjectPatcher::new
     );
 
     public static void main(String[] args) throws Exception {
@@ -43,7 +50,7 @@ public class HdfsClassPatcher {
                 byte[] classToPatch = jarFile.getInputStream(jarEntry).readAllBytes();
 
                 ClassReader classReader = new ClassReader(classToPatch);
-                ClassWriter classWriter = new ClassWriter(classReader, 0);
+                ClassWriter classWriter = new ClassWriter(classReader, COMPUTE_FRAMES | COMPUTE_MAXS);
                 classReader.accept(patcher.getValue().apply(classWriter), 0);
 
                 Path outputFile = outputDir.resolve(patcher.getKey());

+ 87 - 0
plugins/repository-hdfs/hadoop-client-api/src/patcher/java/org/elasticsearch/hdfs/patch/SubjectGetSubjectPatcher.java

@@ -0,0 +1,87 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the "Elastic License
+ * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
+ * Public License v 1"; you may not use this file except in compliance with, at
+ * your election, the "Elastic License 2.0", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+package org.elasticsearch.hdfs.patch;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
+
+import static org.objectweb.asm.Opcodes.ASM9;
+import static org.objectweb.asm.Opcodes.BIPUSH;
+import static org.objectweb.asm.Opcodes.GOTO;
+import static org.objectweb.asm.Opcodes.IF_ICMPLE;
+import static org.objectweb.asm.Opcodes.INVOKESTATIC;
+import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static org.objectweb.asm.Opcodes.POP;
+
+class SubjectGetSubjectPatcher extends ClassVisitor {
+    SubjectGetSubjectPatcher(ClassWriter classWriter) {
+        super(ASM9, classWriter);
+    }
+
+    @Override
+    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
+        return new ReplaceCallMethodVisitor(super.visitMethod(access, name, descriptor, signature, exceptions), name, access, descriptor);
+    }
+
+    /**
+     * Replaces calls to Subject.getSubject(context); with calls to Subject.current();
+     */
+    private static class ReplaceCallMethodVisitor extends MethodVisitor {
+        private static final String SUBJECT_CLASS_INTERNAL_NAME = "javax/security/auth/Subject";
+        private static final String METHOD_NAME = "getSubject";
+
+        ReplaceCallMethodVisitor(MethodVisitor methodVisitor, String name, int access, String descriptor) {
+            super(ASM9, methodVisitor);
+        }
+
+        @Override
+        public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
+            if (opcode == INVOKESTATIC && SUBJECT_CLASS_INTERNAL_NAME.equals(owner) && METHOD_NAME.equals(name)) {
+                Label olderJdk = new Label();
+                Label end = new Label();
+                mv.visitMethodInsn(
+                    INVOKESTATIC,
+                    Type.getInternalName(Runtime.class),
+                    "version",
+                    Type.getMethodDescriptor(Type.getType(Runtime.Version.class)),
+                    false
+                );
+                mv.visitMethodInsn(
+                    INVOKEVIRTUAL,
+                    Type.getInternalName(Runtime.Version.class),
+                    "feature",
+                    Type.getMethodDescriptor(Type.getType(int.class)),
+                    false
+                );
+                mv.visitIntInsn(BIPUSH, 17);
+                mv.visitJumpInsn(IF_ICMPLE, olderJdk);
+                // Get rid of the extra arg on the stack
+                mv.visitInsn(POP);
+                // Call Subject.current()
+                mv.visitMethodInsn(
+                    INVOKESTATIC,
+                    SUBJECT_CLASS_INTERNAL_NAME,
+                    "current",
+                    Type.getMethodDescriptor(Type.getObjectType(SUBJECT_CLASS_INTERNAL_NAME)),
+                    false
+                );
+                mv.visitJumpInsn(GOTO, end);
+                mv.visitLabel(olderJdk);
+                super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+                mv.visitLabel(end);
+            } else {
+                super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+            }
+        }
+    }
+}