EVP CIPHER CTX block size 报错
# 1. 报错背景与现象
在编译完成后执行如下命令:
hadoop checknative -a
1
输出日志中可见:
25/08/13 05:51:30 INFO bzip2.Bzip2Factory: Successfully loaded & initialized native-bzip2 library system-native
25/08/13 05:51:30 INFO zlib.ZlibFactory: Successfully loaded & initialized native-zlib library
25/08/13 05:51:30 WARN erasurecode.ErasureCodeNative: ISA-L support is not available in your platform... using builtin-java codec where applicable
25/08/13 05:51:30 INFO nativeio.NativeIO: The native code was built without PMDK support.
Native library checking:
hadoop: true /usr/bigtop/3.2.0/usr/lib/hadoop/lib/native/libhadoop.so.1.0.0
zlib: true /lib/x86_64-linux-gnu/libz.so.1
zstd : false
bzip2: true /lib/x86_64-linux-gnu/libbz2.so.1
openssl: false EVP_CIPHER_CTX_block_size
ISA-L: false libhadoop was built without ISA-L support
PMDK: false The native code was built without PMDK support.
25/08/13 05:51:30 INFO util.ExitUtil: Exiting with status 1: ExitException
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
关键问题点:
openssl: false EVP_CIPHER_CTX_block_size
# 2. 问题原因分析
该问题出现在 Hadoop 3.3.4 的源码文件:
hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/crypto/OpensslCipher.c
1
在旧版本 OpenSSL(1.1.x)中,EVP_CIPHER_CTX_block_size
可以直接使用,但在 OpenSSL 3.x 环境下该符号已被替换为:
EVP_CIPHER_CTX_get_block_size
EVP_CIPHER_CTX_is_encrypting
直接调用旧符号会导致 dlsym
查找失败,从而触发 checknative
检测 openssl=false。
# 3. 解决方案思路
- 在原始动态加载代码基础上,引入一个
load_sym2
方法,优先加载 OpenSSL 3.x 符号,找不到再回退到 OpenSSL 1.1.x 符号。 - 对
EVP_CIPHER_CTX_block_size
和EVP_CIPHER_CTX_encrypting
两个函数分别处理,确保兼容新旧版本 API。
# 4. 补丁 diff
以下为经过修改的 diff 文件,应用后重新编译即可解决:
Subject: [PATCH] meta:处理openssl
---
Index: hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/crypto/OpensslCipher.c
===================================================================
+#include <dlfcn.h> /* for dlopen/dlsym/dladdr */
+
+/* 优先尝试 OpenSSL 3 符号,找不到再回退到 OpenSSL 1.1 符号 */
+static void *load_sym2(void *handle, const char *name_new, const char *name_old) {
+ void *p = dlsym(handle, name_new);
+ if (!p) p = dlsym(handle, name_old);
+ return p;
+}
...
- LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_block_size, env, openssl, \
- "EVP_CIPHER_CTX_block_size");
+
+ /* OpenSSL 3: EVP_CIPHER_CTX_block_size -> EVP_CIPHER_CTX_get_block_size */
+ dlsym_EVP_CIPHER_CTX_block_size =
+ (int (*)(const EVP_CIPHER_CTX *)) load_sym2(openssl,
+ "EVP_CIPHER_CTX_get_block_size", "EVP_CIPHER_CTX_block_size");
+ if (!dlsym_EVP_CIPHER_CTX_block_size) {
+ THROW(env, "java/lang/UnsatisfiedLinkError",
+ "Missing EVP_CIPHER_CTX_(get_)block_size");
+ return;
+ }
...
- LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_encrypting, env, openssl, \
- "EVP_CIPHER_CTX_encrypting");
+
+ /* OpenSSL 3: EVP_CIPHER_CTX_encrypting -> EVP_CIPHER_CTX_is_encrypting */
+ dlsym_EVP_CIPHER_CTX_encrypting =
+ (int (*)(const EVP_CIPHER_CTX *)) load_sym2(openssl,
+ "EVP_CIPHER_CTX_is_encrypting", "EVP_CIPHER_CTX_encrypting");
+ if (!dlsym_EVP_CIPHER_CTX_encrypting) {
+ THROW(env, "java/lang/UnsatisfiedLinkError",
+ "Missing EVP_CIPHER_CTX_(is_)encrypting");
+ return;
+ }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
- 01
- [/metrics/aggregated] — 聚合数据范围 检查点09-19
- 02
- [/metrics] — 反向分析接口参数 请求抓包09-17
- 03
- [/metrics] — 普通指标写入方法 POST09-17