various: add -Dbuild-static and alternatives to libc functions

When we try to build with -static, the linker refuses dlopen and
various functions related to nss. This commit adds the basic support
to compile with -static and allow the link to pass.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2026-07-02 17:19:18 +02:00
parent b3749de21c
commit bbeef4b948
7 changed files with 65 additions and 17 deletions
+5
View File
@@ -101,6 +101,10 @@ void block_dlopen(void) {
}
int dlopen_safe(const char *filename, void **ret, const char **reterr_dlerror) {
#if BUILD_STATIC
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"dlopen is not supported in static builds, cannot load %s.", filename);
#else
_cleanup_(dlclosep) void *dl = NULL;
int r;
@@ -142,4 +146,5 @@ int dlopen_safe(const char *filename, void **ret, const char **reterr_dlerror) {
*ret = TAKE_PTR(dl);
return 0;
#endif
}
+43 -13
View File
@@ -1171,6 +1171,9 @@ int lookup_pwent_in_files(
return -ESRCH;
}
#if !BUILD_STATIC
static size_t getpw_buffer_size(void) {
long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
return bufsize <= 0 ? 4096U : (size_t) bufsize;
@@ -1182,15 +1185,25 @@ static bool errno_is_user_doesnt_exist(int error) {
return IN_SET(abs(error), ENOENT, ESRCH, EBADF, EPERM);
}
#endif
int getpwnam_malloc(const char *name, struct passwd **ret) {
/* For static builds use a very simplistic implementation that looks at 'passwd' in /etc/
* and /usr/lib/, and for non-static builds use NSS. The first matching entry wins. The
* same logic is implemented in getpwnam_malloc, getpwuid_malloc, getgrnam_malloc, and
* getgrgid_malloc. */
if (isempty(name))
return -EINVAL;
#if BUILD_STATIC
return lookup_pwent_in_files(PASSWD_FILES, name, UID_INVALID, ret);
#else
size_t bufsize = getpw_buffer_size();
int r;
/* A wrapper around getpwnam_r() that allocates the necessary buffer on the heap. The caller must
* free() the returned structures! */
if (isempty(name))
return -EINVAL;
* free() the returned structure! */
for (;;) {
_cleanup_free_ void *buf = NULL;
@@ -1226,15 +1239,19 @@ int getpwnam_malloc(const char *name, struct passwd **ret) {
return -ENOMEM;
bufsize *= 2;
}
#endif
}
int getpwuid_malloc(uid_t uid, struct passwd **ret) {
size_t bufsize = getpw_buffer_size();
int r;
if (!uid_is_valid(uid))
return -EINVAL;
#if BUILD_STATIC
return lookup_pwent_in_files(PASSWD_FILES, /* name= */ NULL, uid, ret);
#else
size_t bufsize = getpw_buffer_size();
int r;
for (;;) {
_cleanup_free_ void *buf = NULL;
@@ -1267,6 +1284,7 @@ int getpwuid_malloc(uid_t uid, struct passwd **ret) {
return -ENOMEM;
bufsize *= 2;
}
#endif
}
static int copy_struct_group(const struct group *gr, struct group **ret) {
@@ -1427,18 +1445,25 @@ ssize_t lookup_groups_in_files(
return n_arr;
}
#if !BUILD_STATIC
static size_t getgr_buffer_size(void) {
long bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
return bufsize <= 0 ? 4096U : (size_t) bufsize;
}
int getgrnam_malloc(const char *name, struct group **ret) {
size_t bufsize = getgr_buffer_size();
int r;
#endif
int getgrnam_malloc(const char *name, struct group **ret) {
if (isempty(name))
return -EINVAL;
#if BUILD_STATIC
return lookup_grent_in_files(GROUP_FILES, name, GID_INVALID, ret);
#else
size_t bufsize = getgr_buffer_size();
int r;
for (;;) {
_cleanup_free_ void *buf = NULL;
@@ -1471,15 +1496,19 @@ int getgrnam_malloc(const char *name, struct group **ret) {
return -ENOMEM;
bufsize *= 2;
}
#endif
}
int getgrgid_malloc(gid_t gid, struct group **ret) {
size_t bufsize = getgr_buffer_size();
int r;
if (!gid_is_valid(gid))
return -EINVAL;
#if BUILD_STATIC
return lookup_grent_in_files(GROUP_FILES, /* name= */ NULL, gid, ret);
#else
size_t bufsize = getgr_buffer_size();
int r;
for (;;) {
_cleanup_free_ void *buf = NULL;
@@ -1512,4 +1541,5 @@ int getgrgid_malloc(gid_t gid, struct group **ret) {
return -ENOMEM;
bufsize *= 2;
}
#endif
}
+4
View File
@@ -159,6 +159,10 @@ static inline bool hashed_password_is_locked_or_invalid(const char *password) {
return password && password[0] != '$';
}
/* Places where we will try to load account data from */
#define PASSWD_FILES STRV_MAKE("/etc/passwd", "/usr/lib/passwd")
#define GROUP_FILES STRV_MAKE("/etc/group", "/usr/lib/group")
/* A locked *and* invalid password for "struct spwd"'s .sp_pwdp and "struct passwd"'s .pw_passwd field */
#define PASSWORD_LOCKED_AND_INVALID "!*"