我正在尝试为 Android 构建 OpenSSH。我正在使用当前(截至撰写本文时)版本,即 9.3p。这是我所做的(主要取自Building OpenSSH for Android):
export ANDROID_NDK_ROOT=$ANDROID_HOME/ndk/21.0.6113669
export PATH=$PATH:$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin
cd ~/src
git clone [email protected]:openssh/openssh-portable.git
cd github-portable
git checkout V_9_3_P1
mkdir -p build/android-arm
autoreconf
# for the moment, build a stripped-down version without zlib and openssl
CHOST="arm-linux-androideabi" \
CHOST2="armv7a-linux-androideabi17" \
CC="${CHOST2}-clang" \
CXX="${CHOST2}-clang++" \
CFLAGS="-DHAVE_ATTRIBUTE__SENTINEL__=1" \
CXXFLAGS="-DHAVE_ATTRIBUTE__SENTINEL__=1" \
RANLIB="${CHOST}-ranlib" \
LD="${CHOST}-ld" \
AR="${CHOST}-ar" \
ARFLAGS="cr" \
CHOST="${CHOST}" \
./configure --host=arm-linux-androideabi --with-libs --without-zlib --without-openssl --prefix=$PWD/build/android-arm
make ssh
CFLAGS
和CXXFLAGS
是另一个构建问题的解决方法,在对上述问题的评论以及https://github.com/android/ndk/issues/1362#issuecomment-712437159中进行了描述。
构建失败并出现错误,显然是由于 OpenSSH 与 NDK 中包含的头文件之一之间存在一些不兼容:
armv7a-linux-androideabi26-clang -DHAVE_ATTRIBUTE__SENTINEL__=1 -pipe -Wunknown-warning-option -Qunused-arguments -Wall -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wsizeof-pointer-memaccess -Wno-pointer-sign -Wno-unused-result -Wimplicit-fallthrough -fno-strict-aliasing -mretpoline -D_FORTIFY_SOURCE=2 -ftrapv -fno-builtin-memset -fstack-protector-strong -fPIC -I. -I.. -I. -I./.. -DHAVE_CONFIG_H -c bsd-misc.c
bsd-misc.c:392:7: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
bzero(void *b, size_t n)
^
bsd-misc.c:392:16: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
bzero(void *b, size_t n)
^
bsd-misc.c:392:1: error: at most one overload for a given name may lack the 'overloadable' attribute
bzero(void *b, size_t n)
^
/home/user149408/tools/android-sdk-linux_86/ndk/21.0.6113669/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/include/strings.h:61:23: note: expanded from macro 'bzero'
#define bzero(b, len) __bionic_bzero((b), (len))
^
/home/user149408/tools/android-sdk-linux_86/ndk/21.0.6113669/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/include/strings.h:62:40: note: previous unmarked overload of function is here
static __inline__ __always_inline void __bionic_bzero(void* b, size_t len) {
^
bsd-misc.c:392:7: error: parameter name omitted
bzero(void *b, size_t n)
^
bsd-misc.c:392:16: error: parameter name omitted
bzero(void *b, size_t n)
^
bsd-misc.c:394:15: error: use of undeclared identifier 'b'
(void)memset(b, 0, n);
^
bsd-misc.c:394:21: error: use of undeclared identifier 'n'
(void)memset(b, 0, n);
^
2 warnings and 5 errors generated.
make[1]: *** [Makefile:106: bsd-misc.o] Error 1
make[1]: Leaving directory '/home/user149408/src/openssh-portable/openbsd-compat'
make: *** [Makefile:199: openbsd-compat/libopenbsd-compat.a] Error 2
可以为主机平台(Ubuntu 22.04 x86_64)进行本机构建。
这是怎么回事,我能做什么?
我刚刚构建了一个成功运行的 openssh-9.4p1 ssh 客户端。 (使用 openssl-3.0.10 和 ldns-1.8.3 因为我需要安全连接,但这与这个问题无关......)
我想你应该声明你有 bzero(),因为 openbsd-compat/explicit_bzero.c 需要 bzero()。 (explicit_bzero.c有3种explicit_bzero()的实现,一种需要explicit_memset(),一种需要memset_s(),一种需要bzero(),而android没有explicit_memset()也没有memset_s())
那么,
cat >zzconfig.cache <<EOF
ac_cv_func_mblen=yes
ac_cv_func_bzero=yes
ac_cv_have_decl_bzero=yes
ac_cv_member_struct_passwd_pw_gecos=no
EOF
(
ac_cv_member_struct_passwd_pw_gecos=no
用于为ILP32构建ssh客户端。LP64应该不需要这个,但我没有检查LP64。请参阅sysroot中的某个地方的pwd.h。)
然后做
configure --cache-file=`pwd`/zzconfig.cache ...
问题是 android bzero() 不是一个函数,而是 __bionic_bzero() 的一个类似函数的宏。所以要么需要在 openbsd-compat/explicit_bzero.c 中修复这个问题
static void (* volatile ssh_bzero)(void *, size_t) = bzero;
或将其添加到某处
#undef bzero
void bzero(void* b, size_t len) {
__bionic_bzero(b, len);
}
我想您遇到的下一个问题是 getrrsetbyname()。 getrrsetbyname() 有两种实现,一种需要 libresolv,一种需要带有 SSL 的 ldns(或者具有 ldns_verify_trusted() 函数的 ldns。)我使用后者,因为 IIRC android 没有可用的 libresolv,而我实际上已经有了后者。
最后,构建还需要 getifaddrs() 和 freeifaddrs() 但你可以在某个地方获取它们。我从 dhcpd for android 那里得到了我的。
并且您有一个可用的 ssh 客户端。
2024-01-31 我不知道我的帖子是否有任何帮助,但无论如何,今天我构建了 LP64 版本的 ssh 客户端,发现 LP64 版本的
struct passwd
确实有 pw_gecos
成员(所以您需要为 LP64 版本设置 ac_cv_member_struct_passwd_pw_gecos=yes
),但是,它的值设置为 NULL,导致 SEGV,至少在 uid = AID_SHELL (2000) 的 Android 8.0 设备上。
所以你需要像这样修复源。
diff -rup openssh-9.6p1/misc.c openssh-9.6p1-droid-p01/misc.c
--- openssh-9.6p1/misc.c 2023-12-18 23:59:50.000000000 +0900
+++ openssh-9.6p1-droid-p01/misc.c 2024-01-31 17:10:46.530066587 +0900
@@ -488,7 +488,7 @@ pwcopy(struct passwd *pw)
copy->pw_name = xstrdup(pw->pw_name);
copy->pw_passwd = xstrdup(pw->pw_passwd == NULL ? "*" : pw->pw_passwd);
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
- copy->pw_gecos = xstrdup(pw->pw_gecos);
+ copy->pw_gecos = xstrdup(pw->pw_gecos == NULL ? "null" : pw->pw_gecos);
#endif
copy->pw_uid = pw->pw_uid;
copy->pw_gid = pw->pw_gid;