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

[Xen-changelog] Introduce some finer-grained locking to prevent calling



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 42a70a5297531270612557e49908597e5ddb9ba3
# Parent  1449c89adb8b2221cc49b67c0015ff03d09e4da4
Introduce some finer-grained locking to prevent calling
copy_from/to_user while preventing interrupts and fix allocation of
memory from within a task and other issues.

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>

diff -r 1449c89adb8b -r 42a70a529753 
linux-2.6-xen-sparse/drivers/xen/tpmback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Wed May 03 10:59:54 
2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Wed May 03 11:00:57 
2006 +0100
@@ -50,6 +50,8 @@ typedef struct tpmif_st {
        grant_handle_t shmem_handle;
        grant_ref_t shmem_ref;
        struct page *pagerange;
+
+       char devname[20];
 } tpmif_t;
 
 void tpmif_disconnect_complete(tpmif_t * tpmif);
diff -r 1449c89adb8b -r 42a70a529753 
linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c      Wed May 03 
10:59:54 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c      Wed May 03 
11:00:57 2006 +0100
@@ -32,6 +32,7 @@ static tpmif_t *alloc_tpmif(domid_t domi
        tpmif->domid = domid;
        tpmif->status = DISCONNECTED;
        tpmif->tpm_instance = instance;
+       snprintf(tpmif->devname, sizeof(tpmif->devname), "tpmif%d", domid);
        atomic_set(&tpmif->refcnt, 1);
 
        tpmif->pagerange = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE);
@@ -144,7 +145,7 @@ int tpmif_map(tpmif_t *tpmif, unsigned l
        tpmif->tx = (tpmif_tx_interface_t *)tpmif->tx_area->addr;
 
        tpmif->irq = bind_evtchn_to_irqhandler(
-               tpmif->evtchn, tpmif_be_int, 0, "tpmif-backend", tpmif);
+               tpmif->evtchn, tpmif_be_int, 0, tpmif->devname, tpmif);
        tpmif->shmem_ref = shared_page;
        tpmif->active = 1;
 
diff -r 1449c89adb8b -r 42a70a529753 
linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c        Wed May 03 
10:59:54 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c        Wed May 03 
11:00:57 2006 +0100
@@ -28,7 +28,8 @@ struct data_exchange {
        struct list_head pending_pak;
        struct list_head current_pak;
        unsigned int copied_so_far;
-       u8 has_opener;
+       u8 has_opener:1;
+       u8 aborted:1;
        rwlock_t pak_lock;      // protects all of the previous fields
        wait_queue_head_t wait_queue;
 };
@@ -101,6 +102,16 @@ static inline int copy_to_buffer(void *t
        return 0;
 }
 
+
+static void dataex_init(struct data_exchange *dataex)
+{
+       INIT_LIST_HEAD(&dataex->pending_pak);
+       INIT_LIST_HEAD(&dataex->current_pak);
+       dataex->has_opener = 0;
+       rwlock_init(&dataex->pak_lock);
+       init_waitqueue_head(&dataex->wait_queue);
+}
+
 /***************************************************************
  Packet-related functions
 ***************************************************************/
