dazuko-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Dazuko-devel] Patch for patch-dazuko-linux-2.6.26


From: Lino Sanfilippo
Subject: [Dazuko-devel] Patch for patch-dazuko-linux-2.6.26
Date: Tue, 28 Oct 2008 14:25:51 +0100
User-agent: IceDove 1.5.0.14eol (X11/20080724)




Dear John, dear  Mailing list

I am one of the developers at Avira that are currently working on a new version of the unix antivir workstation/server software. While working with the dazuko patch for linux kernel 2.6.26 I realized that after registering 5 groups at dazuko, dazuko returns an error (-EINTR) and no more group registration is possible. After looking at the dazuko kernel code, I saw that 5 registered groups are the max. of groups that are allowed to be registered at the same time and any further group registration results in an EINTR error returned by the "write" system call (btw. is an EINTR really the best error code to indicate that no more groups can be handled? The process receiving this error would expect that it indeed has been interrupted by a signal. Looking at the man page for "write" I saw there is an ENOSPC error for example, that IMHO would make more sense for this kind of error).

I also saw that a group is never removed once it has been registered, even if unregistering it via dazuko_unregister_daemon().

I fixed this by modifying the kernel code in a way that its cleaning up the data structures at unregistration. For this reason I introduced an additional counter in the struct slotlist that keeps track of daemons that are registered at it. I also reimplemented the way of reference counting for the slotlists to ensure that no slotlist is freed if still in use by a process.

Beside this the patch also removes a bug in run_daemon_on_slotlist(): At two places the code was waiting there uninterruptibly (what is almost never a good idea), but handled the case of interruption. I changed that uninterruptible waiting into an interruptible one.

I created a patch for the dazuko-linux-2.6.26 patch, so if you want to test it, please patch the original dazuko-patch for kernel 2.6.26 before compiling the kernel.
The patch is attached to this mail, I hope you'll find it useful.

After studying the kernel code it also seems to me that the group registration code in dazuko_register_daemon() contains a possible race condition: Looking for a slotlist to register a group PLUS assigning the group to it should be done atomic. Otherwise in the (admittedly rare) case that two or more processes are trying to register the same group, one process could assign the group to a slotlist right after another one has figured out that this group is not yet registered and thus trying to register it, too. The result could be 2 or more slotlists being assigned to the same group.

Torsten Reinecke and I are also currently evaluating the dazukoFS. After a first view the solution with a stackable filesystem looks promising. We will keep you in the loop about our experiences with it.

Best regards,
Lino Sanfilippo

Geschäftsführender Gesellschafter: Tjark Auerbach
Sitz der Gesellschaft: Tettnang
Handelsregister: Amtsgericht Ulm, HRB 630992

ALLGEMEINE GESCHÄFTSBEDINGUNGEN
Es gelten unsere Allgemeinen Geschäftsbedingungen
(AGB). Sie finden sie in der jeweils gültigen Fassung
im Internet unter http://www.avira.de/agb
***************************************************
diff -ru origin/security/dazuko/dazuko_core.c new3/security/dazuko/dazuko_core.c
--- origin/security/dazuko/dazuko_core.c        2008-10-17 15:15:40.000000000 
+0200
+++ new3/security/dazuko/dazuko_core.c  2008-10-28 09:56:14.000000000 +0100
@@ -1,4 +1,4 @@
-/* DazukoXP. Allow cross platform file access control for 3rd-party 
applications.
+ /* DazukoXP. Allow cross platform file access control for 3rd-party 
applications.
    Written by John Ogness <address@hidden>
 
    Copyright (c) 2002, 2003, 2004, 2005, 2006 H+BEDV Datentechnik GmbH
@@ -117,7 +117,7 @@
        struct event_properties event_p;
        struct file_properties  file_p;
        struct xp_mutex         mutex;
-       struct slot_list        *slot_list;
+       struct slot_list        *slot_list;                              
        struct xp_queue         wait_daemon_waiting_until_this_slot_not_READY;
        struct xp_queue         
wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING;
        struct xp_queue         wait_daemon_waiting_until_this_slot_not_DONE;
@@ -126,6 +126,14 @@
 
 struct slot_list
 {
+        int                             container_idx;
+        /* number of processes registered at this group */
+        int                             active_count; 
+        /* indicates if this group is valid (if 0 this
+           struct is being freed soon) */
+        struct xp_atomic                invalid;
+        /* number of processes that hold a reference to this
+           list */
        struct xp_atomic                use_count;
        struct slot                     slots[NUM_SLOTS];
        struct dazuko_path              *incl_paths;
@@ -136,7 +144,7 @@
        struct xp_rwlock                lock_trusted_list;
        struct trusted_container        *trusted_list;
        char                            set_trusted_list;
-       struct xp_queue                 
wait_kernel_waiting_for_any_READY_slot_or_zero_use_count;
+       struct xp_queue                 
wait_kernel_waiting_for_any_READY_slot_or_invalid;
 };
 
 struct slot_list_container
@@ -163,6 +171,7 @@
 {
        struct slot             *slot;
        struct slot_list        *slotlist;
+        int                     invalid;
 };
 
 static int                             unique_count = 1;
@@ -173,6 +182,74 @@
 static unsigned char                   
access_mask_cache[NUM_EVENTS][NUM_SLOT_LISTS];
 static struct xp_mutex                 mutex_amc;
 
