verityutils: fix a memory leak
this CL fixes a leak of malloc'ed memory, and introduces a tool that
makes malloc'ing this memory going forward a bit easier.
caught by the static analyzer:
> system/security/ondevice-signing/VerityUtils.cpp:189:71: warning:
Potential leak of memory pointed to by 'd' [clang-analyzer-unix.Malloc]
Bug: None
Test: TreeHugger
Change-Id: I8fe9dc047af729b0f5730ec1844b3902225fa73e
diff --git a/ondevice-signing/VerityUtils.cpp b/ondevice-signing/VerityUtils.cpp
index 71ba8f6..a8d72fc 100644
--- a/ondevice-signing/VerityUtils.cpp
+++ b/ondevice-signing/VerityUtils.cpp
@@ -88,19 +88,36 @@
return std::vector<uint8_t>(&digest->digest[0], &digest->digest[32]);
}
+namespace {
+template <typename T> struct DeleteAsPODArray {
+ void operator()(T* x) {
+ if (x) {
+ x->~T();
+ delete[](uint8_t*) x;
+ }
+ }
+};
+} // namespace
+
+template <typename T> using trailing_unique_ptr = std::unique_ptr<T, DeleteAsPODArray<T>>;
+
+template <typename T>
+static trailing_unique_ptr<T> makeUniqueWithTrailingData(size_t trailing_data_size) {
+ uint8_t* memory = new uint8_t[sizeof(T*) + trailing_data_size];
+ T* ptr = new (memory) T;
+ return trailing_unique_ptr<T>{ptr};
+}
+
static Result<std::vector<uint8_t>> signDigest(const SigningKey& key,
const std::vector<uint8_t>& digest) {
- fsverity_signed_digest* d;
- size_t signed_digest_size = sizeof(*d) + digest.size();
- std::unique_ptr<uint8_t[]> digest_buffer{new uint8_t[signed_digest_size]};
- d = (fsverity_signed_digest*)digest_buffer.get();
+ auto d = makeUniqueWithTrailingData<fsverity_signed_digest>(digest.size());
memcpy(d->magic, "FSVerity", 8);
d->digest_algorithm = cpu_to_le16(FS_VERITY_HASH_ALG_SHA256);
d->digest_size = cpu_to_le16(digest.size());
memcpy(d->digest, digest.data(), digest.size());
- auto signed_digest = key.sign(std::string((char*)d, signed_digest_size));
+ auto signed_digest = key.sign(std::string((char*)d.get(), sizeof(*d) + digest.size()));
if (!signed_digest.ok()) {
return signed_digest.error();
}
@@ -181,10 +198,9 @@
return Error() << "File is not in fs-verity: " << path;
}
- struct fsverity_digest* d;
- d = (struct fsverity_digest*)malloc(sizeof(*d) + FS_VERITY_MAX_DIGEST_SIZE);
+ auto d = makeUniqueWithTrailingData<fsverity_digest>(FS_VERITY_MAX_DIGEST_SIZE);
d->digest_size = FS_VERITY_MAX_DIGEST_SIZE;
- ret = ioctl(fd, FS_IOC_MEASURE_VERITY, d);
+ ret = ioctl(fd, FS_IOC_MEASURE_VERITY, d.get());
if (ret < 0) {
return ErrnoError() << "Failed to FS_IOC_MEASURE_VERITY for " << path;
}