Bug 1290481 - P5: Implement a function to generate padding size. r=bkelly

MozReview-Commit-ID: 6poDeyErBjc

--HG--
extra : rebase_source : 982139c536c17a6699d700df7c8b3071939bb3c0
This commit is contained in:
Tom Tung 2017-07-10 17:03:24 +08:00
Родитель 29522efbef
Коммит a1e22fa9e7
7 изменённых файлов: 112 добавлений и 7 удалений

1
dom/cache/CacheTypes.ipdlh поставляемый
Просмотреть файл

@ -86,6 +86,7 @@ struct CacheResponse
CacheReadStreamOrVoid body;
IPCChannelInfo channelInfo;
OptionalPrincipalInfo principalInfo;
uint32_t paddingInfo;
int64_t paddingSize;
};

40
dom/cache/FileUtils.cpp поставляемый
Просмотреть файл

@ -31,6 +31,10 @@ using mozilla::dom::quota::QuotaObject;
namespace {
// Const variable for generate padding size.
// XXX This will be tweaked to something more meaningful in Bug 1383656.
const int64_t kRoundUpNumber = 20480;
enum BodyFileType
{
BODY_FILE_FINAL,
@ -42,7 +46,16 @@ BodyIdToFile(nsIFile* aBaseDir, const nsID& aId, BodyFileType aType,
nsIFile** aBodyFileOut);
int64_t
BodyGeneratePadding(const int64_t aBodyFileSize);
RoundUp(const int64_t aX, const int64_t aY);
// The alogrithm for generating padding refers to the mitigation approach in
// https://github.com/whatwg/storage/issues/31.
// First, generate a random number between 0 and 100kB.
// Next, round up the sum of random number and response size to the nearest
// 20kB.
// Finally, the virtual padding size will be the result minus the response size.
int64_t
BodyGeneratePadding(const int64_t aBodyFileSize, const uint32_t aPaddingInfo);
} // namespace
@ -254,7 +267,8 @@ BodyOpen(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir, const nsID& aId,
// static
nsresult
BodyMaybeUpdatePaddingSize(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir,
const nsID& aId, int64_t* aPaddingSizeOut)
const nsID& aId, const uint32_t aPaddingInfo,
int64_t* aPaddingSizeOut)
{
MOZ_DIAGNOSTIC_ASSERT(aBaseDir);
MOZ_DIAGNOSTIC_ASSERT(aPaddingSizeOut);
@ -277,7 +291,7 @@ BodyMaybeUpdatePaddingSize(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir,
MOZ_DIAGNOSTIC_ASSERT(fileSize >= 0);
if (*aPaddingSizeOut == InternalResponse::UNKNOWN_PADDING_SIZE) {
*aPaddingSizeOut = BodyGeneratePadding(fileSize);
*aPaddingSizeOut = BodyGeneratePadding(fileSize, aPaddingInfo);
}
MOZ_DIAGNOSTIC_ASSERT(*aPaddingSizeOut >= 0);
@ -354,10 +368,24 @@ BodyIdToFile(nsIFile* aBaseDir, const nsID& aId, BodyFileType aType,
}
int64_t
BodyGeneratePadding(const int64_t aBodyFileSize)
RoundUp(const int64_t aX, const int64_t aY)
{
// XXXtt: Will deal with it in the next patch.
return 0;
MOZ_DIAGNOSTIC_ASSERT(aX >= 0);
MOZ_DIAGNOSTIC_ASSERT(aY > 0);
MOZ_DIAGNOSTIC_ASSERT(INT64_MAX - ((aX - 1) / aY) * aY >= aY);
return aY + ((aX - 1) / aY) * aY;
}
int64_t
BodyGeneratePadding(const int64_t aBodyFileSize, const uint32_t aPaddingInfo)
{
// Generate padding
int64_t randomSize = static_cast<int64_t>(aPaddingInfo);
MOZ_DIAGNOSTIC_ASSERT(INT64_MAX - aBodyFileSize >= randomSize);
randomSize += aBodyFileSize;
return RoundUp(randomSize, kRoundUpNumber) - aBodyFileSize;
}
} // namespace

1
dom/cache/Manager.cpp поставляемый
Просмотреть файл

@ -785,6 +785,7 @@ private:
// It'll generate padding if we've not set it yet.
rv = BodyMaybeUpdatePaddingSize(mQuotaInfo.ref(), mDBDir,
e.mResponseBodyId,
e.mResponse.paddingInfo(),
&e.mResponse.paddingSize());
if (NS_WARN_IF(NS_FAILED(rv))) {
DoResolve(rv);

1
dom/cache/TypeUtils.cpp поставляемый
Просмотреть файл

@ -202,6 +202,7 @@ TypeUtils::ToCacheResponseWithoutBody(CacheResponse& aOut,
aOut.principalInfo() = void_t();
}
aOut.paddingInfo() = aIn.GetPaddingInfo();
aOut.paddingSize() = aIn.GetPaddingSize();
}

Просмотреть файл

@ -433,9 +433,12 @@ FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse,
case LoadTainting::CORS:
filteredResponse = aResponse->CORSResponse();
break;
case LoadTainting::Opaque:
case LoadTainting::Opaque: {
filteredResponse = aResponse->OpaqueResponse();
nsresult rv = filteredResponse->GeneratePaddingInfo();
if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; }
break;
}
default:
MOZ_CRASH("Unexpected case");
}
@ -614,6 +617,12 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
// Resolves fetch() promise which may trigger code running in a worker. Make
// sure the Response is fully initialized before calling this.
mResponse = BeginAndGetFilteredResponse(response, foundOpaqueRedirect);
if (NS_WARN_IF(!mResponse)) {
// Fail to generate a paddingInfo for opaque response.
MOZ_DIAGNOSTIC_ASSERT(mResponse->Type() == ResponseType::Opaque);
FailWithNetworkError();
return rv;
}
// From "Main Fetch" step 19: SRI-part1.
if (ShouldCheckSRI(mRequest, mResponse) && mSRIMetadata.IsEmpty()) {

Просмотреть файл

@ -11,12 +11,21 @@
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "nsIRandomGenerator.h"
#include "nsIURI.h"
#include "nsStreamUtils.h"
namespace mozilla {
namespace dom {
namespace {
// Const variable for generate padding size
// XXX This will be tweaked to something more meaningful in Bug 1383656.
const uint32_t kMaxRandomNumber = 102400;
} // namespace
InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText)
: mType(ResponseType::Default)
, mStatus(aStatus)
@ -145,6 +154,7 @@ InternalResponse::Clone(CloneType aCloneType)
clone->mHeaders = new InternalHeaders(*mHeaders);
// Make sure the clone response will have the same padding size.
clone->mPaddingInfo = mPaddingInfo;
clone->mPaddingSize = mPaddingSize;
if (mWrappedResponse) {
@ -194,6 +204,52 @@ InternalResponse::CORSResponse()
return cors.forget();
}
uint32_t
InternalResponse::GetPaddingInfo()
{
// If it's an opaque response, the paddingInfo should be generated only when
// paddingSize is unknown size.
// If it's not, the paddingInfo should be nothing and the paddingSize should
// be unknown size.
MOZ_DIAGNOSTIC_ASSERT((mType == ResponseType::Opaque &&
mPaddingSize == UNKNOWN_PADDING_SIZE &&
mPaddingInfo.isSome()) ||
(mType == ResponseType::Opaque &&
mPaddingSize != UNKNOWN_PADDING_SIZE &&
mPaddingInfo.isNothing()) ||
(mType != ResponseType::Opaque &&
mPaddingSize == UNKNOWN_PADDING_SIZE &&
mPaddingInfo.isNothing()));
return mPaddingInfo.isSome() ? mPaddingInfo.ref() : 0;
}
nsresult
InternalResponse::GeneratePaddingInfo()
{
MOZ_DIAGNOSTIC_ASSERT(mType == ResponseType::Opaque);
MOZ_DIAGNOSTIC_ASSERT(mPaddingSize == UNKNOWN_PADDING_SIZE);
// Utilize random generator to generator a random number
nsresult rv;
uint32_t randomNumber = 0;
nsCOMPtr<nsIRandomGenerator> randomGenerator =
do_GetService("@mozilla.org/security/random-generator;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
MOZ_DIAGNOSTIC_ASSERT(randomGenerator);
uint8_t* buffer;
rv = randomGenerator->GenerateRandomBytes(sizeof(randomNumber), &buffer);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
memcpy(&randomNumber, buffer, sizeof(randomNumber));
free(buffer);
mPaddingInfo.emplace(randomNumber % kMaxRandomNumber);
return rv;
}
int64_t
InternalResponse::GetPaddingSize()
{

Просмотреть файл

@ -233,6 +233,12 @@ public:
mBodySize = aBodySize;
}
uint32_t
GetPaddingInfo();
nsresult
GeneratePaddingInfo();
int64_t
GetPaddingSize();
@ -307,6 +313,9 @@ private:
RefPtr<InternalHeaders> mHeaders;
nsCOMPtr<nsIInputStream> mBody;
int64_t mBodySize;
// It's used to passed to the CacheResponse to generate padding size. Once, we
// generate the padding size for resposne, we don't need it anymore.
Maybe<uint32_t> mPaddingInfo;
int64_t mPaddingSize;
public:
static const int64_t UNKNOWN_BODY_SIZE = -1;