+// forward declarations
+static void dazuko_remove_all_paths(struct slot_list *slist);
+static inline void dazuko_remove_all_trusted(struct slot_list *sl);
+
+static void free_slot_list(struct slot_list *sl)
+{
+        int i;
+
+
+        dazuko_remove_all_paths(sl);
+
+        if (call_xp_atomic_read(&sl->use_count))
+                call_xp_print("dazuko: slot_list count was not 0 (possible 
bug)\n");
+
+        for (i = 0 ; i < NUM_SLOTS; i++) {
+                call_xp_destroy_mutex(&sl->slots[i].mutex);
+                
call_xp_destroy_queue(&sl->slots[i].wait_daemon_waiting_until_this_slot_not_READY);
+                
call_xp_destroy_queue(&sl->slots[i].wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING);
+                
call_xp_destroy_queue(&sl->slots[i].wait_daemon_waiting_until_this_slot_not_DONE);
+        }
+        call_xp_destroy_rwlock(&sl->lock_lists);
+        dazuko_remove_all_trusted(sl);
+        call_xp_destroy_rwlock(&sl->lock_trusted_list);        
+        
call_xp_destroy_queue(&sl->wait_kernel_waiting_for_any_READY_slot_or_invalid);
+
+        call_xp_free(sl->reg_name);        
+        call_xp_free(sl);
+}
+
+
+static struct slot_list *get_slotlist(int slnum)
+{
+        struct slot_list *sl;
+
+        call_xp_down(&slot_lists[slnum].mutex);
+        sl = slot_lists[slnum].slot_list;
+        if (sl)
+                call_xp_atomic_inc(&sl->use_count);
+        call_xp_up(&slot_lists[slnum].mutex);
+        
+        return sl;
+}
+
+
+
+static void release_slotlist(struct slot_list *sl)
+{
+        if (sl == NULL) {
+                printk(KERN_WARNING "%s: WARNING release on NULL slotlist\n", 
__func__);
+                return;
+        }
+        /* we "abuse" the mutex of the slots old container idx,
+           since decrementing and testing usage counter must be
+           atomic. TODO: replace with dec_and_test() as soon
+           as available */
+        call_xp_down(&slot_lists[sl->container_idx].mutex);
+        call_xp_atomic_dec(&sl->use_count);
+        if (call_xp_atomic_read(&sl->use_count) == 0){
+                free_slot_list(sl);                    
+        }
+        call_xp_up(&slot_lists[sl->container_idx].mutex);
+}
+
+
+void dazuko_release_slotlist(struct slot_list *sl)
+{
+        release_slotlist(sl);
+}
 
 int dazuko_vsnprintf(char *str, size_t size, const char *format, va_list ap)
 {
@@ -383,13 +460,7 @@
 
                for (j=0 ; j<NUM_SLOT_LISTS ; j++)
                {
-/* DOWN */
-                       call_xp_down(&(slot_lists[j].mutex));
-
-                       sl = slot_lists[j].slot_list;
-
-                       call_xp_up(&(slot_lists[j].mutex));
-/* UP */
+                        sl = get_slotlist(j);
 
                        if (sl == NULL)
                                continue;
@@ -400,18 +471,21 @@
                                        /* this is a special case since 
ON_CLOSE_MODIFIED
                                         * also triggers ON_CLOSE events */
 
-                                       if (((DAZUKO_ON_CLOSE | 
DAZUKO_ON_CLOSE_MODIFIED) & (sl->access_mask)) == 0)
+                                       if (((DAZUKO_ON_CLOSE | 
DAZUKO_ON_CLOSE_MODIFIED) & (sl->access_mask)) == 0) {
+                                                release_slotlist(sl);
                                                continue;
+                                        }
                                        break;
                                default:
-                                       if ((event & (sl->access_mask)) == 0)
+                                       if ((event & (sl->access_mask)) == 0) {
+                                                release_slotlist(sl);
                                                continue;
+                                        }
                                        break;
                        }
-
+                        release_slotlist(sl);
                        /* if we made it this far, then the
                         * event is in the access mask */
-
                        access_mask_cache[i][index] = j;
                        index++;
                }
@@ -515,7 +589,7 @@
        return success;
 }
 
