Browse Source

add locking mechanism in the fusd_file_info_t structure to prevent potential race conditions.

Godzil 11 years ago
parent
commit
0678a66b3c
2 changed files with 44 additions and 9 deletions
  1. 7 2
      include/fusd.h
  2. 37 7
      libfusd/libfusd.c

+ 7 - 2
include/fusd.h

@@ -66,6 +66,8 @@ __BEGIN_DECLS
 
 #define FUSD_KOR_HACKED_VERSION
 
+#ifndef __KERNEL__
+
 struct fusd_file_info; /* forward decl */
 
 typedef
@@ -105,6 +107,7 @@ struct fusd_file_info {
 
   /* other info might be added later, e.g. state needed to complete
      operations... */
+  pthread_mutex_t lock;
 
   /* request message associated with this call */
   int fd;
@@ -112,8 +115,8 @@ struct fusd_file_info {
 
 } fusd_file_info_t;
 
-
-
+#define FILE_LOCK(__f) pthread_mutex_lock(&__f->lock)
+#define FILE_UNLOCK(__f) pthread_mutex_unlock(&__f->lock)
 
 /*************************** Library Functions ****************************/
 
@@ -278,6 +281,8 @@ static inline int fusd_get_poll_diff_cached_state(struct fusd_file_info *file)
 /* returns static string representing the flagset (e.g. RWE) */
 char *fusd_unparse_flags(int flags);
 
+#endif /* !__KERNEL__ */
+
 #ifndef __KERNEL__
 __END_DECLS
 #endif

+ 37 - 7
libfusd/libfusd.c

@@ -53,6 +53,11 @@ char libfusd_c_id[] = "$Id: libfusd.c 12351 2007-01-19 07:22:54Z xiphmont $";
 #include <string.h>
 #include <time.h>
 
+#include <pthread.h>
+
+#include <unistd.h>
+#include <sys/syscall.h>
+
 #include "fusd.h"
 #include "fusd_msg.h"
 
@@ -72,7 +77,7 @@ char *dev_root = NULL;
  * struct for each fusd fd.
  */
 static fusd_file_operations_t fusd_fops_set[FD_SETSIZE];
-fusd_file_operations_t null_fops = { NULL };
+fusd_file_operations_t null_fops = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
 
 /*
  * accessor macros
@@ -389,6 +394,11 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
 
   /* fill the file info struct */
   memset(file, '\0', sizeof(fusd_file_info_t));
+
+  pthread_mutex_init(&file->lock, NULL);
+
+  FILE_LOCK(file);
+
   file->fd = fd;
   file->device_info = msg->parm.fops_msg.device_info;
   file->private_data = msg->parm.fops_msg.private_info;
@@ -398,6 +408,8 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
   file->gid = msg->parm.fops_msg.gid;
   file->fusd_msg = msg;  
 
+  FILE_UNLOCK(file);
+
   /* right now we only handle fops requests */
   if (msg->cmd != FUSD_FOPS_CALL && msg->cmd != FUSD_FOPS_NONBLOCK &&
       msg->cmd != FUSD_FOPS_CALL_DROPREPLY) {
@@ -602,20 +614,28 @@ int fusd_return(fusd_file_info_t *file, ssize_t retval)
   int driver_retval = 0;
   struct iovec iov[2];
 
-  if (file == NULL) {
+  if (file == NULL)
+  {
     fprintf(stderr, "fusd_return: NULL file\n");
-    return -EINVAL;
+    ret = -EINVAL;
+    goto exit;
   }
 
+  FILE_LOCK(file);
+
   fd = file->fd;
-  if (!FUSD_FD_VALID(fd)) {
+  if (!FUSD_FD_VALID(fd))
+  {
     fprintf(stderr, "fusd_return: badfd (fd %d)\n", fd);
-    return -EBADF;
+    ret = -EBADF;
+    goto exit_unlock;
   }
 
-  if ((msg = file->fusd_msg) == NULL) {
+  if ((msg = file->fusd_msg) == NULL)
+  {
     fprintf(stderr, "fusd_return: fusd_msg is gone\n");
-    return -EINVAL;
+    ret = -EINVAL;
+    goto exit_unlock;
   }
 
   /* if this was a "DONTREPLY" message, just free the struct */
@@ -668,13 +688,23 @@ int fusd_return(fusd_file_info_t *file, ssize_t retval)
     driver_retval = write(fd, msg, sizeof(fusd_msg_t));
   }
 
+free_memory:
+  FILE_UNLOCK(file);
  free_memory:
   fusd_destroy(file);
 
+  ret = 0;
   if (driver_retval < 0)
     return -errno;
   else
     return 0;
+   goto exit;
+
+exit_unlock:
+  FILE_UNLOCK(file);
+
+exit:
+  return ret;
 }