Open
Bug 1201666
Opened 10 years ago
Updated 1 year ago
Missing status check can cause variant_storage_traits<uint8_t[], false>::storage_conversion to silently elide data
Categories
(Core :: SQLite and Embedded Database Bindings, defect, P3)
Tracking
()
NEW
People
(Reporter: q1, Unassigned)
Details
(Keywords: reporter-external)
variant_storage_traits<uint8_t[], false>::storage_conversion (storage\src\Variant.h) does not check the status from its call to FallibleTArray::AppendElements, nor does it return the status to its callers. It thus can silently elide one or more elements from its output on OOM. This can compromise security. For example, EncodeKeysFunction::OnFunctionCall (dom\indexedDB\ActorsParent.cpp) uses storage::BlobVariant to extract an encryption key. But BlobVariant isa Variant<uint8_t[], false> (variant.h), and Variant<uint8_t[], false>::Variant uses variant_storage_traits<uint8_t[], false> to extract the key.
I have not analyzed others of storage_conversion's callers for their security impacts.
Details:
--------
The bugs are on variant.h lines 266-67 (no status check) and 262 (void return value):
257: template < >
258: struct variant_storage_traits<uint8_t[], false>
259: {
260: typedef std::pair<const void *, int> ConstructorType;
261: typedef FallibleTArray<uint8_t> StorageType;
262: static inline void storage_conversion(ConstructorType aBlob, StorageType* _outData)
263: {
264: _outData->Clear();
265: _outData->SetCapacity(aBlob.second);
266: (void)_outData->AppendElements(static_cast<const uint8_t *>(aBlob.first),
267: aBlob.second);
268: }
...
The indirect caller EncodeKeysFunction::OnFunctionCall (dom\indexedDB\ActorsParent.cpp) does:
2202: NS_IMETHOD
2203: OnFunctionCall(mozIStorageValueArray* aArguments,
2204: nsIVariant** aResult) override
2205: {
...
2244: const nsCString& buffer = key.GetBuffer();
2245:
2246: std::pair<const void *, int> data(static_cast<const void*>(buffer.get()),
2247: int(buffer.Length()));
2248:
2249: nsCOMPtr<nsIVariant> result = new mozilla::storage::BlobVariant(data);
2250:
2251: result.forget(aResult);
2252: return NS_OK;
2253: }
Line 2249 calls BlobVariant, which:
441: typedef Variant<uint8_t[], false> BlobVariant;
defines as:
378: template <typename DataType, bool Adopting=false>
379: class Variant final : public Variant_base
380: {
...
387: explicit Variant(const typename variant_storage_traits<DataType, Adopting>::ConstructorType aData)
388: {
389: variant_storage_traits<DataType, Adopting>::storage_conversion(aData, &mData);
390: }
...
which leads back to variant.h line 257, above.
9/3/2015's Aurora has the same defect, though the redundant call to SetCapacity on variant.h line 265 has been removed: http://hg.mozilla.org/releases/mozilla-aurora/file/1d9d6a7a958a/storage/Variant.h .
Updated•10 years ago
|
Flags: sec-bounty?
Updated•10 years ago
|
Component: Untriaged → DOM
Comment 1•10 years ago
|
||
Kyle, do you think this could cause a security issue?
Flags: needinfo?(khuey)
Updated•10 years ago
|
Group: core-security → dom-core-security
I doubt this is a security issue, because the fallible AppendElements either appends the whole thing or nothing.
Group: dom-core-security
Component: DOM → Storage
Flags: needinfo?(khuey)
Product: Core → Toolkit
Group: toolkit-core-security
(In reply to Kyle Huey [:khuey] (khuey@mozilla.com) (UTC+8 and delayed responses until 9/21) from comment #2)
> I doubt this is a security issue, because the fallible AppendElements either
> appends the whole thing or nothing.
If it appends nothing, some caller unexpectedly gets a null key. If it uses that key without checking it, whatever operation it performs will be either trivially weak (encryption, signing, hashing) or incorrect (decryption, signature verification).
The "key" here is not a cryptographic key, it's a key in the key-value store sense.
(In reply to Kyle Huey [:khuey] (khuey@mozilla.com) (UTC+8 and delayed responses until 9/21) from comment #4)
> The "key" here is not a cryptographic key, it's a key in the key-value store
> sense.
Ack! I should have looked deeper. Presumably then the security impact depends upon what the retrieval key is used for, and how lookup failures are handled.
Flags: needinfo?(mak77)
Comment 6•10 years ago
•
|
||
I agree with comment 2.
I think we want to preserve a fallible behavior here, because blobs can be large and we likely don't want a failed allocation to be fatal here.
Since I doubt we can do this at the constructor level without making this API fancy, I guess the best we can do is track a status mIsValid property that will likely be true for everything but the non-adopted blob variant (where it will depend on the result of AppendElements).
Then we can use it to bailout from asArray with an NS_ERROR_OUT_OF_MEMORY.
I'm not sure how we could write an automated test for that though.
Flags: needinfo?(mak77)
I don't think you can realistically do automated testing of OOM scenarios.
Comment 8•10 years ago
|
||
Opening this up since it isn't a security issue.
Updated•7 years ago
|
Priority: -- → P3
Updated•3 years ago
|
Severity: normal → S3
Updated•1 year ago
|
Keywords: reporter-external
Updated•1 year ago
|
Product: Toolkit → Core
You need to log in
before you can comment on or make changes to this bug.
Description
•