eabdullin
742312a8a9
- Apply 0004-sss_iface-do-not-add-cli_id-to-chain-key.patch - Apply 0005-Accept-krb5-1.21-for-building-the-PAC-plugin.patch - Apply 0006-MC-a-couple-of-additions-to-recover-from-invalid-memory.patch
221 lines
6.0 KiB
Diff
221 lines
6.0 KiB
Diff
From 641e5f73d3bd5b3d32cafd551013d3bfd2a52732 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
|
Date: Fri, 4 Aug 2023 12:19:49 +0200
|
|
Subject: [PATCH] mc: recover from invalid memory cache size
|
|
|
|
If we access the mmap file outside its boundaries a SIGBUS is raised.
|
|
We can now safely recover if the file has unexpected size.
|
|
|
|
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
|
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
---
|
|
src/responder/nss/nsssrv_mmap_cache.c | 86 +++++++++++++++++----
|
|
src/sss_client/nss_mc_common.c | 42 +++++++---
|
|
src/tests/system/tests/test_memory_cache.py | 36 ++++++++-
|
|
3 files changed, 135 insertions(+), 29 deletions(-)
|
|
|
|
diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
|
|
index 12c2996596..bd814f3bc7 100644
|
|
--- a/src/responder/nss/nsssrv_mmap_cache.c
|
|
+++ b/src/responder/nss/nsssrv_mmap_cache.c
|
|
@@ -722,6 +722,57 @@ static errno_t sss_mmap_cache_invalidate(struct sss_mc_ctx *mcc,
|
|
return EOK;
|
|
}
|
|
|
|
+static errno_t sss_mmap_cache_validate_or_reinit(struct sss_mc_ctx **_mcc)
|
|
+{
|
|
+ struct sss_mc_ctx *mcc = *_mcc;
|
|
+ struct stat fdstat;
|
|
+ bool reinit = false;
|
|
+ errno_t ret;
|
|
+
|
|
+ /* No mcc initialized? Memory cache may be disabled. */
|
|
+ if (mcc == NULL || mcc->fd < 0) {
|
|
+ ret = EINVAL;
|
|
+ reinit = false;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ if (fstat(mcc->fd, &fdstat) == -1) {
|
|
+ ret = errno;
|
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
+ "Unable to stat memory cache [file=%s, fd=%d] [%d]: %s\n",
|
|
+ mcc->file, mcc->fd, ret, sss_strerror(ret));
|
|
+ reinit = true;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ if (fdstat.st_nlink == 0) {
|
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Memory cache file was removed\n");
|
|
+ ret = ENOENT;
|
|
+ reinit = true;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ if (fdstat.st_size != mcc->mmap_size) {
|
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
+ "Memory cache is corrupted, invalid size [file=%s, fd=%d, "
|
|
+ "expected_size=%zu, real_size=%zu]\n",
|
|
+ mcc->file, mcc->fd, mcc->mmap_size, fdstat.st_size);
|
|
+ ret = EINVAL;
|
|
+ reinit = true;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ ret = EOK;
|
|
+ reinit = false;
|
|
+
|
|
+done:
|
|
+ if (reinit) {
|
|
+ return sss_mmap_cache_reinit(talloc_parent(mcc), -1, -1, -1, -1, _mcc);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
/***************************************************************************
|
|
* passwd map
|
|
***************************************************************************/
|
|
@@ -744,9 +795,9 @@ errno_t sss_mmap_cache_pw_store(struct sss_mc_ctx **_mcc,
|
|
size_t pos;
|
|
int ret;
|
|
|
|
- if (mcc == NULL) {
|
|
- /* cache not initialized? */
|
|
- return EINVAL;
|
|
+ ret = sss_mmap_cache_validate_or_reinit(&mcc);
|
|
+ if (ret != EOK) {
|
|
+ return ret;
|
|
}
|
|
|
|
ret = snprintf(uidstr, 11, "%ld", (long)uid);
|
|
@@ -815,9 +866,9 @@ errno_t sss_mmap_cache_pw_invalidate_uid(struct sss_mc_ctx *mcc, uid_t uid)
|
|
char *uidstr;
|
|
errno_t ret;
|
|
|
|
- if (mcc == NULL) {
|
|
- /* cache not initialized? */
|
|
- return EINVAL;
|
|
+ ret = sss_mmap_cache_validate_or_reinit(&mcc);
|
|
+ if (ret != EOK) {
|
|
+ return ret;
|
|
}
|
|
|
|
uidstr = talloc_asprintf(NULL, "%ld", (long)uid);
|
|
@@ -886,9 +937,9 @@ int sss_mmap_cache_gr_store(struct sss_mc_ctx **_mcc,
|
|
size_t pos;
|
|
int ret;
|
|
|
|
- if (mcc == NULL) {
|
|
- /* cache not initialized? */
|
|
- return EINVAL;
|
|
+ ret = sss_mmap_cache_validate_or_reinit(&mcc);
|
|
+ if (ret != EOK) {
|
|
+ return ret;
|
|
}
|
|
|
|
ret = snprintf(gidstr, 11, "%ld", (long)gid);
|
|
@@ -953,9 +1004,9 @@ errno_t sss_mmap_cache_gr_invalidate_gid(struct sss_mc_ctx *mcc, gid_t gid)
|
|
char *gidstr;
|
|
errno_t ret;
|
|
|
|
- if (mcc == NULL) {
|
|
- /* cache not initialized? */
|
|
- return EINVAL;
|
|
+ ret = sss_mmap_cache_validate_or_reinit(&mcc);
|
|
+ if (ret != EOK) {
|
|
+ return ret;
|
|
}
|
|
|
|
gidstr = talloc_asprintf(NULL, "%ld", (long)gid);
|
|
@@ -1018,9 +1069,9 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
|
|
size_t pos;
|
|
int ret;
|
|
|
|
- if (mcc == NULL) {
|
|
- /* cache not initialized? */
|
|
- return EINVAL;
|
|
+ ret = sss_mmap_cache_validate_or_reinit(&mcc);
|
|
+ if (ret != EOK) {
|
|
+ return ret;
|
|
}
|
|
|
|
/* array of gids + name + unique_name */
|
|
@@ -1087,8 +1138,9 @@ errno_t sss_mmap_cache_sid_store(struct sss_mc_ctx **_mcc,
|
|
size_t rec_len;
|
|
int ret;
|
|
|
|
- if (mcc == NULL) {
|
|
- return EINVAL;
|
|
+ ret = sss_mmap_cache_validate_or_reinit(&mcc);
|
|
+ if (ret != EOK) {
|
|
+ return ret;
|
|
}
|
|
|
|
ret = snprintf(idkey, sizeof(idkey), "%d-%ld",
|
|
diff --git a/src/sss_client/nss_mc_common.c b/src/sss_client/nss_mc_common.c
|
|
index 3128861bf3..e227c0bae3 100644
|
|
--- a/src/sss_client/nss_mc_common.c
|
|
+++ b/src/sss_client/nss_mc_common.c
|
|
@@ -69,13 +69,43 @@ static void sss_mt_unlock(struct sss_cli_mc_ctx *ctx)
|
|
#endif
|
|
}
|
|
|
|
+static errno_t sss_nss_mc_validate(struct sss_cli_mc_ctx *ctx)
|
|
+{
|
|
+ struct stat fdstat;
|
|
+
|
|
+ /* No mc ctx initialized?*/
|
|
+ if (ctx == NULL || ctx->fd < 0) {
|
|
+ return EINVAL;
|
|
+ }
|
|
+
|
|
+ if (fstat(ctx->fd, &fdstat) == -1) {
|
|
+ return errno;
|
|
+ }
|
|
+
|
|
+ /* Memcache was removed. */
|
|
+ if (fdstat.st_nlink == 0) {
|
|
+ return ENOENT;
|
|
+ }
|
|
+
|
|
+ /* Invalid size. */
|
|
+ if (fdstat.st_size != ctx->mmap_size) {
|
|
+ return ERANGE;
|
|
+ }
|
|
+
|
|
+ return EOK;
|
|
+}
|
|
+
|
|
errno_t sss_nss_check_header(struct sss_cli_mc_ctx *ctx)
|
|
{
|
|
struct sss_mc_header h;
|
|
bool copy_ok;
|
|
int count;
|
|
int ret;
|
|
- struct stat fdstat;
|
|
+
|
|
+ ret = sss_nss_mc_validate(ctx);
|
|
+ if (ret != EOK) {
|
|
+ return ret;
|
|
+ }
|
|
|
|
/* retry barrier protected reading max 5 times then give up */
|
|
for (count = 5; count > 0; count--) {
|
|
@@ -115,16 +145,6 @@ errno_t sss_nss_check_header(struct sss_cli_mc_ctx *ctx)
|
|
}
|
|
}
|
|
|
|
- ret = fstat(ctx->fd, &fdstat);
|
|
- if (ret == -1) {
|
|
- return EIO;
|
|
- }
|
|
-
|
|
- if (fdstat.st_nlink == 0) {
|
|
- /* memory cache was removed; we need to reinitialize it. */
|
|
- return EINVAL;
|
|
- }
|
|
-
|
|
return 0;
|
|
}
|