From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:36:28
This fixes a bunch of issues around ptr_ring use in net core.
One of these: "tap: fix use-after-free" is also needed on net,
but can't be backported cleanly.
I will post a net patch separately.
Lightly tested - Jason, could you pls confirm this
addresses the security issue you saw with ptr_ring?
Testing reports would be appreciated too.
Michael S. Tsirkin (12):
ptr_ring: keep consumer_head valid at all times
ptr_ring: clean up documentation
ptr_ring: READ/WRITE_ONCE for __ptr_ring_empty
tap: fix use-after-free
ptr_ring: disallow lockless __ptr_ring_full
Revert "net: ptr_ring: otherwise safe empty checks can overrun array
bounds"
skb_array: use __ptr_ring_empty
ptr_ring: prevent queue load/store tearing
tools/virtio: switch to __ptr_ring_empty
tools/virtio: more stubs to fix tools build
tools/virtio: copy READ/WRITE_ONCE
tools/virtio: fix smp_mb on x86
drivers/net/tap.c | 3 --
include/linux/ptr_ring.h | 86 ++++++++++++++++++++++------------------
include/linux/skb_array.h | 2 +-
tools/virtio/linux/kernel.h | 2 +-
tools/virtio/linux/thread_info.h | 1 +
tools/virtio/ringtest/main.h | 59 ++++++++++++++++++++++++++-
tools/virtio/ringtest/ptr_ring.c | 2 +-
7 files changed, 110 insertions(+), 45 deletions(-)
create mode 100644 tools/virtio/linux/thread_info.h
--
MST
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:36:32
The comment near __ptr_ring_peek says:
* If ring is never resized, and if the pointer is merely
* tested, there's no need to take the lock - see e.g. __ptr_ring_empty.
but this was in fact never possible since consumer_head would sometimes
point outside the ring. Refactor the code so that it's always
pointing within a ring.
Fixes: c5ad119fb6c09 ("net: sched: pfifo_fast use skb_array")
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
@@ -248,22 +248,28 @@ static inline void __ptr_ring_discard_one(struct ptr_ring *r)/* Fundamentally, what we want to do is update consumer*indexandzeroouttheentrysoproducercanreuseit.*Doingitnaivelyateachconsumewouldbeassimpleas:-*r->queue[r->consumer++]=NULL;-*if(unlikely(r->consumer>=r->size))-*r->consumer=0;+*consumer=r->consumer;+*r->queue[consumer++]=NULL;+*if(unlikely(consumer>=r->size))+*consumer=0;+*r->consumer=consumer;*butthatissuboptimalwhentheringisfullasproduceriswriting*outnewentriesinthesamecacheline.Defertheseupdatesuntila*batchofentrieshasbeenconsumed.*/-inthead=r->consumer_head++;+/* Note: we must keep consumer_head valid at all times for __ptr_ring_empty+*toworkcorrectly.+*/+intconsumer_head=r->consumer_head;+inthead=consumer_head++;/* Once we have processed enough entries invalidate them in*theringallatoncesoproducercanreusetheirspaceinthering.*Wealsodothiswhenwereachendofthering-notmandatory*buthelpskeeptheimplementationsimple.*/-if(unlikely(r->consumer_head-r->consumer_tail>=r->batch||-r->consumer_head>=r->size)){+if(unlikely(consumer_head-r->consumer_tail>=r->batch||+consumer_head>=r->size)){/* Zero out entries in the reverse order: this way we touch the*cachelinethatproducermightcurrentlybereadingthelast;*producerwon'tmakeprogressandtouchothercachelines
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:36:36
Lockless access to __ptr_ring_full is only legal if ring is
never resized, otherwise it might cause use-after free errors.
Simply drop the lockless test, we'll drop the packet
a bit later when produce fails.
Fixes: 362899b8 ("macvtap: switch to use skb array")
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
drivers/net/tap.c | 3 ---
1 file changed, 3 deletions(-)
@@ -330,9 +330,6 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)if(!q)returnRX_HANDLER_PASS;-if(__ptr_ring_full(&q->ring))-gotodrop;-skb_push(skb,ETH_HLEN);/* Apply the forward feature mask so that we perform segmentation
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:36:40
This reverts commit bcecb4bbf88aa03171c30652bca761cf27755a6b.
If we try to allocate an extra entry as the above commit did, and when
the requested size is UINT_MAX, addition overflows causing zero size to
be passed to kmalloc().
kmalloc then returns ZERO_SIZE_PTR with a subsequent crash.
Reported-by: syzbot+87678bcf753b44c39b67@syzkaller.appspotmail.com
Cc: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
@@ -466,12 +466,7 @@ static inline int ptr_ring_consume_batched_bh(struct ptr_ring *r,staticinlinevoid**__ptr_ring_init_queue_alloc(unsignedintsize,gfp_tgfp){-/* Allocate an extra dummy element at end of ring to avoid consumer head-*orproduceheadaccesspasttheendofthearray.Possiblewhen-*producer/consumeroperationsand__ptr_ring_peekoperationsrunin-*parallel.-*/-returnkcalloc(size+1,sizeof(void*),gfp);+returnkcalloc(size,sizeof(void*),gfp);}staticinlinevoid__ptr_ring_set_size(structptr_ring*r,intsize)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:36:43
We don't rely on lockless guarantees, but it
seems cleaner than inverting __ptr_ring_peek.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
tools/virtio/ringtest/ptr_ring.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:36:48
This is to make ptr_ring test build again.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
tools/virtio/ringtest/main.h | 57 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:37:07
Offset 128 overlaps the last word of the redzone.
Use 132 which is always beyond that.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
tools/virtio/ringtest/main.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:38:04
In theory compiler could tear queue loads or stores in two. It does not
seem to be happening in practice but it seems easier to convert the
cases where this would be a problem to READ/WRITE_ONCE than worry about
it.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:38:25
__skb_array_empty should use __ptr_ring_empty since that's the only
legal lockless function.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/skb_array.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:38:48
Similar to bcecb4bbf88a ("net: ptr_ring: otherwise safe empty checks can
overrun array bounds") a lockless use of __ptr_ring_full might
cause an out of bounds access.
We can fix this, but it's easier to just disallow lockless
__ptr_ring_full for now.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
@@ -45,9 +45,10 @@ struct ptr_ring {};/* Note: callers invoking this in a loop must use a compiler barrier,-*forexamplecpu_relax().Ifringiseverresized,callersmusthold-*producer_lock-seee.g.ptr_ring_full.Otherwise,ifcallersdon'thold-*producer_lock,thenextcallto__ptr_ring_producemayfail.+*forexamplecpu_relax().+*+*NB:thisisunlike__ptr_ring_emptyinthatcallersmustholdproducer_lock:+*seee.g.ptr_ring_full.*/staticinlinebool__ptr_ring_full(structptr_ring*r){
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:39:17
Lockless __ptr_ring_empty requires that consumer head is read and
written at once, atomically. Annotate accordingly to make sure compiler
does it correctly. Switch locked callers to __ptr_ring_peek which does
not support the lockless operation.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-25 23:39:19
The only function safe to call without locks
is __ptr_ring_empty. Move documentation about
lockless use there to make sure people do not
try to use __ptr_ring_peek outside locks.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
@@ -169,21 +169,6 @@ static inline int ptr_ring_produce_bh(struct ptr_ring *r, void *ptr)returnret;}-/* Note: callers invoking this in a loop must use a compiler barrier,-*forexamplecpu_relax().Callersmusttakeconsumer_lock-*iftheydereferencethepointer-seee.g.PTR_RING_PEEK_CALL.-*Ifringisneverresized,andifthepointerismerely-*tested,there'snoneedtotakethelock-seee.g.__ptr_ring_empty.-*However,ifcalledoutsidethelock,andifsomeotherCPU-*consumesringentriesatthesametime,thevaluereturned-*isnotguaranteedtobecorrect.-*Inthiscase-toavoidincorrectlydetectingthering-*asempty-theCPUconsumingtheringentriesisresponsible-*foreitherconsumingallringentriesuntiltheringisempty,-*orsynchronizingwithsomeotherCPUandcausingitto-*execute__ptr_ring_peekand/orconsumetheringenteries-*afterthesynchronizationpoint.-*/staticinlinevoid*__ptr_ring_peek(structptr_ring*r){if(likely(r->size))
@@ -191,7 +176,24 @@ static inline void *__ptr_ring_peek(struct ptr_ring *r)returnNULL;}-/* See __ptr_ring_peek above for locking rules. */+/*+*Testringemptystatuswithouttakinganylocks.+*+*NB:Thisisonlysafetocallifringisneverresized.+*+*However,ifsomeotherCPUconsumesringentriesatthesametime,thevalue+*returnedisnotguaranteedtobecorrect.+*+*Inthiscase-toavoidincorrectlydetectingthering+*asempty-theCPUconsumingtheringentriesisresponsible+*foreitherconsumingallringentriesuntiltheringisempty,+*orsynchronizingwithsomeotherCPUandcausingitto+*re-test__ptr_ring_emptyand/orconsumetheringenteries+*afterthesynchronizationpoint.+*+*Note:callersinvokingthisinaloopmustuseacompilerbarrier,+*forexamplecpu_relax().+*/staticinlinebool__ptr_ring_empty(structptr_ring*r){return!__ptr_ring_peek(r);
From: John Fastabend <john.fastabend@gmail.com> Date: 2018-01-26 00:12:12
On 01/25/2018 03:36 PM, Michael S. Tsirkin wrote:
The comment near __ptr_ring_peek says:
* If ring is never resized, and if the pointer is merely
* tested, there's no need to take the lock - see e.g. __ptr_ring_empty.
but this was in fact never possible since consumer_head would sometimes
point outside the ring. Refactor the code so that it's always
pointing within a ring.
Fixes: c5ad119fb6c09 ("net: sched: pfifo_fast use skb_array")
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
Thanks for fixing this up.
Acked-by: John Fastabend <john.fastabend@gmail.com>
From: John Fastabend <john.fastabend@gmail.com> Date: 2018-01-26 00:13:07
On 01/25/2018 03:36 PM, Michael S. Tsirkin wrote:
This reverts commit bcecb4bbf88aa03171c30652bca761cf27755a6b.
If we try to allocate an extra entry as the above commit did, and when
the requested size is UINT_MAX, addition overflows causing zero size to
be passed to kmalloc().
kmalloc then returns ZERO_SIZE_PTR with a subsequent crash.
Reported-by: syzbot+87678bcf753b44c39b67@syzkaller.appspotmail.com
Cc: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Dang, I missed this case. Thanks.
Acked-by: John Fastabend <john.fastabend@gmail.com>
@@ -466,12 +466,7 @@ static inline int ptr_ring_consume_batched_bh(struct ptr_ring *r,staticinlinevoid**__ptr_ring_init_queue_alloc(unsignedintsize,gfp_tgfp){-/* Allocate an extra dummy element at end of ring to avoid consumer head-*orproduceheadaccesspasttheendofthearray.Possiblewhen-*producer/consumeroperationsand__ptr_ring_peekoperationsrunin-*parallel.-*/-returnkcalloc(size+1,sizeof(void*),gfp);+returnkcalloc(size,sizeof(void*),gfp);}staticinlinevoid__ptr_ring_set_size(structptr_ring*r,intsize)
From: Jason Wang <hidden> Date: 2018-01-26 02:38:09
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted hunk
Lockless __ptr_ring_empty requires that consumer head is read and
written at once, atomically. Annotate accordingly to make sure compiler
does it correctly. Switch locked callers to __ptr_ring_peek which does
not support the lockless operation.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
So after patch 8, __ptr_ring_peek() did:
static inline void *__ptr_ring_peek(struct ptr_ring *r)
{
if (likely(r->size))
return READ_ONCE(r->queue[r->consumer_head]);
return NULL;
}
Looks like a duplication.
Thanks
From: Jason Wang <hidden> Date: 2018-01-26 02:38:17
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
Similar to bcecb4bbf88a ("net: ptr_ring: otherwise safe empty checks can
overrun array bounds") a lockless use of __ptr_ring_full might
cause an out of bounds access.
We can fix this, but it's easier to just disallow lockless
__ptr_ring_full for now.
It looks to me that just fix this is better than disallow through doc
(which is easily to be ignored ...).
Thanks
quoted hunk
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
@@ -45,9 +45,10 @@ struct ptr_ring {};/* Note: callers invoking this in a loop must use a compiler barrier,-*forexamplecpu_relax().Ifringiseverresized,callersmusthold-*producer_lock-seee.g.ptr_ring_full.Otherwise,ifcallersdon'thold-*producer_lock,thenextcallto__ptr_ring_producemayfail.+*forexamplecpu_relax().+*+*NB:thisisunlike__ptr_ring_emptyinthatcallersmustholdproducer_lock:+*seee.g.ptr_ring_full.*/staticinlinebool__ptr_ring_full(structptr_ring*r){
From: Jason Wang <hidden> Date: 2018-01-26 02:38:20
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted hunk
In theory compiler could tear queue loads or stores in two. It does not
seem to be happening in practice but it seems easier to convert the
cases where this would be a problem to READ/WRITE_ONCE than worry about
it.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-26 02:44:14
On Fri, Jan 26, 2018 at 10:37:58AM +0800, Jason Wang wrote:
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted
Lockless __ptr_ring_empty requires that consumer head is read and
written at once, atomically. Annotate accordingly to make sure compiler
does it correctly. Switch locked callers to __ptr_ring_peek which does
not support the lockless operation.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
So after patch 8, __ptr_ring_peek() did:
static inline void *__ptr_ring_peek(struct ptr_ring *r)
{
if (likely(r->size))
return READ_ONCE(r->queue[r->consumer_head]);
return NULL;
}
Looks like a duplication.
Thanks
Nope - they are different.
The reason is that __ptr_ring_peek does not need to read the consumer_head once
since callers have a lock, and __ptr_ring_empty does not need to read
the queue once since it merely compares it to 0.
--
MST
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-26 02:46:15
On Fri, Jan 26, 2018 at 10:38:05AM +0800, Jason Wang wrote:
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted
Similar to bcecb4bbf88a ("net: ptr_ring: otherwise safe empty checks can
overrun array bounds") a lockless use of __ptr_ring_full might
cause an out of bounds access.
We can fix this, but it's easier to just disallow lockless
__ptr_ring_full for now.
It looks to me that just fix this is better than disallow through doc (which
is easily to be ignored ...).
Thanks
lockless is tricky, and I'd rather not sprinkle READ/WRITE_ONCE where
they aren't necessary.
quoted
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
@@ -45,9 +45,10 @@ struct ptr_ring {};/* Note: callers invoking this in a loop must use a compiler barrier,-*forexamplecpu_relax().Ifringiseverresized,callersmusthold-*producer_lock-seee.g.ptr_ring_full.Otherwise,ifcallersdon'thold-*producer_lock,thenextcallto__ptr_ring_producemayfail.+*forexamplecpu_relax().+*+*NB:thisisunlike__ptr_ring_emptyinthatcallersmustholdproducer_lock:+*seee.g.ptr_ring_full.*/staticinlinebool__ptr_ring_full(structptr_ring*r){
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-26 02:49:10
On Fri, Jan 26, 2018 at 10:38:12AM +0800, Jason Wang wrote:
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted
In theory compiler could tear queue loads or stores in two. It does not
seem to be happening in practice but it seems easier to convert the
cases where this would be a problem to READ/WRITE_ONCE than worry about
it.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
@@ -114,7 +114,7 @@ static inline int __ptr_ring_produce(struct ptr_ring *r, void *ptr)/* Pairs with smp_read_barrier_depends in __ptr_ring_consume. */smp_wmb();-r->queue[r->producer++]=ptr;+WRITE_ONCE(r->queue[r->producer++],ptr);if(unlikely(r->producer>=r->size))r->producer=0;
You may want WRITE_ONCE() here? And if we just fix the out of bound
r->producer, we may just need one WRITE_ONCE().
Thanks
No because producers are serialized.
If we were going to sprinkle write/read once all over the place
we should just make it all volatile and drop the annotations.
I don't care much either way but for better or worse linux has volatile
considered harmful doc which says that you are supposed to think and
only add these things were they are necessary.
From: Jason Wang <hidden> Date: 2018-01-26 03:20:07
On 2018年01月26日 10:44, Michael S. Tsirkin wrote:
On Fri, Jan 26, 2018 at 10:37:58AM +0800, Jason Wang wrote:
quoted
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted
Lockless __ptr_ring_empty requires that consumer head is read and
written at once, atomically. Annotate accordingly to make sure compiler
does it correctly. Switch locked callers to __ptr_ring_peek which does
not support the lockless operation.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
So after patch 8, __ptr_ring_peek() did:
static inline void *__ptr_ring_peek(struct ptr_ring *r)
{
if (likely(r->size))
return READ_ONCE(r->queue[r->consumer_head]);
return NULL;
}
Looks like a duplication.
Thanks
Nope - they are different.
The reason is that __ptr_ring_peek does not need to read the consumer_head once
since callers have a lock,
I get this.
and __ptr_ring_empty does not need to read
the queue once since it merely compares it to 0.
Do this still work if it was called inside a loop?
Thanks
From: Jason Wang <hidden> Date: 2018-01-26 03:20:47
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
This fixes a bunch of issues around ptr_ring use in net core.
One of these: "tap: fix use-after-free" is also needed on net,
but can't be backported cleanly.
I will post a net patch separately.
Lightly tested - Jason, could you pls confirm this
addresses the security issue you saw with ptr_ring?
Testing reports would be appreciated too.
With the reproducer provided by syzbot, the problem has been fixed.
Thanks
From: Jason Wang <hidden> Date: 2018-01-26 03:56:22
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted hunk
Offset 128 overlaps the last word of the redzone.
Use 132 which is always beyond that.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
tools/virtio/ringtest/main.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
+#define smp_mb() asm volatile("lock; addl $0,-132(%%rsp)" ::: "memory", "cc")
#else
/*
* Not using __ATOMIC_SEQ_CST since gcc docs say they are only synchronized
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-26 13:44:18
On Fri, Jan 26, 2018 at 11:19:58AM +0800, Jason Wang wrote:
On 2018年01月26日 10:44, Michael S. Tsirkin wrote:
quoted
On Fri, Jan 26, 2018 at 10:37:58AM +0800, Jason Wang wrote:
quoted
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted
Lockless __ptr_ring_empty requires that consumer head is read and
written at once, atomically. Annotate accordingly to make sure compiler
does it correctly. Switch locked callers to __ptr_ring_peek which does
not support the lockless operation.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/linux/ptr_ring.h | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
So after patch 8, __ptr_ring_peek() did:
static inline void *__ptr_ring_peek(struct ptr_ring *r)
{
if (likely(r->size))
return READ_ONCE(r->queue[r->consumer_head]);
return NULL;
}
Looks like a duplication.
Thanks
Nope - they are different.
The reason is that __ptr_ring_peek does not need to read the consumer_head once
since callers have a lock,
I get this.
quoted
and __ptr_ring_empty does not need to read
the queue once since it merely compares it to 0.
Do this still work if it was called inside a loop?
Thanks
Sure because compiler does not know head didn't change.
--
MST
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-26 13:45:43
On Fri, Jan 26, 2018 at 11:56:14AM +0800, Jason Wang wrote:
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted
Offset 128 overlaps the last word of the redzone.
Use 132 which is always beyond that.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
tools/virtio/ringtest/main.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Oh you are right of course. Probably no one ever run this one on i386 :)
I'll add a patch on top as this is not a new bug.
quoted
+#define smp_mb() asm volatile("lock; addl $0,-132(%%rsp)" ::: "memory", "cc")
#else
/*
* Not using __ATOMIC_SEQ_CST since gcc docs say they are only synchronized
From: Jason Wang <hidden> Date: 2018-01-29 03:36:19
On 2018年01月26日 10:46, Michael S. Tsirkin wrote:
quoted
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted
Similar to bcecb4bbf88a ("net: ptr_ring: otherwise safe empty checks can
overrun array bounds") a lockless use of __ptr_ring_full might
cause an out of bounds access.
We can fix this, but it's easier to just disallow lockless
__ptr_ring_full for now.
It looks to me that just fix this is better than disallow through doc (which
is easily to be ignored ...).
Thanks
lockless is tricky, and I'd rather not sprinkle READ/WRITE_ONCE where
they aren't necessary.
The problem is then API looks a little bit strange. Lockless were only
allowed to be done at __ptr_ring_empty() but not __ptr_ring_full().
Thanks
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2018-01-29 04:41:27
On Mon, Jan 29, 2018 at 11:36:09AM +0800, Jason Wang wrote:
On 2018年01月26日 10:46, Michael S. Tsirkin wrote:
quoted
quoted
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted
Similar to bcecb4bbf88a ("net: ptr_ring: otherwise safe empty checks can
overrun array bounds") a lockless use of __ptr_ring_full might
cause an out of bounds access.
We can fix this, but it's easier to just disallow lockless
__ptr_ring_full for now.
It looks to me that just fix this is better than disallow through doc (which
is easily to be ignored ...).
Thanks
lockless is tricky, and I'd rather not sprinkle READ/WRITE_ONCE where
they aren't necessary.
The problem is then API looks a little bit strange. Lockless were only
allowed to be done at __ptr_ring_empty() but not __ptr_ring_full().
Thanks
So __ptr_ring_empty doesn't really work lockless. It merely does not crash.
I don't believe we can do anything to remove the need to read the
docs unless people use the safe non __ variants.
--
MST
From: Jason Wang <hidden> Date: 2018-01-29 07:09:59
On 2018年01月29日 12:41, Michael S. Tsirkin wrote:
On Mon, Jan 29, 2018 at 11:36:09AM +0800, Jason Wang wrote:
quoted
On 2018年01月26日 10:46, Michael S. Tsirkin wrote:
quoted
quoted
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted
Similar to bcecb4bbf88a ("net: ptr_ring: otherwise safe empty checks can
overrun array bounds") a lockless use of __ptr_ring_full might
cause an out of bounds access.
We can fix this, but it's easier to just disallow lockless
__ptr_ring_full for now.
It looks to me that just fix this is better than disallow through doc (which
is easily to be ignored ...).
Thanks
lockless is tricky, and I'd rather not sprinkle READ/WRITE_ONCE where
they aren't necessary.
The problem is then API looks a little bit strange. Lockless were only
allowed to be done at __ptr_ring_empty() but not __ptr_ring_full().
Thanks
So __ptr_ring_empty doesn't really work lockless. It merely does not crash.
I don't believe we can do anything to remove the need to read the
docs unless people use the safe non __ variants.
From: Jason Wang <hidden> Date: 2018-01-29 07:10:44
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
This fixes a bunch of issues around ptr_ring use in net core.
One of these: "tap: fix use-after-free" is also needed on net,
but can't be backported cleanly.
I will post a net patch separately.
Lightly tested - Jason, could you pls confirm this
addresses the security issue you saw with ptr_ring?
Testing reports would be appreciated too.
Michael S. Tsirkin (12):
ptr_ring: keep consumer_head valid at all times
ptr_ring: clean up documentation
ptr_ring: READ/WRITE_ONCE for __ptr_ring_empty
tap: fix use-after-free
ptr_ring: disallow lockless __ptr_ring_full
Revert "net: ptr_ring: otherwise safe empty checks can overrun array
bounds"
skb_array: use __ptr_ring_empty
ptr_ring: prevent queue load/store tearing
tools/virtio: switch to __ptr_ring_empty
tools/virtio: more stubs to fix tools build
tools/virtio: copy READ/WRITE_ONCE
tools/virtio: fix smp_mb on x86
drivers/net/tap.c | 3 --
include/linux/ptr_ring.h | 86 ++++++++++++++++++++++------------------
include/linux/skb_array.h | 2 +-
tools/virtio/linux/kernel.h | 2 +-
tools/virtio/linux/thread_info.h | 1 +
tools/virtio/ringtest/main.h | 59 ++++++++++++++++++++++++++-
tools/virtio/ringtest/ptr_ring.c | 2 +-
7 files changed, 110 insertions(+), 45 deletions(-)
create mode 100644 tools/virtio/linux/thread_info.h
For the series:
Tested-by: Jason Wang <redacted>
Acked-by: Jason Wang <redacted>
Thanks
From: David Miller <davem@davemloft.net> Date: 2018-01-29 17:03:19
From: Jason Wang <redacted>
Date: Mon, 29 Jan 2018 15:10:37 +0800
On 2018年01月26日 07:36, Michael S. Tsirkin wrote:
quoted
This fixes a bunch of issues around ptr_ring use in net core.
One of these: "tap: fix use-after-free" is also needed on net,
but can't be backported cleanly.
I will post a net patch separately.
Lightly tested - Jason, could you pls confirm this
addresses the security issue you saw with ptr_ring?
Testing reports would be appreciated too.
Michael S. Tsirkin (12):
ptr_ring: keep consumer_head valid at all times
ptr_ring: clean up documentation
ptr_ring: READ/WRITE_ONCE for __ptr_ring_empty
tap: fix use-after-free
ptr_ring: disallow lockless __ptr_ring_full
Revert "net: ptr_ring: otherwise safe empty checks can overrun array
bounds"
skb_array: use __ptr_ring_empty
ptr_ring: prevent queue load/store tearing
tools/virtio: switch to __ptr_ring_empty
tools/virtio: more stubs to fix tools build
tools/virtio: copy READ/WRITE_ONCE
tools/virtio: fix smp_mb on x86
drivers/net/tap.c | 3 --
include/linux/ptr_ring.h | 86 ++++++++++++++++++++++------------------
include/linux/skb_array.h | 2 +-
tools/virtio/linux/kernel.h | 2 +-
tools/virtio/linux/thread_info.h | 1 +
tools/virtio/ringtest/main.h | 59 ++++++++++++++++++++++++++-
tools/virtio/ringtest/ptr_ring.c | 2 +-
7 files changed, 110 insertions(+), 45 deletions(-)
create mode 100644 tools/virtio/linux/thread_info.h
For the series:
Tested-by: Jason Wang <redacted>
Acked-by: Jason Wang <redacted>