diff options
author | David S. Miller <davem@davemloft.net> | 2018-01-29 12:02:55 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-01-29 12:02:55 -0500 |
commit | bfbe5bab66e1aa68033786599cc495e6728e55e8 (patch) | |
tree | 68e92d489b96c65ef2fe4a662d615d9400af3635 /tools | |
parent | 7ece54a60ee2ba7a386308cae73c790bd580589c (diff) | |
parent | 491847f3b29cef0417a03142b96e2a6dea81cca0 (diff) |
Merge branch 'ptr_ring-fixes'
Michael S. Tsirkin says:
====================
ptr_ring fixes
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.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Tested-by: Jason Wang <jasowang@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/virtio/linux/kernel.h | 2 | ||||
-rw-r--r-- | tools/virtio/linux/thread_info.h | 1 | ||||
-rw-r--r-- | tools/virtio/ringtest/main.h | 59 | ||||
-rw-r--r-- | tools/virtio/ringtest/ptr_ring.c | 2 |
4 files changed, 61 insertions, 3 deletions
diff --git a/tools/virtio/linux/kernel.h b/tools/virtio/linux/kernel.h index 395521a7a8d8..fca8381bbe04 100644 --- a/tools/virtio/linux/kernel.h +++ b/tools/virtio/linux/kernel.h | |||
@@ -118,7 +118,7 @@ static inline void free_page(unsigned long addr) | |||
118 | #define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__) | 118 | #define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__) |
119 | #define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__) | 119 | #define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__) |
120 | 120 | ||
121 | #define WARN_ON_ONCE(cond) ((cond) && fprintf (stderr, "WARNING\n")) | 121 | #define WARN_ON_ONCE(cond) ((cond) ? fprintf (stderr, "WARNING\n") : 0) |
122 | 122 | ||
123 | #define min(x, y) ({ \ | 123 | #define min(x, y) ({ \ |
124 | typeof(x) _min1 = (x); \ | 124 | typeof(x) _min1 = (x); \ |
diff --git a/tools/virtio/linux/thread_info.h b/tools/virtio/linux/thread_info.h new file mode 100644 index 000000000000..e0f610d08006 --- /dev/null +++ b/tools/virtio/linux/thread_info.h | |||
@@ -0,0 +1 @@ | |||
#define check_copy_size(A, B, C) (1) | |||
diff --git a/tools/virtio/ringtest/main.h b/tools/virtio/ringtest/main.h index 5706e075adf2..301d59bfcd0a 100644 --- a/tools/virtio/ringtest/main.h +++ b/tools/virtio/ringtest/main.h | |||
@@ -111,7 +111,7 @@ static inline void busy_wait(void) | |||
111 | } | 111 | } |
112 | 112 | ||
113 | #if defined(__x86_64__) || defined(__i386__) | 113 | #if defined(__x86_64__) || defined(__i386__) |
114 | #define smp_mb() asm volatile("lock; addl $0,-128(%%rsp)" ::: "memory", "cc") | 114 | #define smp_mb() asm volatile("lock; addl $0,-132(%%rsp)" ::: "memory", "cc") |
115 | #else | 115 | #else |
116 | /* | 116 | /* |
117 | * Not using __ATOMIC_SEQ_CST since gcc docs say they are only synchronized | 117 | * Not using __ATOMIC_SEQ_CST since gcc docs say they are only synchronized |
@@ -134,4 +134,61 @@ static inline void busy_wait(void) | |||
134 | barrier(); \ | 134 | barrier(); \ |
135 | } while (0) | 135 | } while (0) |
136 | 136 | ||
137 | #if defined(__i386__) || defined(__x86_64__) || defined(__s390x__) | ||
138 | #define smp_wmb() barrier() | ||
139 | #else | ||
140 | #define smp_wmb() smp_release() | ||
141 | #endif | ||
142 | |||
143 | #ifdef __alpha__ | ||
144 | #define smp_read_barrier_depends() smp_acquire() | ||
145 | #else | ||
146 | #define smp_read_barrier_depends() do {} while(0) | ||
147 | #endif | ||
148 | |||
149 | static __always_inline | ||
150 | void __read_once_size(const volatile void *p, void *res, int size) | ||
151 | { | ||
152 | switch (size) { \ | ||
153 | case 1: *(unsigned char *)res = *(volatile unsigned char *)p; break; \ | ||
154 | case 2: *(unsigned short *)res = *(volatile unsigned short *)p; break; \ | ||
155 | case 4: *(unsigned int *)res = *(volatile unsigned int *)p; break; \ | ||
156 | case 8: *(unsigned long long *)res = *(volatile unsigned long long *)p; break; \ | ||
157 | default: \ | ||
158 | barrier(); \ | ||
159 | __builtin_memcpy((void *)res, (const void *)p, size); \ | ||
160 | barrier(); \ | ||
161 | } \ | ||
162 | } | ||
163 | |||
164 | static __always_inline void __write_once_size(volatile void *p, void *res, int size) | ||
165 | { | ||
166 | switch (size) { | ||
167 | case 1: *(volatile unsigned char *)p = *(unsigned char *)res; break; | ||
168 | case 2: *(volatile unsigned short *)p = *(unsigned short *)res; break; | ||
169 | case 4: *(volatile unsigned int *)p = *(unsigned int *)res; break; | ||
170 | case 8: *(volatile unsigned long long *)p = *(unsigned long long *)res; break; | ||
171 | default: | ||
172 | barrier(); | ||
173 | __builtin_memcpy((void *)p, (const void *)res, size); | ||
174 | barrier(); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | #define READ_ONCE(x) \ | ||
179 | ({ \ | ||
180 | union { typeof(x) __val; char __c[1]; } __u; \ | ||
181 | __read_once_size(&(x), __u.__c, sizeof(x)); \ | ||
182 | smp_read_barrier_depends(); /* Enforce dependency ordering from x */ \ | ||
183 | __u.__val; \ | ||
184 | }) | ||
185 | |||
186 | #define WRITE_ONCE(x, val) \ | ||
187 | ({ \ | ||
188 | union { typeof(x) __val; char __c[1]; } __u = \ | ||
189 | { .__val = (typeof(x)) (val) }; \ | ||
190 | __write_once_size(&(x), __u.__c, sizeof(x)); \ | ||
191 | __u.__val; \ | ||
192 | }) | ||
193 | |||
137 | #endif | 194 | #endif |
diff --git a/tools/virtio/ringtest/ptr_ring.c b/tools/virtio/ringtest/ptr_ring.c index e6e81305ef46..477899c12c51 100644 --- a/tools/virtio/ringtest/ptr_ring.c +++ b/tools/virtio/ringtest/ptr_ring.c | |||
@@ -187,7 +187,7 @@ bool enable_kick() | |||
187 | 187 | ||
188 | bool avail_empty() | 188 | bool avail_empty() |
189 | { | 189 | { |
190 | return !__ptr_ring_peek(&array); | 190 | return __ptr_ring_empty(&array); |
191 | } | 191 | } |
192 | 192 | ||
193 | bool use_buf(unsigned *lenp, void **bufp) | 193 | bool use_buf(unsigned *lenp, void **bufp) |