Merge "graphics: fix a potential use after free"

This commit is contained in:
TreeHugger Robot
2017-03-10 20:51:47 +00:00
committed by Android (Google) Code Review
2 changed files with 91 additions and 37 deletions

View File

@@ -193,30 +193,30 @@ HandleImporter sHandleImporter;
} // anonymous namespace
BufferClone::BufferClone()
BufferCacheEntry::BufferCacheEntry()
: mHandle(nullptr)
{
}
BufferClone::BufferClone(BufferClone&& other)
BufferCacheEntry::BufferCacheEntry(BufferCacheEntry&& other)
{
mHandle = other.mHandle;
other.mHandle = nullptr;
}
BufferClone& BufferClone::operator=(buffer_handle_t handle)
BufferCacheEntry& BufferCacheEntry::operator=(buffer_handle_t handle)
{
clear();
mHandle = handle;
return *this;
}
BufferClone::~BufferClone()
BufferCacheEntry::~BufferCacheEntry()
{
clear();
}
void BufferClone::clear()
void BufferCacheEntry::clear()
{
if (mHandle) {
sHandleImporter.freeBuffer(mHandle);
@@ -745,10 +745,13 @@ bool ComposerClient::CommandReader::parseSetClientTarget(uint16_t length)
auto damage = readRegion((length - 4) / 4);
auto err = lookupBuffer(BufferCache::CLIENT_TARGETS,
slot, useCache, clientTarget);
slot, useCache, clientTarget, &clientTarget);
if (err == Error::NONE) {
err = mHal.setClientTarget(mDisplay, clientTarget, fence,
dataspace, damage);
updateBuffer(BufferCache::CLIENT_TARGETS, slot, useCache,
clientTarget);
}
if (err != Error::NONE) {
close(fence);
@@ -770,9 +773,12 @@ bool ComposerClient::CommandReader::parseSetOutputBuffer(uint16_t length)
auto fence = readFence();
auto err = lookupBuffer(BufferCache::OUTPUT_BUFFERS,
slot, useCache, outputBuffer);
slot, useCache, outputBuffer, &outputBuffer);
if (err == Error::NONE) {
err = mHal.setOutputBuffer(mDisplay, outputBuffer, fence);
updateBuffer(BufferCache::OUTPUT_BUFFERS,
slot, useCache, outputBuffer);
}
if (err != Error::NONE) {
close(fence);
@@ -870,9 +876,12 @@ bool ComposerClient::CommandReader::parseSetLayerBuffer(uint16_t length)
auto fence = readFence();
auto err = lookupBuffer(BufferCache::LAYER_BUFFERS,
slot, useCache, buffer);
slot, useCache, buffer, &buffer);
if (err == Error::NONE) {
err = mHal.setLayerBuffer(mDisplay, mLayer, buffer, fence);
updateBuffer(BufferCache::LAYER_BUFFERS,
slot, useCache, buffer);
}
if (err != Error::NONE) {
close(fence);
@@ -991,9 +1000,11 @@ bool ComposerClient::CommandReader::parseSetLayerSidebandStream(uint16_t length)
auto stream = readHandle();
auto err = lookupLayerSidebandStream(stream);
auto err = lookupLayerSidebandStream(stream, &stream);
if (err == Error::NONE) {
err = mHal.setLayerSidebandStream(mDisplay, mLayer, stream);
updateLayerSidebandStream(stream);
}
if (err != Error::NONE) {
mWriter.setError(getCommandLoc(), err);
@@ -1092,26 +1103,24 @@ hwc_frect_t ComposerClient::CommandReader::readFRect()
};
}
Error ComposerClient::CommandReader::lookupBuffer(BufferCache cache,
uint32_t slot, bool useCache, buffer_handle_t& handle)
Error ComposerClient::CommandReader::lookupBufferCacheEntryLocked(
BufferCache cache, uint32_t slot, BufferCacheEntry** outEntry)
{
std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
auto dpy = mClient.mDisplayData.find(mDisplay);
if (dpy == mClient.mDisplayData.end()) {
return Error::BAD_DISPLAY;
}
BufferClone* clone = nullptr;
BufferCacheEntry* entry = nullptr;
switch (cache) {
case BufferCache::CLIENT_TARGETS:
if (slot < dpy->second.ClientTargets.size()) {
clone = &dpy->second.ClientTargets[slot];
entry = &dpy->second.ClientTargets[slot];
}
break;
case BufferCache::OUTPUT_BUFFERS:
if (slot < dpy->second.OutputBuffers.size()) {
clone = &dpy->second.OutputBuffers[slot];
entry = &dpy->second.OutputBuffers[slot];
}
break;
case BufferCache::LAYER_BUFFERS:
@@ -1121,7 +1130,7 @@ Error ComposerClient::CommandReader::lookupBuffer(BufferCache cache,
return Error::BAD_LAYER;
}
if (slot < ly->second.Buffers.size()) {
clone = &ly->second.Buffers[slot];
entry = &ly->second.Buffers[slot];
}
}
break;
@@ -1132,7 +1141,7 @@ Error ComposerClient::CommandReader::lookupBuffer(BufferCache cache,
return Error::BAD_LAYER;
}
if (slot == 0) {
clone = &ly->second.SidebandStream;
entry = &ly->second.SidebandStream;
}
}
break;
@@ -1140,25 +1149,59 @@ Error ComposerClient::CommandReader::lookupBuffer(BufferCache cache,
break;
}
if (!clone) {
ALOGW("invalid buffer slot");
if (!entry) {
ALOGW("invalid buffer slot %" PRIu32, slot);
return Error::BAD_PARAMETER;
}
// use or update cache
*outEntry = entry;
return Error::NONE;
}
Error ComposerClient::CommandReader::lookupBuffer(BufferCache cache,
uint32_t slot, bool useCache, buffer_handle_t handle,
buffer_handle_t* outHandle)
{
if (useCache) {
handle = *clone;
std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
BufferCacheEntry* entry;
Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
if (error != Error::NONE) {
return error;
}
// input handle is ignored
*outHandle = entry->getHandle();
} else {
if (!sHandleImporter.importBuffer(handle)) {
return Error::NO_RESOURCES;
}
*clone = handle;
*outHandle = handle;
}
return Error::NONE;
}
void ComposerClient::CommandReader::updateBuffer(BufferCache cache,
uint32_t slot, bool useCache, buffer_handle_t handle)
{
// handle was looked up from cache
if (useCache) {
return;
}
std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
BufferCacheEntry* entry = nullptr;
lookupBufferCacheEntryLocked(cache, slot, &entry);
LOG_FATAL_IF(!entry, "failed to find the cache entry to update");
*entry = handle;
}
} // namespace implementation
} // namespace V2_1
} // namespace composer