@@ -148,11 +159,12 @@ static struct packet *packet_alloc(tpmif
                                   u32 size, u8 req_tag, u8 flags)
 {
        struct packet *pak = NULL;
-       pak = kzalloc(sizeof (struct packet), GFP_KERNEL);
+       pak = kzalloc(sizeof (struct packet), GFP_ATOMIC);
        if (NULL != pak) {
                if (tpmif) {
                        pak->tpmif = tpmif;
                        pak->tpm_instance = tpmif->tpm_instance;
+                       tpmif_get(tpmif);
                }
                pak->data_len = size;
                pak->req_tag = req_tag;
@@ -180,6 +192,9 @@ static void packet_free(struct packet *p
        if (timer_pending(&pak->processing_timer)) {
                BUG();
        }
+
+       if (pak->tpmif)
+               tpmif_put(pak->tpmif);
        kfree(pak->data_buffer);
        /*
         * cannot do tpmif_put(pak->tpmif); bad things happen
@@ -271,7 +286,6 @@ int _packet_write(struct packet *pak,
                struct gnttab_map_grant_ref map_op;
                struct gnttab_unmap_grant_ref unmap_op;
                tpmif_tx_request_t *tx;
-               unsigned long pfn, mfn, mfn_orig;
 
                tx = &tpmif->tx->ring[i].req;
 
@@ -294,12 +308,6 @@ int _packet_write(struct packet *pak,
                        DPRINTK(" Grant table operation failure !\n");
                        return 0;
                }
-
-               pfn = __pa(MMAP_VADDR(tpmif, i)) >> PAGE_SHIFT;
-               mfn = FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT);
-               mfn_orig = pfn_to_mfn(pfn);
-
-               set_phys_to_machine(pfn, mfn);
 
                tocopy = MIN(size - offset, PAGE_SIZE);
 
@@ -310,8 +318,6 @@ int _packet_write(struct packet *pak,
                        return -EFAULT;
                }
                tx->size = tocopy;
-
-               set_phys_to_machine(pfn, mfn_orig);
 
                gnttab_set_unmap_op(&unmap_op, MMAP_VADDR(tpmif, i),
                                    GNTMAP_host_map, handle);
@@ -514,27 +520,41 @@ static ssize_t vtpm_op_read(struct file 
        unsigned long flags;
 
        write_lock_irqsave(&dataex.pak_lock, flags);
+       if (dataex.aborted) {
+               dataex.aborted = 0;
+               dataex.copied_so_far = 0;
+               write_unlock_irqrestore(&dataex.pak_lock, flags);
+               return -EIO;
+       }
 
        if (list_empty(&dataex.pending_pak)) {
                write_unlock_irqrestore(&dataex.pak_lock, flags);
                wait_event_interruptible(dataex.wait_queue,
                                         !list_empty(&dataex.pending_pak));
                write_lock_irqsave(&dataex.pak_lock, flags);
+               dataex.copied_so_far = 0;
        }
 
        if (!list_empty(&dataex.pending_pak)) {
                unsigned int left;
+
                pak = list_entry(dataex.pending_pak.next, struct packet, next);
-
                left = pak->data_len - dataex.copied_so_far;
+               list_del(&pak->next);
+               write_unlock_irqrestore(&dataex.pak_lock, flags);
 
                DPRINTK("size given by app: %d, available: %d\n", size, left);
 
                ret_size = MIN(size, left);
 
                ret_size = packet_read(pak, ret_size, data, size, 1);
+
+               write_lock_irqsave(&dataex.pak_lock, flags);
+
                if (ret_size < 0) {
-                       ret_size = -EFAULT;
+                       del_singleshot_timer_sync(&pak->processing_timer);
+                       packet_free(pak);
+                       dataex.copied_so_far = 0;
                } else {
                        DPRINTK("Copied %d bytes to user buffer\n", ret_size);
 
@@ -545,7 +565,6 @@ static ssize_t vtpm_op_read(struct file 
 
                                del_singleshot_timer_sync(&pak->
                                                          processing_timer);
-                               list_del(&pak->next);
                                list_add_tail(&pak->next, &dataex.current_pak);
                                /*
                                 * The more fontends that are handled at the 
same time,
@@ -554,6 +573,8 @@ static ssize_t vtpm_op_read(struct file 
                                mod_timer(&pak->processing_timer,
                                          jiffies + (num_frontends * 60 * HZ));
                                dataex.copied_so_far = 0;
+                       } else {
+                               list_add(&pak->next, &dataex.pending_pak);
                        }
                }
        }
@@ -601,8 +622,8 @@ static ssize_t vtpm_op_write(struct file
 
        if (pak == NULL) {
                write_unlock_irqrestore(&dataex.pak_lock, flags);
-               printk(KERN_ALERT "No associated packet! (inst=%d)\n",
-                      ntohl(vrh.instance_no));
+               DPRINTK(KERN_ALERT "No associated packet! (inst=%d)\n",
+                       ntohl(vrh.instance_no));
                return -EFAULT;
        }
 
@@ -784,15 +805,17 @@ static int tpm_send_fail_message(struct 
        return rc;
 }
 
-static void _vtpm_release_packets(struct list_head *head,
-                                 tpmif_t * tpmif, int send_msgs)
-{
+static int _vtpm_release_packets(struct list_head *head,
+                                tpmif_t * tpmif, int send_msgs)
+{
+       int aborted = 0;
+       int c = 0;
        struct packet *pak;
-       struct list_head *pos,
-                *tmp;
+       struct list_head *pos, *tmp;
 
        list_for_each_safe(pos, tmp, head) {
                pak = list_entry(pos, struct packet, next);
+               c += 1;
 
                if (tpmif == NULL || pak->tpmif == tpmif) {
                        int can_send = 0;
@@ -808,8 +831,11 @@ static void _vtpm_release_packets(struct
                                tpm_send_fail_message(pak, pak->req_tag);
                        }
                        packet_free(pak);
-               }
-       }
+                       if (c == 1)
+                               aborted = 1;
+               }
+       }
+       return aborted;
 }
 
 int vtpm_release_packets(tpmif_t * tpmif, int send_msgs)
@@ -818,7 +844,9 @@ int vtpm_release_packets(tpmif_t * tpmif
 
        write_lock_irqsave(&dataex.pak_lock, flags);
 
-       _vtpm_release_packets(&dataex.pending_pak, tpmif, send_msgs);
+       dataex.aborted = _vtpm_release_packets(&dataex.pending_pak,
+                                              tpmif,
+                                              send_msgs);
        _vtpm_release_packets(&dataex.current_pak, tpmif, send_msgs);
 
        write_unlock_irqrestore(&dataex.pak_lock, flags);
@@ -1020,11 +1048,7 @@ static int __init tpmback_init(void)
                return rc;
        }
 
-       INIT_LIST_HEAD(&dataex.pending_pak);
-       INIT_LIST_HEAD(&dataex.current_pak);
-       dataex.has_opener = 0;
-       rwlock_init(&dataex.pak_lock);
-       init_waitqueue_head(&dataex.wait_queue);
+       dataex_init(&dataex);
 
        spin_lock_init(&tpm_schedule_list_lock);
        INIT_LIST_HEAD(&tpm_schedule_list);
@@ -1041,6 +1065,7 @@ module_init(tpmback_init);
 
 static void __exit tpmback_exit(void)
 {
+       vtpm_release_packets(NULL, 0);
        tpmif_xenbus_exit();
        tpmif_interface_exit();
        misc_deregister(&vtpms_miscdevice);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.