Fix: callstack context memory corruption
[lttng-modules.git] / src / lttng-context.c
index eb5e5d113cd6bad3bc65a6c77f758ec9e9828ccb..9d6b71e0fdd7304491a0c541e2b3abaa420a99aa 100644 (file)
@@ -29,6 +29,8 @@ int lttng_find_context(struct lttng_ctx *ctx, const char *name)
 {
        unsigned int i;
 
+       if (!ctx)
+               return 0;
        for (i = 0; i < ctx->nr_fields; i++) {
                /* Skip allocated (but non-initialized) contexts */
                if (!ctx->fields[i].event_field.name)
@@ -63,18 +65,27 @@ int lttng_get_context_index(struct lttng_ctx *ctx, const char *name)
 }
 EXPORT_SYMBOL_GPL(lttng_get_context_index);
 
+struct lttng_ctx_field *lttng_get_context_field_from_index(struct lttng_ctx *ctx,
+               size_t index)
+{
+       if (index >= ctx->nr_fields)
+               return NULL;
+       return &ctx->fields[index];
+}
+EXPORT_SYMBOL_GPL(lttng_get_context_field_from_index);
+
 /*
  * Note: as we append context information, the pointer location may change.
  */
-struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
+ssize_t lttng_append_context_index(struct lttng_ctx **ctx_p)
 {
-       struct lttng_ctx_field *field;
        struct lttng_ctx *ctx;
+       ssize_t pos = -1;
 
        if (!*ctx_p) {
                *ctx_p = kzalloc(sizeof(struct lttng_ctx), GFP_KERNEL);
                if (!*ctx_p)
-                       return NULL;
+                       goto end;
                (*ctx_p)->largest_align = 1;
        }
        ctx = *ctx_p;
@@ -84,15 +95,29 @@ struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
                ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
                new_fields = lttng_kvzalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field), GFP_KERNEL);
                if (!new_fields)
-                       return NULL;
+                       goto end;
                if (ctx->fields)
                        memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
                lttng_kvfree(ctx->fields);
                ctx->fields = new_fields;
        }
-       field = &ctx->fields[ctx->nr_fields];
-       ctx->nr_fields++;
-       return field;
+       pos = ctx->nr_fields++;
+end:
+       return pos;
+}
+EXPORT_SYMBOL_GPL(lttng_append_context_index);
+
+/*
+ * Note: as we append context information, the pointer location may change.
+ */
+struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
+{
+       ssize_t pos;
+
+       pos = lttng_append_context_index(ctx_p);
+       if (pos < 0)
+               return NULL;
+       return &(*ctx_p)->fields[pos];
 }
 EXPORT_SYMBOL_GPL(lttng_append_context);
 
@@ -180,6 +205,22 @@ void lttng_context_update(struct lttng_ctx *ctx)
        ctx->largest_align = largest_align >> 3;        /* bits to bytes */
 }
 
+/* Keep same order. */
+void lttng_remove_context_field_index(struct lttng_ctx **ctx_p, size_t index)
+{
+       struct lttng_ctx *ctx = *ctx_p;
+
+       WARN_ON_ONCE(ctx->nr_fields >= index);
+       if (index != ctx->nr_fields - 1) {
+               memmove(&ctx->fields[index], &ctx->fields[index + 1],
+                       (ctx->nr_fields - index - 1) * sizeof(struct lttng_ctx_field));
+       }
+       /* Clear last item. */
+       memset(&ctx->fields[ctx->nr_fields - 1], 0, sizeof(struct lttng_ctx_field));
+       ctx->nr_fields--;
+}
+EXPORT_SYMBOL_GPL(lttng_remove_context_field_index);
+
 /*
  * Remove last context field.
  */
This page took 0.024784 seconds and 4 git commands to generate.