Kylin V10 aarch64 升级 OpenSSL 1.1.1w 完整技术方案

一、 问题背景

项目 内容
操作系统 Kylin Linux Advanced Server V10 (Tercel)
系统架构 aarch64
编译器版本 GCC 7.3.0
底层 C 库 glibc 2.28(麒麟定制版)
原 OpenSSL 1.1.1f
目标 OpenSSL 1.1.1w
升级目标 独立安装,不替换系统默认 OpenSSL,支撑 OpenSSH 及业务组件

二、 核心难点(Kylin 特有环境)

难点 1:Linker 强制选择静态库 libpthread.a

  • 在 shared library 链接阶段,Kylin 的 ld 即使面对存在的 libpthread.so,且显式指定了 -lpthread-Wl,-Bdynamic,仍会优先选择 /usr/lib64/libpthread.a

难点 2:静态 pthread 在 aarch64 上不可用

  • libpthread.a 被麒麟系统裁剪,缺失关键符号:_dl_pagesize_dl_init_static_tls_dl_wait_lookup_done_dl_stack_flags__pointer_chk_guard_local
  • 后果:导致严重的链接错误 undefined reference to '_dl_pagesize'。这是 glibc 的设计限制,无法通过常规编译参数解决。

难点 3:OpenSSL 1.1.1 构建系统限制

  • ./config LDFLAGS=... 被 OpenSSL 构建脚本明确拒绝。
  • -Wl,-Bdynamic 在 Kylin 环境下会误导 linker。
  • EX_LIBS 不参与最终的链接顺序,无法强制覆盖。

难点 4:运行时 Loader 优先加载系统库

  • 现象:即使编译成功,运行 openssl version -a 仍显示 OpenSSL 1.1.1w (Library: OpenSSL 1.1.1f)
  • 原因/usr/lib64ld.so 缓存中优先级极高,OpenSSL 默认回退到了系统的 libcrypto.so

三、 尝试过的方案与失败原因分析

尝试方案 结果 原因分析
-Wl,-Bdynamic -lpthread 失败 Kylin 的 ld 直接忽略该参数
LDFLAGS=-ldl -lpthread 失败 Linker 依然强制选择 .a 静态库
./config LDFLAGS=... 失败 OpenSSL 构建系统明确禁止此用法
临时移走 libpthread.a 失败 Linker 误判为 static link 导致报错
--sysroot + .a 存在 失败 静态 pthread 本身不可用
shared + zlib-dynamic 失败 仍受底层 Linker 模式影响

四、 最终采用方案:--sysroot + 仅 .so + patchelf

核心思想

在构建期,通过 sysroot 隔离,让 Linker 根本“看不见” libpthread.a,但能正常找到 libpthread.so

方案优势评估

评估维度 结果
是否修改系统文件
是否使用静态 pthread
是否触发 static link
OpenSSL shared build 成功
可脚本化 / 可批量

结论:这是 Kylin V10 + GCC 7.3 环境下,唯一稳定且安全的升级方案。

五、 标准升级流程(已验证)

1️⃣ 前置检查

uname -a
cat /etc/os-release
/usr/bin/openssl version

2️⃣ 准备源码

cd /zoujc
tar -xzf openssl-1.1.1w.tar.gz
cd openssl-1.1.1w

3️⃣ 构建“纯净 sysroot”(关键步骤)

mkdir -p /opt/openssl-lib
cp /lib64/libpthread.so.0 /opt/openssl-lib/libpthread.so
cp /lib64/libdl.so.2      /opt/openssl-lib/libdl.so
cp /lib64/libc.so.6       /opt/openssl-lib/
cp /lib64/ld-linux-aarch64.so.1 /opt/openssl-lib/

4️⃣ 清理旧构建

make distclean 2>/dev/null || true

5️⃣ 设置编译环境

export LDFLAGS="--sysroot=/opt/openssl-lib -L/opt/openssl-lib -ldl -lpthread"

6️⃣ 配置编译参数

./config \
  --prefix=/usr/local/openssl-1.1.1w \
  --openssldir=/usr/local/openssl-1.1.1w/ssl \
  shared \
  zlib-dynamic

验证:执行 grep '^LDFLAGS' Makefile 确认参数已注入。

7️⃣ 编译与安装

