Skip to content

Commit 65c56c8

Browse files
Ole Troanmgsmith1000
authored andcommitted
stats: missing dimension in stat_set_simple_counter
A simple counter is a two dimensional array by threads and counter index. 28017 introduced an error missing the first dimension. If a vector is updated at the same time as a client reads, an invalid pointer my result. This will be caught by the optimistic locking after copying out the data, but if following a pointer outside of the stat segment then the stat client would crash. Add suitable boundary checks for access to stat memory segment. Fixes: 7d29e32 Type: fix Signed-off-by: Ole Troan <ot@cisco.com> Change-Id: I94f124ec71d98218c4eda5d124ac5594743d93d6
1 parent 7ff514b commit 65c56c8

File tree

3 files changed

+26
-9
lines changed

3 files changed

+26
-9
lines changed

src/vpp-api/client/stat_client.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,16 @@ stat_segment_heartbeat (void)
192192
return stat_segment_heartbeat_r (sm);
193193
}
194194

195+
#define stat_vec_dup(S,V) \
196+
({ \
197+
__typeof__ ((V)[0]) * _v(v) = 0; \
198+
if (V && ((void *)V > (void *)S->shared_header) && \
199+
(((void*)V + vec_bytes(V)) < \
200+
((void *)S->shared_header + S->memory_size))) \
201+
_v(v) = vec_dup(V); \
202+
_v(v); \
203+
})
204+
195205
static stat_segment_data_t
196206
copy_data (stat_segment_directory_entry_t * ep, stat_client_main_t * sm)
197207
{
@@ -213,21 +223,21 @@ copy_data (stat_segment_directory_entry_t * ep, stat_client_main_t * sm)
213223

214224
case STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE:
215225
simple_c = stat_segment_adjust (sm, ep->data);
216-
result.simple_counter_vec = vec_dup (simple_c);
226+
result.simple_counter_vec = stat_vec_dup (sm, simple_c);
217227
for (i = 0; i < vec_len (simple_c); i++)
218228
{
219229
counter_t *cb = stat_segment_adjust (sm, simple_c[i]);
220-
result.simple_counter_vec[i] = vec_dup (cb);
230+
result.simple_counter_vec[i] = stat_vec_dup (sm, cb);
221231
}
222232
break;
223233

224234
case STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED:
225235
combined_c = stat_segment_adjust (sm, ep->data);
226-
result.combined_counter_vec = vec_dup (combined_c);
236+
result.combined_counter_vec = stat_vec_dup (sm, combined_c);
227237
for (i = 0; i < vec_len (combined_c); i++)
228238
{
229239
vlib_counter_t *cb = stat_segment_adjust (sm, combined_c[i]);
230-
result.combined_counter_vec[i] = vec_dup (cb);
240+
result.combined_counter_vec[i] = stat_vec_dup (sm, cb);
231241
}
232242
break;
233243

@@ -246,11 +256,11 @@ copy_data (stat_segment_directory_entry_t * ep, stat_client_main_t * sm)
246256
case STAT_DIR_TYPE_NAME_VECTOR:
247257
{
248258
uint8_t **name_vector = stat_segment_adjust (sm, ep->data);
249-
result.name_vector = vec_dup (name_vector);
259+
result.name_vector = stat_vec_dup (sm, name_vector);
250260
for (i = 0; i < vec_len (name_vector); i++)
251261
{
252262
u8 *name = stat_segment_adjust (sm, name_vector[i]);
253-
result.name_vector[i] = vec_dup (name);
263+
result.name_vector[i] = stat_vec_dup (sm, name);
254264
}
255265
}
256266
break;
@@ -290,6 +300,8 @@ stat_segment_data_free (stat_segment_data_t * res)
290300
case STAT_DIR_TYPE_ERROR_INDEX:
291301
vec_free (res[i].error_vector);
292302
break;
303+
case STAT_DIR_TYPE_SCALAR_INDEX:
304+
break;
293305
default:
294306
assert (0);
295307
}

src/vpp-api/client/stat_client.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,12 @@ _time_now_nsec (void)
101101
static inline void *
102102
stat_segment_adjust (stat_client_main_t * sm, void *data)
103103
{
104-
return (void *) ((char *) sm->shared_header +
105-
((char *) data - (char *) sm->shared_header->base));
104+
void *p = (void *) ((char *) sm->shared_header +
105+
((char *) data - (char *) sm->shared_header->base));
106+
if (p > (void *) sm->shared_header &&
107+
((p + sizeof (p)) < ((void *) sm->shared_header + sm->memory_size)))
108+
return p;
109+
return 0;
106110
}
107111

108112
/*

src/vpp/stats/stat_segment.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ stat_set_simple_counter (stat_segment_directory_entry_t * ep,
281281
u32 thread_index, u32 index, u64 value)
282282
{
283283
ASSERT (ep->data);
284-
counter_t *cb = ep->data;
284+
counter_t **counters = ep->data;
285+
counter_t *cb = counters[thread_index];
285286
cb[index] = value;
286287
}
287288

0 commit comments

Comments
 (0)