- Apply 0007-SSS_CLIENT-replace-__thread-with-pthread_-specific.patch
This commit is contained in:
parent
742312a8a9
commit
c7d052497b
@ -0,0 +1,384 @@
|
||||
From b0212b04f109875936612a52a7b30a80e5a85ee5 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Tikhonov <atikhono@redhat.com>
|
||||
Date: Mon, 23 Oct 2023 16:11:17 +0200
|
||||
Subject: [PATCH] SSS_CLIENT: replace `__thread` with `pthread_*specific()`
|
||||
|
||||
in sss_client code to properly handle OOM condition (with `__thread`
|
||||
glibc terminates process in this case).
|
||||
|
||||
Solution relies on the fact that `sss_cli_check_socket()` is always
|
||||
executed first, before touching socket.
|
||||
Nonetheless, there are sanity guards in setters/getters just in case.
|
||||
|
||||
It's possible to move context initialization code into a separate
|
||||
function and call it in every getter/setter, but probably not worth it.
|
||||
|
||||
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
||||
Reviewed-by: Carlos O'Donell <codonell@redhat.com>
|
||||
---
|
||||
src/sss_client/common.c | 202 ++++++++++++++++++++++++++++++++--------
|
||||
1 file changed, 164 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
|
||||
index c80c8e74b7..1075af9419 100644
|
||||
--- a/src/sss_client/common.c
|
||||
+++ b/src/sss_client/common.c
|
||||
@@ -62,22 +62,31 @@
|
||||
|
||||
/* common functions */
|
||||
|
||||
+static int sss_cli_sd_get(void);
|
||||
+static void sss_cli_sd_set(int sd);
|
||||
+static const struct stat *sss_cli_sb_get(void);
|
||||
+static int sss_cli_sb_set_by_sd(int sd);
|
||||
+
|
||||
#ifdef HAVE_PTHREAD_EXT
|
||||
static pthread_key_t sss_sd_key;
|
||||
static pthread_once_t sss_sd_key_init = PTHREAD_ONCE_INIT;
|
||||
static atomic_bool sss_sd_key_initialized = false;
|
||||
-static __thread int sss_cli_sd = -1; /* the sss client socket descriptor */
|
||||
-static __thread struct stat sss_cli_sb; /* the sss client stat buffer */
|
||||
+struct sss_socket_descriptor_t {
|
||||
+ int sd;
|
||||
+ struct stat sb;
|
||||
+};
|
||||
#else
|
||||
-static int sss_cli_sd = -1; /* the sss client socket descriptor */
|
||||
-static struct stat sss_cli_sb; /* the sss client stat buffer */
|
||||
+static int _sss_cli_sd = -1; /* the sss client socket descriptor */
|
||||
+static struct stat _sss_cli_sb; /* the sss client stat buffer */
|
||||
#endif
|
||||
|
||||
void sss_cli_close_socket(void)
|
||||
{
|
||||
- if (sss_cli_sd != -1) {
|
||||
- close(sss_cli_sd);
|
||||
- sss_cli_sd = -1;
|
||||
+ int sd = sss_cli_sd_get();
|
||||
+
|
||||
+ if (sd != -1) {
|
||||
+ close(sd);
|
||||
+ sss_cli_sd_set(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,25 +94,30 @@ void sss_cli_close_socket(void)
|
||||
static void sss_at_thread_exit(void *v)
|
||||
{
|
||||
sss_cli_close_socket();
|
||||
+ free(v);
|
||||
+ pthread_setspecific(sss_sd_key, NULL);
|
||||
}
|
||||
|
||||
static void init_sd_key(void)
|
||||
{
|
||||
- pthread_key_create(&sss_sd_key, sss_at_thread_exit);
|
||||
- sss_sd_key_initialized = true;
|
||||
+ if (pthread_key_create(&sss_sd_key, sss_at_thread_exit) == 0) {
|
||||
+ sss_sd_key_initialized = true;
|
||||
+ }
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_FUNCTION_ATTRIBUTE_DESTRUCTOR
|
||||
__attribute__((destructor)) void sss_at_lib_unload(void)
|
||||
{
|
||||
+ sss_cli_close_socket();
|
||||
#ifdef HAVE_PTHREAD_EXT
|
||||
if (sss_sd_key_initialized) {
|
||||
sss_sd_key_initialized = false;
|
||||
+ free(pthread_getspecific(sss_sd_key));
|
||||
+ pthread_setspecific(sss_sd_key, NULL);
|
||||
pthread_key_delete(sss_sd_key);
|
||||
}
|
||||
#endif
|
||||
- sss_cli_close_socket();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -137,7 +151,7 @@ static enum sss_status sss_cli_send_req(enum sss_cli_command cmd,
|
||||
int res, error;
|
||||
|
||||
*errnop = 0;
|
||||
- pfd.fd = sss_cli_sd;
|
||||
+ pfd.fd = sss_cli_sd_get();
|
||||
pfd.events = POLLOUT;
|
||||
|
||||
do {
|
||||
@@ -163,7 +177,7 @@ static enum sss_status sss_cli_send_req(enum sss_cli_command cmd,
|
||||
*errnop = EPIPE;
|
||||
} else if (pfd.revents & POLLNVAL) {
|
||||
/* Invalid request: fd is not opened */
|
||||
- sss_cli_sd = -1;
|
||||
+ sss_cli_sd_set(-1);
|
||||
*errnop = EPIPE;
|
||||
} else if (!(pfd.revents & POLLOUT)) {
|
||||
*errnop = EBUSY;
|
||||
@@ -180,13 +194,13 @@ static enum sss_status sss_cli_send_req(enum sss_cli_command cmd,
|
||||
|
||||
errno = 0;
|
||||
if (datasent < SSS_NSS_HEADER_SIZE) {
|
||||
- res = send(sss_cli_sd,
|
||||
+ res = send(sss_cli_sd_get(),
|
||||
(char *)header + datasent,
|
||||
SSS_NSS_HEADER_SIZE - datasent,
|
||||
SSS_DEFAULT_WRITE_FLAGS);
|
||||
} else {
|
||||
rdsent = datasent - SSS_NSS_HEADER_SIZE;
|
||||
- res = send(sss_cli_sd,
|
||||
+ res = send(sss_cli_sd_get(),
|
||||
(const char *)rd->data + rdsent,
|
||||
rd->len - rdsent,
|
||||
SSS_DEFAULT_WRITE_FLAGS);
|
||||
@@ -249,7 +263,7 @@ static enum sss_status sss_cli_recv_rep(enum sss_cli_command cmd,
|
||||
int bufrecv;
|
||||
int res, error;
|
||||
|
||||
- pfd.fd = sss_cli_sd;
|
||||
+ pfd.fd = sss_cli_sd_get();
|
||||
pfd.events = POLLIN;
|
||||
|
||||
do {
|
||||
@@ -278,7 +292,7 @@ static enum sss_status sss_cli_recv_rep(enum sss_cli_command cmd,
|
||||
*errnop = EPIPE;
|
||||
} else if (pfd.revents & POLLNVAL) {
|
||||
/* Invalid request: fd is not opened */
|
||||
- sss_cli_sd = -1;
|
||||
+ sss_cli_sd_set(-1);
|
||||
*errnop = EPIPE;
|
||||
} else if (!(pfd.revents & POLLIN)) {
|
||||
*errnop = EBUSY;
|
||||
@@ -296,12 +310,12 @@ static enum sss_status sss_cli_recv_rep(enum sss_cli_command cmd,
|
||||
|
||||
errno = 0;
|
||||
if (datarecv < SSS_NSS_HEADER_SIZE) {
|
||||
- res = read(sss_cli_sd,
|
||||
+ res = read(sss_cli_sd_get(),
|
||||
(char *)header + datarecv,
|
||||
SSS_NSS_HEADER_SIZE - datarecv);
|
||||
} else {
|
||||
bufrecv = datarecv - SSS_NSS_HEADER_SIZE;
|
||||
- res = read(sss_cli_sd,
|
||||
+ res = read(sss_cli_sd_get(),
|
||||
(char *) buf + bufrecv,
|
||||
header[0] - datarecv);
|
||||
}
|
||||
@@ -591,16 +605,6 @@ static int sss_cli_open_socket(int *errnop, const char *socket_name, int timeout
|
||||
return -1;
|
||||
}
|
||||
|
||||
-#ifdef HAVE_PTHREAD_EXT
|
||||
- pthread_once(&sss_sd_key_init, init_sd_key); /* once for all threads */
|
||||
-
|
||||
- /* It actually doesn't matter what value to set for a key.
|
||||
- * The only important thing: key must be non-NULL to ensure
|
||||
- * destructor is executed at thread exit.
|
||||
- */
|
||||
- pthread_setspecific(sss_sd_key, &sss_cli_sd);
|
||||
-#endif
|
||||
-
|
||||
/* set as non-blocking, close on exec, and make sure standard
|
||||
* descriptors are not used */
|
||||
sd = make_safe_fd(sd);
|
||||
@@ -670,7 +674,7 @@ static int sss_cli_open_socket(int *errnop, const char *socket_name, int timeout
|
||||
return -1;
|
||||
}
|
||||
|
||||
- ret = fstat(sd, &sss_cli_sb);
|
||||
+ ret = sss_cli_sb_set_by_sd(sd);
|
||||
if (ret != 0) {
|
||||
close(sd);
|
||||
return -1;
|
||||
@@ -686,33 +690,69 @@ static enum sss_status sss_cli_check_socket(int *errnop,
|
||||
static pid_t mypid_s;
|
||||
static ino_t myself_ino;
|
||||
struct stat mypid_sb, myself_sb;
|
||||
+ const struct stat *sss_cli_sb = NULL;
|
||||
pid_t mypid_d;
|
||||
int mysd;
|
||||
int ret;
|
||||
+#ifdef HAVE_PTHREAD_EXT
|
||||
+ struct sss_socket_descriptor_t *descriptor = NULL;
|
||||
+
|
||||
+ ret = pthread_once(&sss_sd_key_init, init_sd_key); /* once for all threads */
|
||||
+ if (ret != 0) {
|
||||
+ *errnop = EFAULT;
|
||||
+ return SSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+ if (!sss_sd_key_initialized) {
|
||||
+ /* pthread_once::init_sd_key::pthread_key_create failed -- game over? */
|
||||
+ *errnop = EFAULT;
|
||||
+ return SSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+
|
||||
+ if (pthread_getspecific(sss_sd_key) == NULL) { /* for every thread */
|
||||
+ descriptor = (struct sss_socket_descriptor_t *)
|
||||
+ calloc(1, sizeof(struct sss_socket_descriptor_t));
|
||||
+ if (descriptor == NULL) {
|
||||
+ *errnop = ENOMEM;
|
||||
+ return SSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+ descriptor->sd = -1;
|
||||
+ ret = pthread_setspecific(sss_sd_key, descriptor);
|
||||
+ if (ret != 0) {
|
||||
+ free(descriptor);
|
||||
+ *errnop = ENOMEM;
|
||||
+ return SSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+ sss_cli_sb = sss_cli_sb_get();
|
||||
+ if (sss_cli_sb == NULL) {
|
||||
+ *errnop = EFAULT;
|
||||
+ return SSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
|
||||
ret = lstat("/proc/self/", &myself_sb);
|
||||
mypid_d = getpid();
|
||||
if (mypid_d != mypid_s || (ret == 0 && myself_sb.st_ino != myself_ino)) {
|
||||
- ret = fstat(sss_cli_sd, &mypid_sb);
|
||||
+ ret = fstat(sss_cli_sd_get(), &mypid_sb);
|
||||
if (ret == 0) {
|
||||
if (S_ISSOCK(mypid_sb.st_mode) &&
|
||||
- mypid_sb.st_dev == sss_cli_sb.st_dev &&
|
||||
- mypid_sb.st_ino == sss_cli_sb.st_ino) {
|
||||
+ mypid_sb.st_dev == sss_cli_sb->st_dev &&
|
||||
+ mypid_sb.st_ino == sss_cli_sb->st_ino) {
|
||||
sss_cli_close_socket();
|
||||
}
|
||||
}
|
||||
- sss_cli_sd = -1;
|
||||
+ sss_cli_sd_set(-1);
|
||||
mypid_s = mypid_d;
|
||||
myself_ino = myself_sb.st_ino;
|
||||
}
|
||||
|
||||
/* check if the socket has been closed on the other side */
|
||||
- if (sss_cli_sd != -1) {
|
||||
+ if (sss_cli_sd_get() != -1) {
|
||||
struct pollfd pfd;
|
||||
int res, error;
|
||||
|
||||
*errnop = 0;
|
||||
- pfd.fd = sss_cli_sd;
|
||||
+ pfd.fd = sss_cli_sd_get();
|
||||
pfd.events = POLLIN | POLLOUT;
|
||||
|
||||
do {
|
||||
@@ -738,7 +778,7 @@ static enum sss_status sss_cli_check_socket(int *errnop,
|
||||
*errnop = EPIPE;
|
||||
} else if (pfd.revents & POLLNVAL) {
|
||||
/* Invalid request: fd is not opened */
|
||||
- sss_cli_sd = -1;
|
||||
+ sss_cli_sd_set(-1);
|
||||
*errnop = EPIPE;
|
||||
} else if (!(pfd.revents & (POLLIN | POLLOUT))) {
|
||||
*errnop = EBUSY;
|
||||
@@ -760,7 +800,7 @@ static enum sss_status sss_cli_check_socket(int *errnop,
|
||||
return SSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
- sss_cli_sd = mysd;
|
||||
+ sss_cli_sd_set(mysd);
|
||||
|
||||
if (sss_cli_check_version(socket_name, timeout)) {
|
||||
return SSS_STATUS_SUCCESS;
|
||||
@@ -1015,7 +1055,7 @@ int sss_pam_make_request(enum sss_cli_command cmd,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- error = check_server_cred(sss_cli_sd);
|
||||
+ error = check_server_cred(sss_cli_sd_get());
|
||||
if (error != 0) {
|
||||
sss_cli_close_socket();
|
||||
*errnop = error;
|
||||
@@ -1307,3 +1347,89 @@ errno_t sss_readrep_copy_string(const char *in,
|
||||
|
||||
return EOK;
|
||||
}
|
||||
+
|
||||
+#ifdef HAVE_PTHREAD_EXT
|
||||
+
|
||||
+static int sss_cli_sd_get(void)
|
||||
+{
|
||||
+ if (!sss_sd_key_initialized) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ struct sss_socket_descriptor_t *descriptor = pthread_getspecific(sss_sd_key);
|
||||
+
|
||||
+ if (descriptor == NULL) { /* sanity check */
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return descriptor->sd;
|
||||
+}
|
||||
+
|
||||
+static void sss_cli_sd_set(int sd)
|
||||
+{
|
||||
+ if (!sss_sd_key_initialized) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ struct sss_socket_descriptor_t *descriptor = pthread_getspecific(sss_sd_key);
|
||||
+
|
||||
+ if (descriptor == NULL) { /* sanity check */
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ descriptor->sd = sd;
|
||||
+}
|
||||
+
|
||||
+static const struct stat *sss_cli_sb_get(void)
|
||||
+{
|
||||
+ if (!sss_sd_key_initialized) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ struct sss_socket_descriptor_t *descriptor = pthread_getspecific(sss_sd_key);
|
||||
+
|
||||
+ if (descriptor == NULL) { /* sanity check */
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return &descriptor->sb;
|
||||
+}
|
||||
+
|
||||
+static int sss_cli_sb_set_by_sd(int sd)
|
||||
+{
|
||||
+ if (!sss_sd_key_initialized) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ struct sss_socket_descriptor_t *descriptor = pthread_getspecific(sss_sd_key);
|
||||
+
|
||||
+ if (descriptor == NULL) { /* sanity check */
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return fstat(sd, &descriptor->sb);
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+
|
||||
+static int sss_cli_sd_get(void)
|
||||
+{
|
||||
+ return _sss_cli_sd;
|
||||
+}
|
||||
+
|
||||
+static void sss_cli_sd_set(int sd)
|
||||
+{
|
||||
+ _sss_cli_sd = sd;
|
||||
+}
|
||||
+
|
||||
+static const struct stat *sss_cli_sb_get(void)
|
||||
+{
|
||||
+ return &_sss_cli_sb;
|
||||
+}
|
||||
+
|
||||
+static int sss_cli_sb_set_by_sd(int sd)
|
||||
+{
|
||||
+ return fstat(sd, &_sss_cli_sb);
|
||||
+}
|
||||
+
|
||||
+#endif
|
@ -27,7 +27,7 @@
|
||||
|
||||
Name: sssd
|
||||
Version: 2.9.1
|
||||
Release: 4%{?dist}.alma.1
|
||||
Release: 4%{?dist}.1.alma.1
|
||||
Summary: System Security Services Daemon
|
||||
License: GPLv3+
|
||||
URL: https://github.com/SSSD/sssd/
|
||||
@ -46,7 +46,8 @@ Patch0004: 0004-sss_iface-do-not-add-cli_id-to-chain-key.patch
|
||||
Patch0005: 0005-Accept-krb5-1.21-for-building-the-PAC-plugin.patch
|
||||
# https://github.com/SSSD/sssd/commit/88d8afbb115f18007dcc11f7ebac1b238c3ebd98
|
||||
Patch0006: 0006-MC-a-couple-of-additions-to-recover-from-invalid-memory.patch
|
||||
|
||||
# https://github.com/SSSD/sssd/commit/b0212b04f109875936612a52a7b30a80e5a85ee5
|
||||
Patch0007: 0007-SSS_CLIENT-replace-__thread-with-pthread_-specific.patch
|
||||
### Dependencies ###
|
||||
|
||||
Requires: sssd-ad = %{version}-%{release}
|
||||
@ -1072,6 +1073,9 @@ fi
|
||||
%systemd_postun_with_restart sssd.service
|
||||
|
||||
%changelog
|
||||
* Wed Dec 13 2023 Eduard Abdullin <eabdullin@almalinux.org> - 2.9.1-4.1.alma.1
|
||||
- Apply 0007-SSS_CLIENT-replace-__thread-with-pthread_-specific.patch
|
||||
|
||||
* Wed Nov 08 2023 Eduard Abdullin <eabdullin@almalinux.org> - 2.9.1-4.alma.1
|
||||
- Apply 0003-mc-recover-from-invalid-memory-cache-size.patch
|
||||
- Apply 0004-sss_iface-do-not-add-cli_id-to-chain-key.patch
|
||||
|
Loading…
Reference in New Issue
Block a user