make -j1
make install

8️⃣ 修复运行时库加载(必做)

patchelf --set-rpath /usr/local/openssl-1.1.1w/lib64 \
  /usr/local/openssl-1.1.1w/bin/openssl

patchelf --set-rpath /usr/local/openssl-1.1.1w/lib64 \
  /usr/local/openssl-1.1.1w/lib64/libcrypto.so

patchelf --set-rpath /usr/local/openssl-1.1.1w/lib64 \
  /usr/local/openssl-1.1.1w/lib64/libssl.so

9️⃣ 验证结果

/usr/local/openssl-1.1.1w/bin/openssl version -a
ldd /usr/local/openssl-1.1.1w/bin/openssl | grep libcrypto

** 正确预期结果**:
OpenSSL 1.1.1w (Library: OpenSSL 1.1.1w)
libcrypto.so.1.1 => /usr/local/openssl-1.1.1w/lib64/libcrypto.so.1.1

六、 环境恢复(重要)

unset LDFLAGS
rm -rf /opt/openssl-lib

注意:系统文件未被修改,无需恢复 libpthread.a

七、 OpenSSH 对接方案(两种可选)

核心安全警告(保命操作)
在接下来的所有操作中,务必保留您当前已经登录的这个 SSH 窗口绝对不要关闭! 请另外打开一个新的 SSH 窗口来执行以下命令。万一升级过程中出现配置错误或意外,您可以随时通过旧窗口进行回滚,避免服务器失联。

方案一:patchelf(推荐,不影响系统服务)

patchelf --set-rpath /usr/local/openssl-1.1.1w/lib64 \
  /usr/local/openssh/bin/ssh

patchelf --set-rpath /usr/local/openssl-1.1.1w/lib64 \
  /usr/local/openssh/sbin/sshd

️ 方案二:替换系统二进制(高风险,需回滚预案)

# 1. 备份
mv /usr/sbin/sshd /usr/sbin/sshd.bak
mv /usr/bin/ssh /usr/bin/ssh.bak

# 2. 替换
cp /usr/local/openssh/sbin/sshd /usr/sbin/sshd
cp /usr/local/openssh/bin/ssh /usr/bin/ssh

# 3. 检查配置
sshd -t

# 4. 重启并验证
systemctl restart sshd
ssh -V

八、 一键自动化脚本(生产可用)

#!/bin/bash
set -e

echo "=== OpenSSL 1.1.1w upgrade (Kylin V10 aarch64) ==="
yum install -y patchelf gcc perl

cd /zoujc
tar -xzf openssl-1.1.1w.tar.gz
cd openssl-1.1.1w

mkdir -p /opt/openssl-lib
cp /lib64/libpthread.so.0 /opt/openssl-lib/libpthread.so
cp /lib64/libdl.so.2      /opt/openssl-lib/libdl.so
cp /lib64/libc.so.6       /opt/openssl-lib/
cp /lib64/ld-linux-aarch64.so.1 /opt/openssl-lib/

make distclean || true

export LDFLAGS="--sysroot=/opt/openssl-lib -L/opt/openssl-lib -ldl -lpthread"

./config \
  --prefix=/usr/local/openssl-1.1.1w \
  --openssldir=/usr/local/openssl-1.1.1w/ssl \
  shared zlib-dynamic

make -j1
make install

patchelf --set-rpath /usr/local/openssl-1.1.1w/lib64 \
  /usr/local/openssl-1.1.1w/bin/openssl

patchelf --set-rpath /usr/local/openssl-1.1.1w/lib64 \
  /usr/local/openssl-1.1.1w/lib64/libcrypto.so

patchelf --set-rpath /usr/local/openssl-1.1.1w/lib64 \
  /usr/local/openssl-1.1.1w/lib64/libssl.so

unset LDFLAGS
rm -rf /opt/openssl-lib

echo "=== Verification ==="
/usr/local/openssl-1.1.1w/bin/openssl version -a

九、 一句话总结

Kylin V10 aarch64 + GCC 7.3 下,OpenSSL 1.1.1w 的唯一稳定升级路径是:
sysroot 隔离 .a
仅暴露 .so
patchelf 固化 rpath
不修改系统库

该方案已在生产环境验证通过,可安全批量推广。


Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