ia64/xen-unstable
changeset 9925:42a70a529753
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@us.ibm.com>
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@us.ibm.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Wed May 03 11:00:57 2006 +0100 (2006-05-03) |
parents | 1449c89adb8b |
children | 40cd49c88d69 |
files | linux-2.6-xen-sparse/drivers/xen/tpmback/common.h linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c |
line diff
1.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Wed May 03 10:59:54 2006 +0100 1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Wed May 03 11:00:57 2006 +0100 1.3 @@ -50,6 +50,8 @@ typedef struct tpmif_st { 1.4 grant_handle_t shmem_handle; 1.5 grant_ref_t shmem_ref; 1.6 struct page *pagerange; 1.7 + 1.8 + char devname[20]; 1.9 } tpmif_t; 1.10 1.11 void tpmif_disconnect_complete(tpmif_t * tpmif);
2.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Wed May 03 10:59:54 2006 +0100 2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Wed May 03 11:00:57 2006 +0100 2.3 @@ -32,6 +32,7 @@ static tpmif_t *alloc_tpmif(domid_t domi 2.4 tpmif->domid = domid; 2.5 tpmif->status = DISCONNECTED; 2.6 tpmif->tpm_instance = instance; 2.7 + snprintf(tpmif->devname, sizeof(tpmif->devname), "tpmif%d", domid); 2.8 atomic_set(&tpmif->refcnt, 1); 2.9 2.10 tpmif->pagerange = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE); 2.11 @@ -144,7 +145,7 @@ int tpmif_map(tpmif_t *tpmif, unsigned l 2.12 tpmif->tx = (tpmif_tx_interface_t *)tpmif->tx_area->addr; 2.13 2.14 tpmif->irq = bind_evtchn_to_irqhandler( 2.15 - tpmif->evtchn, tpmif_be_int, 0, "tpmif-backend", tpmif); 2.16 + tpmif->evtchn, tpmif_be_int, 0, tpmif->devname, tpmif); 2.17 tpmif->shmem_ref = shared_page; 2.18 tpmif->active = 1; 2.19
3.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Wed May 03 10:59:54 2006 +0100 3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Wed May 03 11:00:57 2006 +0100 3.3 @@ -28,7 +28,8 @@ struct data_exchange { 3.4 struct list_head pending_pak; 3.5 struct list_head current_pak; 3.6 unsigned int copied_so_far; 3.7 - u8 has_opener; 3.8 + u8 has_opener:1; 3.9 + u8 aborted:1; 3.10 rwlock_t pak_lock; // protects all of the previous fields 3.11 wait_queue_head_t wait_queue; 3.12 }; 3.13 @@ -101,6 +102,16 @@ static inline int copy_to_buffer(void *t 3.14 return 0; 3.15 } 3.16 3.17 + 3.18 +static void dataex_init(struct data_exchange *dataex) 3.19 +{ 3.20 + INIT_LIST_HEAD(&dataex->pending_pak); 3.21 + INIT_LIST_HEAD(&dataex->current_pak); 3.22 + dataex->has_opener = 0; 3.23 + rwlock_init(&dataex->pak_lock); 3.24 + init_waitqueue_head(&dataex->wait_queue); 3.25 +} 3.26 + 3.27 /*************************************************************** 3.28 Packet-related functions 3.29 ***************************************************************/ 3.30 @@ -148,11 +159,12 @@ static struct packet *packet_alloc(tpmif 3.31 u32 size, u8 req_tag, u8 flags) 3.32 { 3.33 struct packet *pak = NULL; 3.34 - pak = kzalloc(sizeof (struct packet), GFP_KERNEL); 3.35 + pak = kzalloc(sizeof (struct packet), GFP_ATOMIC); 3.36 if (NULL != pak) { 3.37 if (tpmif) { 3.38 pak->tpmif = tpmif; 3.39 pak->tpm_instance = tpmif->tpm_instance; 3.40 + tpmif_get(tpmif); 3.41 } 3.42 pak->data_len = size; 3.43 pak->req_tag = req_tag; 3.44 @@ -180,6 +192,9 @@ static void packet_free(struct packet *p 3.45 if (timer_pending(&pak->processing_timer)) { 3.46 BUG(); 3.47 } 3.48 + 3.49 + if (pak->tpmif) 3.50 + tpmif_put(pak->tpmif); 3.51 kfree(pak->data_buffer); 3.52 /* 3.53 * cannot do tpmif_put(pak->tpmif); bad things happen 3.54 @@ -271,7 +286,6 @@ int _packet_write(struct packet *pak, 3.55 struct gnttab_map_grant_ref map_op; 3.56 struct gnttab_unmap_grant_ref unmap_op; 3.57 tpmif_tx_request_t *tx; 3.58 - unsigned long pfn, mfn, mfn_orig; 3.59 3.60 tx = &tpmif->tx->ring[i].req; 3.61 3.62 @@ -295,12 +309,6 @@ int _packet_write(struct packet *pak, 3.63 return 0; 3.64 } 3.65 3.66 - pfn = __pa(MMAP_VADDR(tpmif, i)) >> PAGE_SHIFT; 3.67 - mfn = FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT); 3.68 - mfn_orig = pfn_to_mfn(pfn); 3.69 - 3.70 - set_phys_to_machine(pfn, mfn); 3.71 - 3.72 tocopy = MIN(size - offset, PAGE_SIZE); 3.73 3.74 if (copy_from_buffer((void *)(MMAP_VADDR(tpmif, i) | 3.75 @@ -311,8 +319,6 @@ int _packet_write(struct packet *pak, 3.76 } 3.77 tx->size = tocopy; 3.78 3.79 - set_phys_to_machine(pfn, mfn_orig); 3.80 - 3.81 gnttab_set_unmap_op(&unmap_op, MMAP_VADDR(tpmif, i), 3.82 GNTMAP_host_map, handle); 3.83 3.84 @@ -514,27 +520,41 @@ static ssize_t vtpm_op_read(struct file 3.85 unsigned long flags; 3.86 3.87 write_lock_irqsave(&dataex.pak_lock, flags); 3.88 + if (dataex.aborted) { 3.89 + dataex.aborted = 0; 3.90 + dataex.copied_so_far = 0; 3.91 + write_unlock_irqrestore(&dataex.pak_lock, flags); 3.92 + return -EIO; 3.93 + } 3.94 3.95 if (list_empty(&dataex.pending_pak)) { 3.96 write_unlock_irqrestore(&dataex.pak_lock, flags); 3.97 wait_event_interruptible(dataex.wait_queue, 3.98 !list_empty(&dataex.pending_pak)); 3.99 write_lock_irqsave(&dataex.pak_lock, flags); 3.100 + dataex.copied_so_far = 0; 3.101 } 3.102 3.103 if (!list_empty(&dataex.pending_pak)) { 3.104 unsigned int left; 3.105 + 3.106 pak = list_entry(dataex.pending_pak.next, struct packet, next); 3.107 - 3.108 left = pak->data_len - dataex.copied_so_far; 3.109 + list_del(&pak->next); 3.110 + write_unlock_irqrestore(&dataex.pak_lock, flags); 3.111 3.112 DPRINTK("size given by app: %d, available: %d\n", size, left); 3.113 3.114 ret_size = MIN(size, left); 3.115 3.116 ret_size = packet_read(pak, ret_size, data, size, 1); 3.117 + 3.118 + write_lock_irqsave(&dataex.pak_lock, flags); 3.119 + 3.120 if (ret_size < 0) { 3.121 - ret_size = -EFAULT; 3.122 + del_singleshot_timer_sync(&pak->processing_timer); 3.123 + packet_free(pak); 3.124 + dataex.copied_so_far = 0; 3.125 } else { 3.126 DPRINTK("Copied %d bytes to user buffer\n", ret_size); 3.127 3.128 @@ -545,7 +565,6 @@ static ssize_t vtpm_op_read(struct file 3.129 3.130 del_singleshot_timer_sync(&pak-> 3.131 processing_timer); 3.132 - list_del(&pak->next); 3.133 list_add_tail(&pak->next, &dataex.current_pak); 3.134 /* 3.135 * The more fontends that are handled at the same time, 3.136 @@ -554,6 +573,8 @@ static ssize_t vtpm_op_read(struct file 3.137 mod_timer(&pak->processing_timer, 3.138 jiffies + (num_frontends * 60 * HZ)); 3.139 dataex.copied_so_far = 0; 3.140 + } else { 3.141 + list_add(&pak->next, &dataex.pending_pak); 3.142 } 3.143 } 3.144 } 3.145 @@ -601,8 +622,8 @@ static ssize_t vtpm_op_write(struct file 3.146 3.147 if (pak == NULL) { 3.148 write_unlock_irqrestore(&dataex.pak_lock, flags); 3.149 - printk(KERN_ALERT "No associated packet! (inst=%d)\n", 3.150 - ntohl(vrh.instance_no)); 3.151 + DPRINTK(KERN_ALERT "No associated packet! (inst=%d)\n", 3.152 + ntohl(vrh.instance_no)); 3.153 return -EFAULT; 3.154 } 3.155 3.156 @@ -784,15 +805,17 @@ static int tpm_send_fail_message(struct 3.157 return rc; 3.158 } 3.159 3.160 -static void _vtpm_release_packets(struct list_head *head, 3.161 - tpmif_t * tpmif, int send_msgs) 3.162 +static int _vtpm_release_packets(struct list_head *head, 3.163 + tpmif_t * tpmif, int send_msgs) 3.164 { 3.165 + int aborted = 0; 3.166 + int c = 0; 3.167 struct packet *pak; 3.168 - struct list_head *pos, 3.169 - *tmp; 3.170 + struct list_head *pos, *tmp; 3.171 3.172 list_for_each_safe(pos, tmp, head) { 3.173 pak = list_entry(pos, struct packet, next); 3.174 + c += 1; 3.175 3.176 if (tpmif == NULL || pak->tpmif == tpmif) { 3.177 int can_send = 0; 3.178 @@ -808,8 +831,11 @@ static void _vtpm_release_packets(struct 3.179 tpm_send_fail_message(pak, pak->req_tag); 3.180 } 3.181 packet_free(pak); 3.182 + if (c == 1) 3.183 + aborted = 1; 3.184 } 3.185 } 3.186 + return aborted; 3.187 } 3.188 3.189 int vtpm_release_packets(tpmif_t * tpmif, int send_msgs) 3.190 @@ -818,7 +844,9 @@ int vtpm_release_packets(tpmif_t * tpmif 3.191 3.192 write_lock_irqsave(&dataex.pak_lock, flags); 3.193 3.194 - _vtpm_release_packets(&dataex.pending_pak, tpmif, send_msgs); 3.195 + dataex.aborted = _vtpm_release_packets(&dataex.pending_pak, 3.196 + tpmif, 3.197 + send_msgs); 3.198 _vtpm_release_packets(&dataex.current_pak, tpmif, send_msgs); 3.199 3.200 write_unlock_irqrestore(&dataex.pak_lock, flags); 3.201 @@ -1020,11 +1048,7 @@ static int __init tpmback_init(void) 3.202 return rc; 3.203 } 3.204 3.205 - INIT_LIST_HEAD(&dataex.pending_pak); 3.206 - INIT_LIST_HEAD(&dataex.current_pak); 3.207 - dataex.has_opener = 0; 3.208 - rwlock_init(&dataex.pak_lock); 3.209 - init_waitqueue_head(&dataex.wait_queue); 3.210 + dataex_init(&dataex); 3.211 3.212 spin_lock_init(&tpm_schedule_list_lock); 3.213 INIT_LIST_HEAD(&tpm_schedule_list); 3.214 @@ -1041,6 +1065,7 @@ module_init(tpmback_init); 3.215 3.216 static void __exit tpmback_exit(void) 3.217 { 3.218 + vtpm_release_packets(NULL, 0); 3.219 tpmif_xenbus_exit(); 3.220 tpmif_interface_exit(); 3.221 misc_deregister(&vtpms_miscdevice);