64位系统运行32位编译的PAM对象报错:无法加载ELFCLASS32的my_pam.so
这个问题我碰到过好几次了,其实原因特别直白:你的系统是64位的,运行的PAM服务(比如sshd)也是64位进程,但你编译出来的my_pam.so是32位的——64位进程根本没法加载32位的共享库,这就是报错PAM unable to dlopen my_pam.so wrong ELF class: ELFCLASS32的核心原因。
下面给你一步步解决的方案:
1. 重新编译64位版本的PAM模块
你之前的编译命令加了-m32强制生成32位目标文件,现在要去掉这个参数,换成64位编译选项(64位系统默认就是64位编译,不过加上-m64更明确):
gcc -O0 -g -m64 -I/ext -I/inc -MD -MP -c -DARCH=x86_64 -o my_pam.o my_pam.c
注意还要把-DARCH=x86改成-DARCH=x86_64,避免代码里的32位相关宏定义生效。
另外,你之前的命令只完成了编译(-c选项是生成目标文件.o),还需要执行链接步骤生成共享库.so:
gcc -m64 -shared -o my_pam.so my_pam.o -lpam
这里-shared是告诉编译器生成共享库,-lpam是链接系统的PAM库,不然可能会出现符号未定义的错误。
2. 验证编译出的模块是64位的
用file命令检查生成的模块架构:
file my_pam.so
如果输出里包含ELF 64-bit LSB shared object,就说明你已经得到了正确的64位PAM模块。
3. 确保模块权限与配置路径正确
你的/etc/pam.d/sshd配置用了绝对路径/root/my_pam.so没问题,但要保证sshd进程能读取这个文件:
chmod 644 /root/my_pam.so
另外,很多系统会把PAM模块统一放在/lib64/security/目录下,你也可以把编译好的my_pam.so移到这个目录,然后修改配置为:
account optional my_pam.so session optional my_pam.so auth optional my_pam.so password optional my_pam.so
这样不用写绝对路径,更符合系统规范。
额外提醒
如果你的my_pam.c代码里有依赖32位环境的逻辑(比如硬编码了指针大小、用int代替size_t处理内存长度),那你需要调整代码适配64位环境,避免出现潜在的内存错误。
内容的提问来源于stack exchange,提问作者Omer Anisfeld

