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;
