14
14
#include <linux/spinlock.h>
15
15
#include <xen/xen.h>
16
16
17
+ static bool force_used_validation = false;
18
+ module_param (force_used_validation , bool , 0444 );
19
+
17
20
#ifdef DEBUG
18
21
/* For development, we want to crash whenever the ring is screwed. */
19
22
#define BAD_RING (_vq , fmt , args ...) \
@@ -182,6 +185,9 @@ struct vring_virtqueue {
182
185
} packed ;
183
186
};
184
187
188
+ /* Per-descriptor in buffer length */
189
+ u32 * buflen ;
190
+
185
191
/* How to notify other side. FIXME: commonalize hcalls! */
186
192
bool (* notify )(struct virtqueue * vq );
187
193
@@ -490,6 +496,7 @@ static inline int virtqueue_add_split(struct virtqueue *_vq,
490
496
unsigned int i , n , avail , descs_used , prev , err_idx ;
491
497
int head ;
492
498
bool indirect ;
499
+ u32 buflen = 0 ;
493
500
494
501
START_USE (vq );
495
502
@@ -571,6 +578,7 @@ static inline int virtqueue_add_split(struct virtqueue *_vq,
571
578
VRING_DESC_F_NEXT |
572
579
VRING_DESC_F_WRITE ,
573
580
indirect );
581
+ buflen += sg -> length ;
574
582
}
575
583
}
576
584
/* Last one doesn't continue. */
@@ -610,6 +618,10 @@ static inline int virtqueue_add_split(struct virtqueue *_vq,
610
618
else
611
619
vq -> split .desc_state [head ].indir_desc = ctx ;
612
620
621
+ /* Store in buffer length if necessary */
622
+ if (vq -> buflen )
623
+ vq -> buflen [head ] = buflen ;
624
+
613
625
/* Put entry in available array (but don't update avail->idx until they
614
626
* do sync). */
615
627
avail = vq -> split .avail_idx_shadow & (vq -> split .vring .num - 1 );
@@ -784,6 +796,11 @@ static void *virtqueue_get_buf_ctx_split(struct virtqueue *_vq,
784
796
BAD_RING (vq , "id %u is not a head!\n" , i );
785
797
return NULL ;
786
798
}
799
+ if (vq -> buflen && unlikely (* len > vq -> buflen [i ])) {
800
+ BAD_RING (vq , "used len %d is larger than in buflen %u\n" ,
801
+ * len , vq -> buflen [i ]);
802
+ return NULL ;
803
+ }
787
804
788
805
/* detach_buf_split clears data, so grab it now. */
789
806
ret = vq -> split .desc_state [i ].data ;
@@ -1062,6 +1079,7 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq,
1062
1079
unsigned int i , n , err_idx ;
1063
1080
u16 head , id ;
1064
1081
dma_addr_t addr ;
1082
+ u32 buflen = 0 ;
1065
1083
1066
1084
head = vq -> packed .next_avail_idx ;
1067
1085
desc = alloc_indirect_packed (total_sg , gfp );
@@ -1091,6 +1109,8 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq,
1091
1109
desc [i ].addr = cpu_to_le64 (addr );
1092
1110
desc [i ].len = cpu_to_le32 (sg -> length );
1093
1111
i ++ ;
1112
+ if (n >= out_sgs )
1113
+ buflen += sg -> length ;
1094
1114
}
1095
1115
}
1096
1116
@@ -1144,6 +1164,10 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq,
1144
1164
vq -> packed .desc_state [id ].indir_desc = desc ;
1145
1165
vq -> packed .desc_state [id ].last = id ;
1146
1166
1167
+ /* Store in buffer length if necessary */
1168
+ if (vq -> buflen )
1169
+ vq -> buflen [id ] = buflen ;
1170
+
1147
1171
vq -> num_added += 1 ;
1148
1172
1149
1173
pr_debug ("Added buffer head %i to %p\n" , head , vq );
@@ -1179,6 +1203,7 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq,
1179
1203
__le16 head_flags , flags ;
1180
1204
u16 head , id , prev , curr , avail_used_flags ;
1181
1205
int err ;
1206
+ u32 buflen = 0 ;
1182
1207
1183
1208
START_USE (vq );
1184
1209
@@ -1258,6 +1283,8 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq,
1258
1283
1 << VRING_PACKED_DESC_F_AVAIL |
1259
1284
1 << VRING_PACKED_DESC_F_USED ;
1260
1285
}
1286
+ if (n >= out_sgs )
1287
+ buflen += sg -> length ;
1261
1288
}
1262
1289
}
1263
1290
@@ -1277,6 +1304,10 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq,
1277
1304
vq -> packed .desc_state [id ].indir_desc = ctx ;
1278
1305
vq -> packed .desc_state [id ].last = prev ;
1279
1306
1307
+ /* Store in buffer length if necessary */
1308
+ if (vq -> buflen )
1309
+ vq -> buflen [id ] = buflen ;
1310
+
1280
1311
/*
1281
1312
* A driver MUST NOT make the first descriptor in the list
1282
1313
* available before all subsequent descriptors comprising
@@ -1463,6 +1494,11 @@ static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq,
1463
1494
BAD_RING (vq , "id %u is not a head!\n" , id );
1464
1495
return NULL ;
1465
1496
}
1497
+ if (vq -> buflen && unlikely (* len > vq -> buflen [id ])) {
1498
+ BAD_RING (vq , "used len %d is larger than in buflen %u\n" ,
1499
+ * len , vq -> buflen [id ]);
1500
+ return NULL ;
1501
+ }
1466
1502
1467
1503
/* detach_buf_packed clears data, so grab it now. */
1468
1504
ret = vq -> packed .desc_state [id ].data ;
@@ -1668,6 +1704,7 @@ static struct virtqueue *vring_create_virtqueue_packed(
1668
1704
struct vring_virtqueue * vq ;
1669
1705
struct vring_packed_desc * ring ;
1670
1706
struct vring_packed_desc_event * driver , * device ;
1707
+ struct virtio_driver * drv = drv_to_virtio (vdev -> dev .driver );
1671
1708
dma_addr_t ring_dma_addr , driver_event_dma_addr , device_event_dma_addr ;
1672
1709
size_t ring_size_in_bytes , event_size_in_bytes ;
1673
1710
@@ -1757,6 +1794,15 @@ static struct virtqueue *vring_create_virtqueue_packed(
1757
1794
if (!vq -> packed .desc_extra )
1758
1795
goto err_desc_extra ;
1759
1796
1797
+ if (!drv -> suppress_used_validation || force_used_validation ) {
1798
+ vq -> buflen = kmalloc_array (num , sizeof (* vq -> buflen ),
1799
+ GFP_KERNEL );
1800
+ if (!vq -> buflen )
1801
+ goto err_buflen ;
1802
+ } else {
1803
+ vq -> buflen = NULL ;
1804
+ }
1805
+
1760
1806
/* No callback? Tell other side not to bother us. */
1761
1807
if (!callback ) {
1762
1808
vq -> packed .event_flags_shadow = VRING_PACKED_EVENT_FLAG_DISABLE ;
@@ -1769,6 +1815,8 @@ static struct virtqueue *vring_create_virtqueue_packed(
1769
1815
spin_unlock (& vdev -> vqs_list_lock );
1770
1816
return & vq -> vq ;
1771
1817
1818
+ err_buflen :
1819
+ kfree (vq -> packed .desc_extra );
1772
1820
err_desc_extra :
1773
1821
kfree (vq -> packed .desc_state );
1774
1822
err_desc_state :
@@ -2176,6 +2224,7 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
2176
2224
void (* callback )(struct virtqueue * ),
2177
2225
const char * name )
2178
2226
{
2227
+ struct virtio_driver * drv = drv_to_virtio (vdev -> dev .driver );
2179
2228
struct vring_virtqueue * vq ;
2180
2229
2181
2230
if (virtio_has_feature (vdev , VIRTIO_F_RING_PACKED ))
@@ -2235,6 +2284,15 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
2235
2284
if (!vq -> split .desc_extra )
2236
2285
goto err_extra ;
2237
2286
2287
+ if (!drv -> suppress_used_validation || force_used_validation ) {
2288
+ vq -> buflen = kmalloc_array (vring .num , sizeof (* vq -> buflen ),
2289
+ GFP_KERNEL );
2290
+ if (!vq -> buflen )
2291
+ goto err_buflen ;
2292
+ } else {
2293
+ vq -> buflen = NULL ;
2294
+ }
2295
+
2238
2296
/* Put everything in free lists. */
2239
2297
vq -> free_head = 0 ;
2240
2298
memset (vq -> split .desc_state , 0 , vring .num *
@@ -2245,6 +2303,8 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
2245
2303
spin_unlock (& vdev -> vqs_list_lock );
2246
2304
return & vq -> vq ;
2247
2305
2306
+ err_buflen :
2307
+ kfree (vq -> split .desc_extra );
2248
2308
err_extra :
2249
2309
kfree (vq -> split .desc_state );
2250
2310
err_state :
0 commit comments