-static struct slot * _dazuko_find_slot(struct daemon_id *did, int release, 
struct slot_list *sl)
+static struct slot * _dazuko_find_slot(struct daemon_id *did, struct slot_list 
*sl, int release)
 {
        /* Find the first slot with the same given
         * pid number. SMP safe. Use this function
@@ -584,49 +658,45 @@
        return NULL;
 }
 
-static struct slot * dazuko_find_slot_and_slotlist(struct daemon_id *did, int 
release, struct slot_list *slist, struct slot_list **sl_result)
+
+/* returns a free slot from a given slotlist if slist != NULL or from an 
arbitrary slotlist
+   if slotlist == NULL. On successful return slist is filled with a valid 
pointer to a slotlist
+   and the use counter for this slotlist has been incremented, thus the caller 
must decrement
+   the slotlists use count by calling release_slotlist as soon as it does not 
longer need it. 
+   Returns a slot on success or NULL on failure.
+*/ 
+static struct slot *dazuko_find_slot_and_slotlist(struct daemon_id *did, 
+                                                  struct slot_list **slist, 
+                                                  int release)
 {
        struct slot             *s;
        int                     i;
        struct slot_list        *sl;
-
-       if (slist == NULL)
-       {
-               for (i=0 ; i<NUM_SLOT_LISTS ; i++)
-               {
-/* DOWN */
-                       call_xp_down(&(slot_lists[i].mutex));
-
-                       sl = slot_lists[i].slot_list;
-
-                       call_xp_up(&(slot_lists[i].mutex));
-/* UP */
-
-                       if (sl != NULL)
-                       {
-                               s = _dazuko_find_slot(did, release, sl);
-                               if (s != NULL)
-                               {
-                                       /* set the current slot_list */
-                                       if (sl_result != NULL)
-                                               *sl_result = sl;
+ 
+       if (!*slist) {
+               for (i = 0; i < NUM_SLOT_LISTS; i++) {
+                        sl = get_slotlist(i);
+
+                       if (sl) {
+                               s = _dazuko_find_slot(did, sl, release);
+                               if (s) {
+                                        *slist = sl;                           
                     
 
                                        return s;
                                }
+                                release_slotlist(sl);
                        }
                }
-       }
-       else
-       {
-               return _dazuko_find_slot(did, release, slist);
-       }
-
+       } else
+               return _dazuko_find_slot(did, *slist, release);
+      
        return NULL;
 }
 
-static inline struct slot * dazuko_find_slot(struct daemon_id *did, int 
release, struct slot_list *slist)
+
+static inline struct slot * dazuko_find_slot(struct daemon_id *did, struct 
slot_list **slist, int release)
 {
-       return dazuko_find_slot_and_slotlist(did, release, slist, NULL);
+       return dazuko_find_slot_and_slotlist(did, slist, release);
 }
 
 static int dazuko_insert_path_fs(struct dazuko_path **list, struct xp_rwlock 
*lock_lists, char *fs_path, int fs_len)
@@ -768,14 +838,15 @@
         * current process id, the daemon. */
 
        struct slot             *s;
-       struct slot_list        *sl;
+       struct slot_list        *sl = NULL;
+        int slot_invalid = 0;
 
        DPRINT(("dazuko: dazuko_unregister_daemon() [%d]\n", did->unique));
 
        /* find our slot and hold the mutex
         * if we find it */
 /* DOWN? */
-       s = dazuko_find_slot_and_slotlist(did, 0, NULL, &sl);
+       s = dazuko_find_slot_and_slotlist(did, &sl, 0);
 
        if (s == NULL)
        {
@@ -800,21 +871,6 @@
        call_xp_up(&(s->mutex));
 /* UP */
 
-       call_xp_atomic_dec(&(sl->use_count));
-
-       /* Remove all the include and exclude paths
-        * if there are no more daemons in this group */
-
-       if (call_xp_atomic_read(&(sl->use_count)) == 0)
-       {
-               sl->access_mask = 0;
-               dazuko_setup_amc_cache();
-               dazuko_remove_all_paths(sl);
-
-               /* this was the last daemon in the group */
-               call_xp_atomic_dec(&groupcount);
-       }
-
        /* active should always be positive here, but
         * let's check just to be sure. ;) */
        if (call_xp_atomic_read(&active) > 0)
@@ -830,16 +886,37 @@
                call_xp_print("dazuko: active count error (possible bug)\n");
        }
 
-       /* slot->state has changed to FREE, notifiy appropriate queues */
+
+       /* slot->state has changed to FREE, notify appropriate queues */
        /* we need to notify all slot queues because unique could be -1,
         * which means that it is possible that this process does not
         * really belong to this slot */
        call_xp_notify(&(s->wait_daemon_waiting_until_this_slot_not_DONE));
        
call_xp_notify(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
        call_xp_notify(&(s->wait_daemon_waiting_until_this_slot_not_READY));
+        
+        call_xp_down(&slot_lists[sl->container_idx].mutex);
 
-       /* slotlist->use_count has been decreased, notify appropriate queue */
-       
call_xp_notify(&(sl->wait_kernel_waiting_for_any_READY_slot_or_zero_use_count));
+        sl->active_count--;
+        /* check if this was the last daemon in the group,
+           and if slotlist has to bee freed */
+        if (sl->active_count == 0) {
+                /* unlink this list from slotlists container */
+                call_xp_atomic_dec(&sl->use_count);
+                slot_lists[sl->container_idx].slot_list = NULL;
+                call_xp_atomic_set(&sl->invalid, 1);
+               call_xp_atomic_dec(&groupcount);
+                slot_invalid = 1;
+        }
+        call_xp_up(&slot_lists[sl->container_idx].mutex);
+
+       /* notify appropriate queue about slotlist state change */
+       call_xp_notify(&sl->wait_kernel_waiting_for_any_READY_slot_or_invalid);
+
+        if (slot_invalid) /*slotlist has been freed */
+                dazuko_setup_amc_cache();                
+        
+        release_slotlist(sl);
 
        return 0;
 }
@@ -871,13 +948,7 @@
 
        for (i=0 ; i<NUM_SLOT_LISTS ; i++)
        {
-/* DOWN */
-               call_xp_down(&(slot_lists[i].mutex));
-
-               sl = slot_lists[i].slot_list;
-
-               call_xp_up(&(slot_lists[i].mutex));
-/* UP */
+                sl = get_slotlist(i);
 
                if (sl != NULL)
                {
@@ -895,6 +966,8 @@
 
                        if (*p1 == *p2)
                                return sl;
+
+                        release_slotlist(sl);
                }
        }
 
@@ -906,113 +979,110 @@
        const char              *p1;
        char                    *p2;
        struct slot             *s;
-       struct slot_list        *sl;
-       int                     i;
+        struct slot_list        *sl = NULL;
 
        DPRINT(("dazuko: dazuko_register_daemon() [%d]\n", did->unique));
 
        if (did == NULL || reg_name == NULL)
                return XP_ERROR_PERMISSION;
 
-       s = dazuko_find_slot(did, 1, NULL);
+       s = dazuko_find_slot(did, &sl, 1);
 
        if (s != NULL)
        {
                /* We are already registered! */
 
                call_xp_print("dazuko: daemon %d already assigned to 
slot[%d]\n", did->unique, s->id);
-
+                release_slotlist(sl);
                return XP_ERROR_PERMISSION;
        }
 
        /* Find the slot_list with the matching name. */
 
+        /* FIXME:
+           Checking for a free slotlist by groupname AND assigning
+           a group to a free slotlist should be done atomic to avoid
+           possible race conditions if two or more processes try to register
+           a group with the same name at the same time */
        sl = find_slot_list_from_groupname(reg_name);
 
-       if (sl == NULL)
-       {
+       if (sl == NULL) {
+               int i;
                /* There is no slot_list with this name. We
                 * need to make one. */
 
-               sl = (struct slot_list *)call_xp_malloc(sizeof(struct 
slot_list));
-               if (sl == NULL)
-                       return XP_ERROR_FAULT;
-
-               dazuko_bzero(sl, sizeof(struct slot_list));
-
-               sl->reg_name = call_xp_malloc(string_length + 1);
-               if (sl->reg_name == NULL)
-               {
-                       call_xp_free(sl);
-                       return XP_ERROR_FAULT;
-               }
-               dazuko_bzero(sl->reg_name, string_length + 1);
-
-               call_xp_atomic_set(&(sl->use_count), 0);
-               call_xp_init_rwlock(&(sl->lock_lists));
-               call_xp_init_rwlock(&(sl->lock_trusted_list));
-               
call_xp_init_queue(&(sl->wait_kernel_waiting_for_any_READY_slot_or_zero_use_count));
-
-               p1 = reg_name;
-               p2 = sl->reg_name;
-
-               while (*p1)
-               {
-                       *p2 = *p1;
-
-                       p1++;
-                       p2++;
-               }
-               *p2 = 0;
-
-               /* give each slot a unique id and assign slot_list */
-               for (i=0 ; i<NUM_SLOTS ; i++)
-               {
-                       sl->slots[i].id = i;
-                       sl->slots[i].slot_list = sl;
-                       call_xp_init_mutex(&(sl->slots[i].mutex));
-                       
call_xp_init_queue(&(sl->slots[i].wait_daemon_waiting_until_this_slot_not_READY));
-                       
call_xp_init_queue(&(sl->slots[i].wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
-                       
call_xp_init_queue(&(sl->slots[i].wait_daemon_waiting_until_this_slot_not_DONE));
-               }
-
                /* we need to find an empty slot */
-               for (i=0 ; i<NUM_SLOT_LISTS ; i++)
-               {
-/* DOWN */
-                       call_xp_down(&(slot_lists[i].mutex));
-
-                       if (slot_lists[i].slot_list == NULL)
-                       {
+               for (i=0 ; (i < NUM_SLOT_LISTS) && !sl; i++) {
+                        /* DOWN */
+                       call_xp_down(&slot_lists[i].mutex);
+
+                       if (slot_lists[i].slot_list == NULL) {
+                               int j;
+
+                                sl = (struct slot_list *) 
+                                        call_xp_malloc(sizeof(struct 
slot_list));
+                                if (sl == NULL) {
+                                        call_xp_up(&slot_lists[i].mutex);
+                                        return XP_ERROR_FAULT;
+                                }
+                                dazuko_bzero(sl, sizeof(struct slot_list));
+
+                                sl->container_idx = i;
+                                sl->reg_name = call_xp_malloc(string_length + 
1);
+                                if (sl->reg_name == NULL) {
+                                        call_xp_free(sl);
+                                        call_xp_up(&slot_lists[i].mutex);
+                                        return XP_ERROR_FAULT;
+                                }                      
+                                dazuko_bzero(sl->reg_name, string_length + 1);
+
+                                /* initial use count. If this ever reaches 0 
the
+                                   slotlist will be freed */
+                                call_xp_atomic_set(&sl->use_count, 1);
+                                call_xp_atomic_set(&sl->invalid, 0);
+                                call_xp_init_rwlock(&sl->lock_lists);
+                                call_xp_init_rwlock(&sl->lock_trusted_list);
+                                
call_xp_init_queue(&sl->wait_kernel_waiting_for_any_READY_slot_or_invalid);
+
+                                p1 = reg_name;
+                                p2 = sl->reg_name;
+
+                                while (*p1)
+                                {
+                                        *p2 = *p1;
+
+                                        p1++;
+                                        p2++;
+                                }
+                                *p2 = 0;
+
+                                /* give each slot a unique id and assign 
slot_list */
+                                for (j=0 ; j < NUM_SLOTS; j++)
+                                {
+                                        sl->slots[j].id = j;
+                                        sl->slots[j].slot_list = sl;
+                                        
call_xp_init_mutex(&(sl->slots[j].mutex));
+                                        
call_xp_init_queue(&(sl->slots[j].wait_daemon_waiting_until_this_slot_not_READY));
+                                        
call_xp_init_queue(&(sl->slots[j].wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
+                                        
call_xp_init_queue(&(sl->slots[j].wait_daemon_waiting_until_this_slot_not_DONE));
+                                }
                                slot_lists[i].slot_list = sl;
-
-                               call_xp_up(&(slot_lists[i].mutex));
-/* UP */
-                               break;
-                       }
-
-                       call_xp_up(&(slot_lists[i].mutex));
-/* UP */
+                        } 
+                        /* UP */
+                       call_xp_up(&slot_lists[i].mutex);
                }
-
-               if (i == NUM_SLOT_LISTS)
-               {
-                       /* no empty slot :( */
-
-                       call_xp_free(sl->reg_name);
-                       call_xp_free(sl);
-
+               if (!sl)
                        return XP_ERROR_BUSY;
-               }
        }
-
        /* find an available slot and hold the mutex
         * if we find one */
 /* DOWN? */
-       s = dazuko_find_slot(NULL, 0, sl);
+       s = dazuko_find_slot(NULL, &sl, 0);
 
-       if (s == NULL)
+       if (s == NULL) {
+                release_slotlist(sl);
                return XP_ERROR_BUSY;
+        }
 
 /* DOWN */
 
@@ -1023,21 +1093,28 @@
 
        call_xp_atomic_inc(&active);
 
-       /* get new unique id for this process */
+       /* get new unique id for this process */ 
        did->unique = dazuko_get_new_unique();
 
        s->did.unique = did->unique;
        s->did.xp_id = call_xp_id_copy(did->xp_id);
        s->write_mode = write_mode;
 
-       call_xp_atomic_inc(&(sl->use_count));
-
-       if (call_xp_atomic_read(&(sl->use_count)) == 1)
-       {
+        
+        call_xp_down(&slot_lists[sl->container_idx].mutex);
+       sl->active_count++;
+        
+       if (sl->active_count == 1) /* first usage */
+        {
+                /* inc use count again, since it will
+                 * be decreased below */
+                call_xp_atomic_inc(&sl->use_count);
                /* this is the first daemon in the group */
                call_xp_atomic_inc(&groupcount);
        }
 
+        call_xp_up(&slot_lists[sl->container_idx].mutex);
+
        /* the daemon is registered, but not yet
         * ready to receive files */
        __dazuko_change_slot_state(s, DAZUKO_FREE, DAZUKO_FREE);
@@ -1047,13 +1124,15 @@
        call_xp_up(&(s->mutex));
 /* UP */
 
+        release_slotlist(sl);
+
        /* although there was a state change, we don't need to notify any queues
         * because a new slot is first interesting when it hits the READY state 
*/
 
        return 0;
 }
 
-static struct slot* dazuko_get_an_access(struct daemon_id *did)
+static struct slot* dazuko_get_an_access(struct daemon_id *did, struct 
slot_list **psl)
 {
        /* The daemon is requesting a filename of a file
         * to scan. This code will wait until a filename
@@ -1069,7 +1148,8 @@
 
 tryagain:
        /* find our slot */
-       s = dazuko_find_slot(did, 1, NULL);
+        *psl = NULL;
+       s = dazuko_find_slot(did, psl, 1);
 
        if (s == NULL)
        {
@@ -1080,7 +1160,7 @@
                        return NULL;
                }
 
-               s = dazuko_find_slot(did, 1, NULL);
+               s = dazuko_find_slot(did, psl, 1);
                if (s == NULL)
                {
                        call_xp_print("dazuko: unregistered daemon %d attempted 
to get access\n", did->unique);
@@ -1106,7 +1186,7 @@
        }
 
        /* slot->state has changed to READY, notify appropriate queue */
-       
call_xp_notify(&(s->slot_list->wait_kernel_waiting_for_any_READY_slot_or_zero_use_count));
+       
call_xp_notify(&(s->slot_list->wait_kernel_waiting_for_any_READY_slot_or_invalid));
 
        cond_p.slot = s;
        cond_p.state = DAZUKO_READY;
@@ -1123,7 +1203,7 @@
                        /* slot->state has changed to BROKEN, notifiy 
appropriate queue */
                        
call_xp_notify(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
                }
-
+                release_slotlist(*psl);
                return NULL;
        }
 
@@ -1136,7 +1216,7 @@
        if (!dazuko_change_slot_state(s, DAZUKO_WAITING, DAZUKO_WORKING, 0))
        {
                /* State transition error. Try again., */
-
+                release_slotlist(*psl);
                goto tryagain;
        }
 
@@ -1152,15 +1232,20 @@
 
 static int dazuko_initialize_cache(struct daemon_id *did, unsigned long ttl)
 {
+        int rv;
+        struct slot_list *sl = NULL;
        /* find our slot */
-       if (dazuko_find_slot(did, 1, NULL) == NULL)
+        
+       if (dazuko_find_slot(did, &sl, 1) == NULL)
        {
                /* this daemon is not registered! */
 
                return -1;
        }
+        rv = call_xp_init_cache(ttl);
 
-       return call_xp_init_cache(ttl);
+        release_slotlist(sl);
+       return rv;
 }
 
 static int dazuko_return_access(struct daemon_id *did, int response, struct 
slot *s)
@@ -1533,7 +1618,7 @@
         * option in the kernel. */
 
        struct slot             *s;
-       struct slot_list        *sl;
+       struct slot_list        *sl = NULL;
        int                     error = 0;
 
        /* sanity check */
@@ -1544,12 +1629,15 @@
         * (or that we don't register twice) */
 
        /* find our slot */
-       s = dazuko_find_slot_and_slotlist(did, 1, NULL, &sl);
+       s = dazuko_find_slot_and_slotlist(did, &sl, 1);
 
        switch (opt)
        {
                case REGISTER:
                        call_xp_print("dazuko: dazuko_set_option does not 
support REGISTER (bug!)\n");
+                        if (sl)
+                                release_slotlist(sl);
+                                
                        return XP_ERROR_PERMISSION;
 
                case UNREGISTER:
@@ -1571,7 +1659,7 @@
                                        return XP_ERROR_PERMISSION;
                                }
 
-                               s = dazuko_find_slot_and_slotlist(did, 1, NULL, 
&sl);
+                               s = dazuko_find_slot_and_slotlist(did, &sl, 1);
                                if (s == NULL)
                                {
                                        call_xp_print("dazuko: unregistered 
daemon %d attempted access\n", did->unique);
@@ -1631,6 +1719,7 @@
                        error = XP_ERROR_INVALID;
                        break;
        }
+        release_slotlist(sl);
 
        return error;
 }
@@ -1664,12 +1753,17 @@
        return NULL;
 }
 
-static int get_ready_slot_condition(void *param)
+static int get_ready_slot_condition(void *p)
 {
-       return ((((struct get_ready_slot_condition_param *)param)->slot = 
dazuko_get_and_hold_ready_slot(((struct get_ready_slot_condition_param 
*)param)->slotlist)) != NULL
-               || call_xp_atomic_read(&(((struct 
get_ready_slot_condition_param *)param)->slotlist->use_count)) == 0);
+        struct get_ready_slot_condition_param *param = p;
+
+       param->slot = dazuko_get_and_hold_ready_slot(param->slotlist);
+        param->invalid = call_xp_atomic_read(&param->slotlist->invalid) ? 1 : 
0;        
+
+        return !!param->slot || param->invalid;  
 }
 
+
 static int dazuko_run_daemon_on_slotlist(unsigned long event, char *filename, 
int filenamelength, struct event_properties *event_p, struct file_properties 
*file_p, int prev_response, struct slot_list *sl, struct dazuko_file_struct 
*dfs)
 {
        /* This is the main function called by the kernel
@@ -1691,7 +1785,7 @@
        /* wait for a slot to become ready */
        cond_p1.slotlist = sl;
        cond_p1.slot = s;
-       if 
(call_xp_wait_until_condition(&(sl->wait_kernel_waiting_for_any_READY_slot_or_zero_use_count),
 get_ready_slot_condition, &cond_p1, 0) != 0)
+       if 
(call_xp_wait_until_condition(&(sl->wait_kernel_waiting_for_any_READY_slot_or_invalid),
 get_ready_slot_condition, &cond_p1, 1) != 0)
        {
                /* The kernel process was killed while
                 * waiting for a slot to become ready.
@@ -1702,6 +1796,9 @@
                return -1;  /* user interrupted */
        }
 
+        if (cond_p1.invalid) 
+                return -1;
+
        /* Make sure we have a slot. We may have
         * gotten past the last wait because we
         * are no longer active. */
@@ -1757,7 +1854,8 @@
        cond_p2.state1 = DAZUKO_WAITING;
        cond_p2.slot2 = s;
        cond_p2.state2 = DAZUKO_WORKING;
-       if 
(call_xp_wait_until_condition(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING),
 two_slot_state_not_condition, &cond_p2, 0) != 0)
+
+       if 
(call_xp_wait_until_condition(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING),
 two_slot_state_not_condition, &cond_p2, 1) != 0)
        {
                /* The kernel process was killed while
                 * waiting for a daemon to process the file.
@@ -1775,7 +1873,6 @@
 
                return -1;  /* user interrupted */
        }
-
        /* we are working with the slot, so
         * we need to lock it */
 /* DOWN */
@@ -1972,24 +2069,18 @@
                        call_xp_print("dazuko: illegal value:%d in 
access_mask_cache (possible bug)\n", j);
                        break;
                }
-       
-/* DOWN */
-               call_xp_down(&(slot_lists[j].mutex));
-
-               sl = slot_lists[j].slot_list;
-
-               call_xp_up(&(slot_lists[j].mutex));
-/* UP */
-
+                sl = get_slotlist(j);                
                if (sl == NULL)
                        continue;
-
-               if (sl == skip_slotlist)
+               if (sl == skip_slotlist) {
+                        release_slotlist(sl);
                        continue;
-
+                }
 #ifdef ANONYMOUS_RESOLVE
-               if (!dazuko_should_scan(dfs, sl))
+               if (!dazuko_should_scan(dfs, sl)) {
+                        release_slotlist(sl);
                        continue;
+                }
 
                error = dazuko_run_daemon_on_slotlist(event, dfs->filename, 
dfs->filename_length, event_p, &(dfs->file_p), rc, sl, NULL);
 #else
@@ -2000,6 +2091,7 @@
                {
                        /* most likely user interrupt */
                        rc = error;
+                        release_slotlist(sl);
                        break;
                }
                else if (error > 0)
@@ -2007,6 +2099,7 @@
                        /* this daemon wants access blocked */
                        rc = 1;
                }
+                release_slotlist(sl);
        }
 
        return rc;
@@ -2034,7 +2127,7 @@
        return next;
 }
 
-inline int dazuko_is_our_daemon(struct xp_daemon_id *xp_id, struct slot_list 
**slotlist, struct slot **slot)
+inline int dazuko_is_our_daemon(struct xp_daemon_id *xp_id, struct slot_list 
**slotlist)
 {
        /* Check if the current process is one
         * of the daemons. */
@@ -2053,39 +2146,31 @@
 
        for (i=0 ; i<NUM_SLOT_LISTS ; i++)
        {
-/* DOWN */
-               call_xp_down(&(slot_lists[i].mutex));
-
-               sl = slot_lists[i].slot_list;
-
-               call_xp_up(&(slot_lists[i].mutex));
-/* UP */
-
-               if (sl == NULL)
+                sl = get_slotlist(i);                
+               if (sl== NULL)
                        continue;
 
-               s = _dazuko_find_slot(&did, 1, sl);
+               s = _dazuko_find_slot(&did, sl, 1);
                if (s != NULL)
                {
                        ret = 1;
 
-                       if (slotlist != NULL)
-                               *slotlist = sl;
-
-                       if (slot != NULL)
-                               *slot = s;
-
+                       *slotlist = sl;
                        break;
                }
 
-               if (did.xp_id == NULL)
+               if (did.xp_id == NULL) {
+                        release_slotlist(sl);
                        continue;
+                }
 
                /* This boolean is not protected by a lock on purpose.
                 * It is used as optimization when there are no trusted
                 * processes. If it is set, then we will use the lock. */
-               if (!(sl->set_trusted_list))
+               if (!(sl->set_trusted_list)) {
+                        release_slotlist(sl);
                        continue;
+                }
 
 /* LOCK */
                call_xp_read_lock(&(sl->lock_trusted_list));
@@ -2093,15 +2178,16 @@
                tc = sl->trusted_list;
                prev = NULL;
                while (tc != NULL)
-               {
+               {                                          
+ 
+
                        cmp = call_xp_id_compare(tc->xp_id, did.xp_id, 1);
 
                        if (cmp == DAZUKO_SAME || (cmp == DAZUKO_CHILD && 
tc->trust_children))
                        {
                                ret = 1;
 
-                               if (slotlist != NULL)
-                                       *slotlist = sl;
+                               *slotlist = sl;
 
                                break;
                        }
@@ -2119,12 +2205,12 @@
                                tc = tc->next;
                        }
                }
-
+                /* UNLOCK */
                call_xp_read_unlock(&(sl->lock_trusted_list));
-/* UNLOCK */
 
                if (ret)
                        break;
+                release_slotlist(sl);
        }
 
        call_xp_id_free(did.xp_id);
@@ -2245,8 +2331,10 @@
                return -1;
 
        /* check if this group is accepting trust requests */
-       if ((DAZUKO_TRUST_REQUEST & sl->access_mask) == 0)
+       if ((DAZUKO_TRUST_REQUEST & sl->access_mask) == 0) {
+                release_slotlist(sl);
                return -1;
+        }
 
        memset(&event_p, 0, sizeof(event_p));
 
@@ -2273,7 +2361,7 @@
 
                rc = dazuko_add_trusted_daemon(xp_id, token, trust_children, 
sl);
        }
-
+        release_slotlist(sl);
        return rc;
 }
 
@@ -2287,22 +2375,17 @@
 
        for (i=0 ; i<NUM_SLOT_LISTS ; i++)
        {
-/* DOWN */
-               call_xp_down(&(slot_lists[i].mutex));
-
-               sl = slot_lists[i].slot_list;
-
-               call_xp_up(&(slot_lists[i].mutex));
-/* UP */
-
+                sl = get_slotlist(i);                
                if (sl == NULL)
                        continue;
 
                /* This boolean is not protected by a lock on purpose.
                 * It is used as optimization when there are no trusted
                 * processes. If it is set, then we will use the lock. */
-               if (!(sl->set_trusted_list))
+               if (!(sl->set_trusted_list)) {
+                        release_slotlist(sl);
                        continue;
+                }
 
 /* LOCK */
                call_xp_read_lock(&(sl->lock_trusted_list));
@@ -2329,6 +2412,7 @@
                        sl->set_trusted_list = 0;
 
                call_xp_read_unlock(&(sl->lock_trusted_list));
+                release_slotlist(sl);
 /* UNLOCK */
        }
 
@@ -2490,6 +2574,7 @@
        int                     error = 0;
        struct slot             *s;
        struct daemon_id        did;
+        struct slot_list        *sl = NULL;
 
        /* read "\nID=id" */
        /* send "\nEV=event\nFN=file\nUI=uid\nPI=pid\nFL=flags\nMD=mode..." */
@@ -2511,7 +2596,8 @@
 dazuko_handle_request_get_an_access_begin:
 
 /* DOWN? */
-       s = dazuko_get_an_access(&did);
+        sl = NULL;
+       s = dazuko_get_an_access(&did, &sl);
 
        if (s == NULL)
        {
@@ -2533,6 +2619,7 @@
                        call_xp_up(&(s->mutex));
 /* UP */
                        dazuko_return_access(&did, 0, s);
+                        release_slotlist(sl);
                        goto dazuko_handle_request_get_an_access_begin;
                }
 
@@ -2543,6 +2630,7 @@
                        call_xp_up(&(s->mutex));
 /* UP */
                        dazuko_return_access(&did, 0, s);
+                        release_slotlist(sl);
                        goto dazuko_handle_request_get_an_access_begin;
                }
 
@@ -2606,7 +2694,7 @@
                call_xp_up(&(s->mutex));
 /* UP */
        }
-
+        release_slotlist(sl);
        call_xp_id_free(did.xp_id);
 
        return error;
@@ -2619,6 +2707,7 @@
        int                     error = 0;
        struct daemon_id        did;
        struct slot             *s;
+        struct slot_list        *sl = NULL;
 
        /* read "\nID=id\nDN=deny" */
 
@@ -2638,7 +2727,7 @@
        did.unique = dazuko_strtol(value1);
 
        /* find our slot */
-       s = dazuko_find_slot(&did, 1, NULL);
+       s = dazuko_find_slot(&did, &sl, 1);
 
        if (s == NULL)
        {
@@ -2653,6 +2742,7 @@
        {
                if (!handle_event_as_readonly(s))
                        error = dazuko_return_access(&did, 
dazuko_strtoul(value2), s);
+                release_slotlist(sl);
        }
 
        call_xp_free(value1);
@@ -3118,7 +3208,6 @@
 {
        struct access_compat1   *user_request_1;
        struct access_compat1   *temp_request_1;
-       struct slot_list        *sl;
        int                     error = 0;
        struct slot             *s;
        char                    *k_param;
@@ -3132,95 +3221,100 @@
        did.xp_id = call_xp_id_copy(xp_id);
        did.unique = -1;
 
-       switch (cmd)
-       {
-               case IOCTL_GET_AN_ACCESS:
-                       /* The daemon is requesting a filename of a file
-                        * to scan. This code will wait until a filename
-                        * is available, or until we should be killed.
-                        * (killing is done if any errors occur as well
-                        * as when the user kills us) */
-
-                       user_request_1 = (struct access_compat1 *)ptr;
+       switch (cmd) {
+                case IOCTL_GET_AN_ACCESS: {
+                        struct slot_list *sl = NULL;
+
+                        /* The daemon is requesting a filename of a file
+                         * to scan. This code will wait until a filename
+                         * is available, or until we should be killed.
+                         * (killing is done if any errors occur as well
+                         * as when the user kills us) */
+
+                        user_request_1 = (struct access_compat1 *)ptr;
+
+                        error = call_xp_verify_user_writable(user_request_1, 
sizeof(struct access_compat1));
+                        if (error)
+                        {
+                                error = XP_ERROR_FAULT;
+                                break;
+                        }
+
+                        /* DOWN? */
+                        s = dazuko_get_an_access(&did, &sl);
+                
+                        if (s == NULL)
+                        {
+                                error = XP_ERROR_INTERRUPT;
+                                break;
+                        }
+
+                        /* DOWN */
+                
+                        /* Slot IS in WORKING state. Copy all the
+                         * necessary information to userspace structure. */
+
+                        if (s->filenamelength >= 
DAZUKO_FILENAME_MAX_LENGTH_COMPAT1)
+                       {
+                                /* filename length overflow :( */
+                                
+                                s->filename[DAZUKO_FILENAME_MAX_LENGTH_COMPAT1 
- 1] = 0;
+                                temp_length = 
DAZUKO_FILENAME_MAX_LENGTH_COMPAT1;
+                        }
+                        else
+                        {
+                                temp_length = s->filenamelength + 1;
+                        }
+
+                        temp_request_1 = (struct access_compat1 
*)call_xp_malloc(sizeof(struct access_compat1));
+                        if (temp_request_1 == NULL)
+                        {
+                                error = XP_ERROR_FAULT;
+                        }
+                        else if (call_xp_copyin(user_request_1, 
temp_request_1, sizeof(struct access_compat1)) != 0)
+                        {
+                                error = XP_ERROR_FAULT;
+                        }
+
+                        if (error == 0)
+                        {
+                                temp_request_1->event = s->event;
+                                temp_request_1->o_flags = s->event_p.flags;
+                                temp_request_1->o_mode = s->event_p.mode;
+                                temp_request_1->uid = s->event_p.uid;
+                                temp_request_1->pid = s->event_p.pid;
+                                memcpy(temp_request_1->filename, s->filename, 
temp_length);
+
+                                if (call_xp_copyout(temp_request_1, 
user_request_1, sizeof(struct access_compat1)) != 0)
+                                {
+                                        error = XP_ERROR_FAULT;
+                                }
+                        }
+
+                        call_xp_up(&(s->mutex));
+                        /* UP */
+                        
+                
+                        if (error)
+                        {
+                                if (dazuko_change_slot_state(s, 
DAZUKO_WORKING, DAZUKO_BROKEN, 1))
+                                {
+                                        /* slot->state has changed to BROKEN, 
notifiy appropriate queue */
+                                        
call_xp_notify(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
+                                }
+                        }
+                        release_slotlist(sl);
+
+                        if (temp_request_1 != NULL)
+                        {
+                                call_xp_free(temp_request_1);
+                        }
+                }
+                        break;
+                        
+                case IOCTL_RETURN_ACCESS: {
+                        struct slot_list *sl = NULL;
 
-                       error = call_xp_verify_user_writable(user_request_1, 
sizeof(struct access_compat1));
-                       if (error)
-                       {
-                               error = XP_ERROR_FAULT;
-                               break;
-                       }
-
-/* DOWN? */
-                       s = dazuko_get_an_access(&did);
-
-                       if (s == NULL)
-                       {
-                               error = XP_ERROR_INTERRUPT;
-                               break;
-                       }
-
-/* DOWN */
-
-                       /* Slot IS in WORKING state. Copy all the
-                        * necessary information to userspace structure. */
-
-                       if (s->filenamelength >= 
DAZUKO_FILENAME_MAX_LENGTH_COMPAT1)
-                       {
-                               /* filename length overflow :( */
-
-                               s->filename[DAZUKO_FILENAME_MAX_LENGTH_COMPAT1 
- 1] = 0;
-                               temp_length = 
DAZUKO_FILENAME_MAX_LENGTH_COMPAT1;
-                       }
-                       else
-                       {
-                               temp_length = s->filenamelength + 1;
-                       }
-
-                       temp_request_1 = (struct access_compat1 
*)call_xp_malloc(sizeof(struct access_compat1));
-                       if (temp_request_1 == NULL)
-                       {
-                               error = XP_ERROR_FAULT;
-                       }
-                       else if (call_xp_copyin(user_request_1, temp_request_1, 
sizeof(struct access_compat1)) != 0)
-                       {
-                               error = XP_ERROR_FAULT;
-                       }
-
-                       if (error == 0)
-                       {
-                               temp_request_1->event = s->event;
-                               temp_request_1->o_flags = s->event_p.flags;
-                               temp_request_1->o_mode = s->event_p.mode;
-                               temp_request_1->uid = s->event_p.uid;
-                               temp_request_1->pid = s->event_p.pid;
-                               memcpy(temp_request_1->filename, s->filename, 
temp_length);
-
-                               if (call_xp_copyout(temp_request_1, 
user_request_1, sizeof(struct access_compat1)) != 0)
-                               {
-                                       error = XP_ERROR_FAULT;
-                               }
-                       }
-
-                       call_xp_up(&(s->mutex));
-/* UP */
-
-                       if (error)
-                       {
-                               if (dazuko_change_slot_state(s, DAZUKO_WORKING, 
DAZUKO_BROKEN, 1))
-                               {
-                                       /* slot->state has changed to BROKEN, 
notifiy appropriate queue */
-                                       
call_xp_notify(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
-                               }
-                       }
-
-                       if (temp_request_1 != NULL)
-                       {
-                               call_xp_free(temp_request_1);
-                       }
-
-                       break;
-
-               case IOCTL_RETURN_ACCESS:
                        /* The daemon has finished scanning a file
                         * and has the response to give. The daemon's
                         * slot should be in the WORKING state. */
@@ -3251,7 +3345,7 @@
                        call_xp_free(temp_request_1);
 
                        /* find our slot */
-                       s = dazuko_find_slot(&did, 1, NULL);
+                       s = dazuko_find_slot(&did, &sl, 1);
 
                        if (s == NULL)
                        {
@@ -3265,7 +3359,9 @@
                        else if (!handle_event_as_readonly(s))
                        {
                                error = dazuko_return_access(&did, temp_int, s);
+                                release_slotlist(sl);
                        }
+                }
 
                        break;
 
@@ -3330,34 +3426,31 @@
 
                        k_param[temp_length] = 0;
 
-                       switch (temp_int)
-                       {
-                               case REGISTER:
-                                       error = dazuko_register_daemon(&did, 
k_param, temp_length, 1);
-                                       break;
-
-                               case SET_ACCESS_MASK:
-                                       /* find our slot */
-                                       if (dazuko_find_slot_and_slotlist(&did, 
1, NULL, &sl) == NULL)
-                                       {
-                                               error = XP_ERROR_PERMISSION;
-                                       }
-                                       else if (sl == NULL)
-                                       {
-                                               error = XP_ERROR_PERMISSION;
-                                       }
-                                       else
-                                       {
-                                               sl->access_mask = k_param[0];
-
-                                               /* rebuild access_mask_cache */
-                                               dazuko_setup_amc_cache();
-                                       }
-                                       break;
+                       switch (temp_int) {
+                        case REGISTER:
+                                error = dazuko_register_daemon(&did, k_param, 
temp_length, 1);
+                                break;
+
+                        case SET_ACCESS_MASK: {
+                                struct slot_list *sl = NULL;
+                                /* find our slot */
+                                if (dazuko_find_slot_and_slotlist(&did, &sl, 
1) == NULL)
+                               {
+                                        error = XP_ERROR_PERMISSION;
+                                }
+                                else
+                               {
+                                        sl->access_mask = k_param[0];
+                                        release_slotlist(sl);
+                                        /* rebuild access_mask_cache */
+                                        dazuko_setup_amc_cache();
+                               }
+                        }
+                                break;
 
-                               default:
-                                       error = dazuko_set_option(&did, 
temp_int, k_param, temp_length);
-                                       break;
+                        default:
+                                error = dazuko_set_option(&did, temp_int, 
k_param, temp_length);
+                                break;
                        }
 
                        call_xp_free(k_param);
@@ -3375,6 +3468,8 @@
        return error;
 }
 
+/* NOTE: susccessful return does not guarantee that the passed slot_list 
pointer contains
+   a valid address. This differs from most functions that take a slot_list 
pointer address */  
 int dazuko_check_access(unsigned long event, int daemon_is_allowed, struct 
xp_daemon_id *xp_id, struct slot_list **cached_lookup)
 {      
        int                     i;
@@ -3401,30 +3496,28 @@
        if (i == AMC_UNSET)
                return -1;
 
-       if (dazuko_is_our_daemon(xp_id, &sl, NULL))
+       if (dazuko_is_our_daemon(xp_id, &sl))
        {
                /* should daemons be allowed this event without a scan? */
                if (daemon_is_allowed)
                {
                        /* this is one of our daemons, so we will report as
                         * as if this event was not in the mask */
-
+                        release_slotlist(sl);
                        return -1;
-               }
+               } 
                else
                {
                        /* this is one of our daemons, but the
                         * other groups must be informed */
 
                        /* if there are no other groups, allow this event */
-                       if (call_xp_atomic_read(&groupcount) == 1)
-                               return -1;
-
-                       if (cached_lookup != NULL)
-                       {
-                               /* this slot list (ours) will be skipped */
-                               *cached_lookup = sl;
-                       }
+                       if (call_xp_atomic_read(&groupcount) == 1) {
+                                release_slotlist(sl);
+                                return -1;
+                        }
+                        /* this slot list (ours) will be skipped */
+                        *cached_lookup = sl;                   
                }
        }
 
@@ -3500,11 +3593,13 @@
        return error;
 }
 
+
+
 int dazuko_exit(void)
 {
-       int     error;
+       int     error; 
        int     i;
-       int     j;
+
 
        i = call_xp_atomic_read(&active);
 
@@ -3521,43 +3616,20 @@
                call_xp_destroy_mutex(&mutex_unique_count);
                call_xp_destroy_mutex(&mutex_amc);
 
-               for (i=0 ; i<NUM_SLOT_LISTS ; i++)
+               for (i=0 ; i < NUM_SLOT_LISTS; i++)
                {
-                       if (slot_lists[i].slot_list != NULL)
-                       {
-                               
dazuko_remove_all_paths(slot_lists[i].slot_list);
-
-                               if 
(call_xp_atomic_read(&(slot_lists[i].slot_list->use_count)) != 0)
-                                       call_xp_print("dazuko: slot_list count 
was not 0 (possible bug)\n");
-
-                               for (j=0 ; j<NUM_SLOTS ; j++)
-                               {
-                                       
call_xp_destroy_mutex(&(slot_lists[i].slot_list->slots[j].mutex));
-                                       
call_xp_destroy_queue(&(slot_lists[i].slot_list->slots[j].wait_daemon_waiting_until_this_slot_not_READY));
-                                       
call_xp_destroy_queue(&(slot_lists[i].slot_list->slots[j].wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
-                                       
call_xp_destroy_queue(&(slot_lists[i].slot_list->slots[j].wait_daemon_waiting_until_this_slot_not_DONE));
-                               }
-
-                               
call_xp_destroy_rwlock(&(slot_lists[i].slot_list->lock_lists));
-
-                               
dazuko_remove_all_trusted(slot_lists[i].slot_list);
-                               
call_xp_destroy_rwlock(&(slot_lists[i].slot_list->lock_trusted_list));
-
-                               
call_xp_destroy_queue(&(slot_lists[i].slot_list->wait_kernel_waiting_for_any_READY_slot_or_zero_use_count));
-
-                               if (slot_lists[i].slot_list->reg_name != NULL)
-                                       
call_xp_free(slot_lists[i].slot_list->reg_name);
-                               slot_lists[i].slot_list->reg_name = NULL;
-
-                               call_xp_free(slot_lists[i].slot_list);
-                               slot_lists[i].slot_list = NULL;
-                       }
+                        call_xp_down(&slot_lists[i].mutex);
+                        if (slot_lists[i].slot_list) 
+                                release_slotlist(slot_lists[i].slot_list);
 
-                       call_xp_destroy_mutex(&(slot_lists[i].mutex));
+                        call_xp_up(&slot_lists[i].mutex);
+                        call_xp_destroy_mutex(&(slot_lists[i].mutex));
                }
 
                call_xp_print("dazuko: unloaded, version=%s\n", VERSION_STRING);
        }
+        /* wait for all processes to release their slot list references..*/
+        msleep(200);
 
        return error;
 }
diff -ru origin/security/dazuko/dazuko_core.h new3/security/dazuko/dazuko_core.h
--- origin/security/dazuko/dazuko_core.h        2008-10-17 15:15:40.000000000 
+0200
+++ new3/security/dazuko/dazuko_core.h  2008-10-22 14:59:07.000000000 +0200
@@ -201,7 +201,7 @@
 
 int dazuko_vsnprintf(char *str, size_t size, const char *format, va_list ap);
 int dazuko_snprintf(char *str, size_t size, const char *format, ...);
-int dazuko_is_our_daemon(struct xp_daemon_id *xp_id, struct slot_list 
**slotlist, struct slot **slot);
+int dazuko_is_our_daemon(struct xp_daemon_id *xp_id, struct slot_list 
**slotlist);
 int dazuko_get_value(const char *key, const char *string, char **value);
 int dazuko_unregister_daemon(struct xp_daemon_id *xp_id);
 int dazuko_handle_user_request(const char *request_buffer, struct xp_daemon_id 
*xp_id);
@@ -213,6 +213,7 @@
 int dazuko_active(void);
 int dazuko_check_access(unsigned long event, int daemon_is_allowed, struct 
xp_daemon_id *xp_id, struct slot_list **cached_lookup);
 int dazuko_process_access(unsigned long event, struct dazuko_file_struct *kfs, 
struct event_properties *event_p, struct slot_list *cached_lookup);
+void dazuko_release_slotlist(struct slot_list *sl);
 int dazuko_init(void);
 int dazuko_exit(void);
 
diff -ru origin/security/dazuko/dazuko_linux26.c 
new3/security/dazuko/dazuko_linux26.c
--- origin/security/dazuko/dazuko_linux26.c     2008-10-17 15:15:40.000000000 
+0200
+++ new3/security/dazuko/dazuko_linux26.c       2008-10-22 14:59:07.000000000 
+0200
@@ -636,6 +636,9 @@
 
                        dazuko_file_struct_cleanup(&dfs);
                }
+                /* slot list may be null here */
+                if (sl) 
+                        dazuko_release_slotlist(sl);
        }
 
        if (error)

reply via email to

[Prev in Thread] Current Thread [Next in Thread]