Skip to content

Commit

Permalink
libdrgn: kdump: simplify getting the PRSTATUS attributes
Browse files Browse the repository at this point in the history
Since the attribute hierarchy cannot change while iterating over the
PRSTATUS attributes, it is not necessary to take an attribute reference.

Although the attribute blob itself should not change either, it is a good
idea to keep its data pinned, because a raw pointer to it is stored in the
drgn_thread_set hash table. If some code tries to modify the PRSTATUS
attribute data, the attempt will fail with KDUMP_ERR_BUSY rather than leave
a dangling pointer in the hash table and possibly cause a UAF bug later.

Signed-off-by: Petr Tesarik <[email protected]>
  • Loading branch information
ptesarik committed Dec 2, 2024
1 parent fb6c32c commit 96ca7c4
Showing 1 changed file with 10 additions and 18 deletions.
28 changes: 10 additions & 18 deletions libdrgn/kdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,39 +299,31 @@ struct drgn_error *drgn_program_cache_kdump_threads(struct drgn_program *prog)
}

/*
* Note that in the following loop we never call kdump_attr_unref() on
* prstatus_ref, nor kdump_blob_unpin() on the prstatus blob that we get
* from libkdumpfile. Since drgn is completely read-only as a consumer
* of that library, we "leak" both the attribute reference and blob pin
* until kdump_free() is called which will clean up everything for us.
* Note that in the following loop we never call kdump_blob_unpin() on
* the prstatus blob that we get from libkdumpfile. Since drgn never
* modifies the PRSTATUS attributes (neither directly nor indirectly),
* we "leak" both the attribute value and blob pin until kdump_free()
* is called which will clean up everything for us.
*/
for (i = 0; i < ncpus; i++) {
/* Enough for the longest possible PRSTATUS attribute name. */
kdump_attr_ref_t prstatus_ref;
kdump_attr_t prstatus_attr;
void *prstatus_data;
size_t prstatus_size;

#define FORMAT "cpu.%" PRIuFAST64 ".PRSTATUS"
/* Enough for the longest possible PRSTATUS attribute name. */
char attr_name[sizeof(FORMAT)
- sizeof("%" PRIuFAST64)
+ max_decimal_length(uint_fast64_t)
+ 1];
snprintf(attr_name, sizeof(attr_name), FORMAT, i);
#undef FORMAT
ks = kdump_attr_ref(prog->kdump_ctx, attr_name, &prstatus_ref);
if (ks != KDUMP_OK) {
return drgn_error_format(DRGN_ERROR_OTHER,
"kdump_attr_ref(%s): %s",
attr_name,
kdump_get_err(prog->kdump_ctx));
}

ks = kdump_attr_ref_get(prog->kdump_ctx, &prstatus_ref,
&prstatus_attr);
prstatus_attr.type = KDUMP_BLOB;
ks = kdump_get_typed_attr(prog->kdump_ctx, attr_name,
&prstatus_attr);
if (ks != KDUMP_OK) {
return drgn_error_format(DRGN_ERROR_OTHER,
"kdump_attr_ref_get(%s): %s",
"kdump_get_typed_attr(%s): %s",
attr_name,
kdump_get_err(prog->kdump_ctx));
}
Expand Down

0 comments on commit 96ca7c4

Please sign in to comment.