View File

@@ -31,18 +31,18 @@ namespace composer {
namespace V2_1 {
namespace implementation {
class BufferClone {
class BufferCacheEntry {
public:
BufferClone();
BufferClone(BufferClone&& other);
BufferCacheEntry();
BufferCacheEntry(BufferCacheEntry&& other);
BufferClone(const BufferClone& other) = delete;
BufferClone& operator=(const BufferClone& other) = delete;
BufferCacheEntry(const BufferCacheEntry& other) = delete;
BufferCacheEntry& operator=(const BufferCacheEntry& other) = delete;
BufferClone& operator=(buffer_handle_t handle);
~BufferClone();
BufferCacheEntry& operator=(buffer_handle_t handle);
~BufferCacheEntry();
operator buffer_handle_t() const { return mHandle; }
buffer_handle_t getHandle() const { return mHandle; }
private:
void clear();
@@ -108,15 +108,15 @@ public:
protected:
struct LayerBuffers {
std::vector<BufferClone> Buffers;
BufferClone SidebandStream;
std::vector<BufferCacheEntry> Buffers;
BufferCacheEntry SidebandStream;
};
struct DisplayData {
bool IsVirtual;
std::vector<BufferClone> ClientTargets;
std::vector<BufferClone> OutputBuffers;
std::vector<BufferCacheEntry> ClientTargets;
std::vector<BufferCacheEntry> OutputBuffers;
std::unordered_map<Layer, LayerBuffers> Layers;
@@ -167,12 +167,23 @@ protected:
LAYER_BUFFERS,
LAYER_SIDEBAND_STREAMS,
};
Error lookupBufferCacheEntryLocked(BufferCache cache, uint32_t slot,
BufferCacheEntry** outEntry);
Error lookupBuffer(BufferCache cache, uint32_t slot,
bool useCache, buffer_handle_t& handle);
bool useCache, buffer_handle_t handle,
buffer_handle_t* outHandle);
void updateBuffer(BufferCache cache, uint32_t slot,
bool useCache, buffer_handle_t handle);
Error lookupLayerSidebandStream(buffer_handle_t& handle)
Error lookupLayerSidebandStream(buffer_handle_t handle,
buffer_handle_t* outHandle)
{
return lookupBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
0, false, handle, outHandle);
}
void updateLayerSidebandStream(buffer_handle_t handle)
{
updateBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
0, false, handle);
}