67 lines
1.9 KiB
Diff
67 lines
1.9 KiB
Diff
From bc1415317379c45b08ac6f8eb98698ca2df9b78c Mon Sep 17 00:00:00 2001
|
|
From: Ivan Pravdin <ipravdin.official@gmail.com>
|
|
Date: Sat, 22 Mar 2025 19:31:02 -0400
|
|
Subject: [PATCH] criu: fix log_keep_err signal deadlock
|
|
|
|
When using pr_err in signal handler, locking is used
|
|
in an unsafe manner. If another signal happens while holding the
|
|
lock, deadlock can happen.
|
|
|
|
To fix this, we can introduce mutex_trylock similar to
|
|
pthread_mutex_trylock that returns immediately. Due to the fact
|
|
that lock is used only for writing first_err, this change garantees
|
|
that deadlock cannot happen.
|
|
|
|
Fixes: #358
|
|
|
|
Signed-off-by: Ivan Pravdin <ipravdin.official@gmail.com>
|
|
---
|
|
criu/log.c | 9 +++++----
|
|
include/common/lock.h | 6 ++++++
|
|
2 files changed, 11 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/criu/log.c b/criu/log.c
|
|
index 89ae8f8205..70e267fd65 100644
|
|
--- a/criu/log.c
|
|
+++ b/criu/log.c
|
|
@@ -132,10 +132,11 @@ static void log_note_err(char *msg)
|
|
* anyway, so it doesn't make much sense to try hard
|
|
* and optimize this out.
|
|
*/
|
|
- mutex_lock(&first_err->l);
|
|
- if (first_err->s[0] == '\0')
|
|
- __strlcpy(first_err->s, msg, sizeof(first_err->s));
|
|
- mutex_unlock(&first_err->l);
|
|
+ if (mutex_trylock(&first_err->l)) {
|
|
+ if (first_err->s[0] == '\0')
|
|
+ __strlcpy(first_err->s, msg, sizeof(first_err->s));
|
|
+ mutex_unlock(&first_err->l);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
diff --git a/include/common/lock.h b/include/common/lock.h
|
|
index ccfa468b83..4733d72870 100644
|
|
--- a/include/common/lock.h
|
|
+++ b/include/common/lock.h
|
|
@@ -2,6 +2,7 @@
|
|
#define __CR_COMMON_LOCK_H__
|
|
|
|
#include <stdint.h>
|
|
+#include <stdbool.h>
|
|
#include <linux/futex.h>
|
|
#include <sys/time.h>
|
|
#include <limits.h>
|
|
@@ -162,6 +163,11 @@ static inline void mutex_lock(mutex_t *m)
|
|
}
|
|
}
|
|
|
|
+static inline bool mutex_trylock(mutex_t *m)
|
|
+{
|
|
+ return atomic_inc_return(&m->raw) == 1;
|
|
+}
|
|
+
|
|
static inline void mutex_unlock(mutex_t *m)
|
|
{
|
|
uint32_t c = 0;
|