Skip to content

Commit 1d7872b

Browse files
authored
[8.x] Add Hdfs patcher to replace deprecated Subject method (elastic#119781)
1 parent 1ae6a08 commit 1d7872b

File tree

2 files changed

+96
-2
lines changed

2 files changed

+96
-2
lines changed

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,19 @@
2222
import java.util.jar.JarEntry;
2323
import java.util.jar.JarFile;
2424

25+
import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
26+
import static org.objectweb.asm.ClassWriter.COMPUTE_MAXS;
27+
2528
public class HdfsClassPatcher {
2629
static final Map<String, Function<ClassWriter, ClassVisitor>> patchers = Map.of(
2730
"org/apache/hadoop/util/ShutdownHookManager.class",
2831
ShutdownHookManagerPatcher::new,
2932
"org/apache/hadoop/util/Shell.class",
30-
ShellPatcher::new
33+
ShellPatcher::new,
34+
"org/apache/hadoop/security/UserGroupInformation.class",
35+
SubjectGetSubjectPatcher::new,
36+
"org/apache/hadoop/security/authentication/client/KerberosAuthenticator.class",
37+
SubjectGetSubjectPatcher::new
3138
);
3239

3340
public static void main(String[] args) throws Exception {
@@ -43,7 +50,7 @@ public static void main(String[] args) throws Exception {
4350
byte[] classToPatch = jarFile.getInputStream(jarEntry).readAllBytes();
4451

4552
ClassReader classReader = new ClassReader(classToPatch);
46-
ClassWriter classWriter = new ClassWriter(classReader, 0);
53+
ClassWriter classWriter = new ClassWriter(classReader, COMPUTE_FRAMES | COMPUTE_MAXS);
4754
classReader.accept(patcher.getValue().apply(classWriter), 0);
4855

4956
Path outputFile = outputDir.resolve(patcher.getKey());
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.hdfs.patch;
11+
12+
import org.objectweb.asm.ClassVisitor;
13+
import org.objectweb.asm.ClassWriter;
14+
import org.objectweb.asm.Label;
15+
import org.objectweb.asm.MethodVisitor;
16+
import org.objectweb.asm.Type;
17+
18+
import static org.objectweb.asm.Opcodes.ASM9;
19+
import static org.objectweb.asm.Opcodes.BIPUSH;
20+
import static org.objectweb.asm.Opcodes.GOTO;
21+
import static org.objectweb.asm.Opcodes.IF_ICMPLE;
22+
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
23+
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
24+
import static org.objectweb.asm.Opcodes.POP;
25+
26+
class SubjectGetSubjectPatcher extends ClassVisitor {
27+
SubjectGetSubjectPatcher(ClassWriter classWriter) {
28+
super(ASM9, classWriter);
29+
}
30+
31+
@Override
32+
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
33+
return new ReplaceCallMethodVisitor(super.visitMethod(access, name, descriptor, signature, exceptions), name, access, descriptor);
34+
}
35+
36+
/**
37+
* Replaces calls to Subject.getSubject(context); with calls to Subject.current();
38+
*/
39+
private static class ReplaceCallMethodVisitor extends MethodVisitor {
40+
private static final String SUBJECT_CLASS_INTERNAL_NAME = "javax/security/auth/Subject";
41+
private static final String METHOD_NAME = "getSubject";
42+
43+
ReplaceCallMethodVisitor(MethodVisitor methodVisitor, String name, int access, String descriptor) {
44+
super(ASM9, methodVisitor);
45+
}
46+
47+
@Override
48+
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
49+
if (opcode == INVOKESTATIC && SUBJECT_CLASS_INTERNAL_NAME.equals(owner) && METHOD_NAME.equals(name)) {
50+
Label olderJdk = new Label();
51+
Label end = new Label();
52+
mv.visitMethodInsn(
53+
INVOKESTATIC,
54+
Type.getInternalName(Runtime.class),
55+
"version",
56+
Type.getMethodDescriptor(Type.getType(Runtime.Version.class)),
57+
false
58+
);
59+
mv.visitMethodInsn(
60+
INVOKEVIRTUAL,
61+
Type.getInternalName(Runtime.Version.class),
62+
"feature",
63+
Type.getMethodDescriptor(Type.getType(int.class)),
64+
false
65+
);
66+
mv.visitIntInsn(BIPUSH, 17);
67+
mv.visitJumpInsn(IF_ICMPLE, olderJdk);
68+
// Get rid of the extra arg on the stack
69+
mv.visitInsn(POP);
70+
// Call Subject.current()
71+
mv.visitMethodInsn(
72+
INVOKESTATIC,
73+
SUBJECT_CLASS_INTERNAL_NAME,
74+
"current",
75+
Type.getMethodDescriptor(Type.getObjectType(SUBJECT_CLASS_INTERNAL_NAME)),
76+
false
77+
);
78+
mv.visitJumpInsn(GOTO, end);
79+
mv.visitLabel(olderJdk);
80+
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
81+
mv.visitLabel(end);
82+
} else {
83+
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
84+
}
85+
}
86+
}
87+
}

0 commit comments

Comments
 (0)