Skip to content

Potential Use-After-Free (UAF) in show_thread_status_json via failure path of json_object_add_value_object #2092

Description

@RigelYoung

Description of the bug

A potential Use-After-Free (UAF) vulnerability exists in stat.c within the show_thread_status_json() function (and potentially other places handling JSON nesting).

The root cause lies in an implicit ownership transfer combined with a lack of return-value checking during error handling in the internal JSON library (json.c).

Detailed Code Flow

  1. In stat.c, a JSON object is allocated: tmp = json_create_object();.
  2. It is then passed to nested helpers via json_object_add_value_object(root, "iodepth_level", tmp);, which internally invokes json_object_add_value_type(obj, name, arg).
  3. Inside json_object_add_value_type, tmp is wrapped into a new json_value via json_create_value_object().
  4. If a subsequent memory allocation fails (e.g., json_create_pair or json_object_add_pair returns an error), the code triggers the error handling path:
pair = json_create_pair(name, value);
if (!pair) {
    json_free_value(value); // <--- Triggers chain deletion
    return ENOMEM;
}
  1. json_free_value(value) inspects the type (JSON_TYPE_OBJECT) and automatically calls json_free_object(value->object). Since value->object points to tmp, tmp is freed here.
  2. However, show_thread_status_json() does not check the return value of json_object_add_value_object. It blindly continues to use the freed tmp pointer in the subsequent loop:
   for (i = 0; i < 7; i++) {
       // ...
       json_object_add_value_float(tmp, (const char *)name, io_u_dist[i]); // <--- USE AFTER FREE
   }

How to reproduce

This is a static code quality and robustness issue identified via static analysis tools. It is triggered during transient Out-Of-Memory (OOM) conditions where malloc returns NULL inside json_create_pair.

While it is hard to deterministically reproduce without fault injection (e.g., failmalloc), the control-flow and memory-flow in the source code clearly show that tmp is accessed after being freed in the ENOMEM branch.

Suggested Fix

The caller should check the return value of json_object_add_value_object. If it returns a non-zero error code (like ENOMEM), the execution should abort or skip the loop to prevent operating on the dangling pointer. Alternatively, the JSON library's error path should be refactored not to free objects it didn't allocate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions