Merge remote-tracking branch 'goog/upstream-master' into merge-citadel-mutex

* goog/upstream-master:
  Datagram: add mutex to protect data buffers

Bug: 111653201
Test: try and race transactions, they no longer fail
Change-Id: Ibec950c3e27c3cd91e25bb8dbe6324562d588e50
diff --git a/citadel/libnos_datagram/citadel.c b/citadel/libnos_datagram/citadel.c
index cea0a42..f2ba9ba 100644
--- a/citadel/libnos_datagram/citadel.c
+++ b/citadel/libnos_datagram/citadel.c
@@ -24,6 +24,7 @@
 #include <getopt.h>
 #include <linux/types.h>
 #include <poll.h>
+#include <pthread.h>
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -47,6 +48,7 @@
 
 #define DEV_CITADEL "/dev/citadel0"
 
+static pthread_mutex_t in_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
 static uint8_t in_buf[MAX_DEVICE_TRANSFER];
 static int read_datagram(void *ctx, uint32_t command, uint8_t *buf, uint32_t len) {
     struct citadel_ioc_tpm_datagram dg = {
@@ -74,17 +76,30 @@
         return -E2BIG;
     }
 
+    /* Lock the in buffer while it is used for this transaction */
+    if (pthread_mutex_lock(&in_buf_mutex) != 0) {
+        ALOGE("%s: failed to lock in_buf_mutex: %s", __func__, strerror(errno));
+        return -errno;
+    }
+
     ret = ioctl(fd, CITADEL_IOC_TPM_DATAGRAM, &dg);
     if (ret < 0) {
         ALOGE("can't send spi message: %s", strerror(errno));
-        return -errno;
+        ret = -errno;
+        goto out;
     }
 
     memcpy(buf, in_buf, len);
 
-    return 0;
+out:
+    if (pthread_mutex_unlock(&in_buf_mutex) != 0) {
+        ALOGE("%s: failed to unlock in_buf_mutex: %s", __func__, strerror(errno));
+        ret = -errno;
+    }
+    return ret;
 }
 
+static pthread_mutex_t out_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
 static uint8_t out_buf[MAX_DEVICE_TRANSFER];
 static int write_datagram(void *ctx, uint32_t command, const uint8_t *buf, uint32_t len) {
     struct citadel_ioc_tpm_datagram dg = {
@@ -111,15 +126,27 @@
         return -E2BIG;
     }
 
+    /* Lock the out buffer while it is used for this transaction */
+    if (pthread_mutex_lock(&out_buf_mutex) != 0) {
+        ALOGE("%s: failed to lock out_buf_mutex: %s", __func__, strerror(errno));
+        return -errno;
+    }
+
     memcpy(out_buf, buf, len);
 
     ret = ioctl(fd, CITADEL_IOC_TPM_DATAGRAM, &dg);
     if (ret < 0) {
         ALOGE("can't send spi message: %s", strerror(errno));
-        return -errno;
+        ret = -errno;
+        goto out;
     }
 
-    return 0;
+out:
+    if (pthread_mutex_unlock(&out_buf_mutex) != 0) {
+        ALOGE("%s: failed to unlock out_buf_mutex: %s", __func__, strerror(errno));
+        ret = -errno;
+    }
+    return ret;
 }
 
 static int wait_for_interrupt(void *ctx, int msecs) {