Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a9120be2 authored by Lee Shombert's avatar Lee Shombert
Browse files

Make PIC native code architecture independent

The size of size_t depends on the architecture (32-bit vs 64-bit).
This CL replaces all occurrences if size_t in the memory layout of PIC
nonces with int32_t.  int32_t is more than large enough and it is
guaranteed to be 4 bytes wide in all architectures.

Flag: EXEMPT bug-fix
Bug: 396674280
Test: atest
 * FrameworksCoreTests:PropertyInvalidatedCacheTests
 * FrameworksCoreTests:IpcDataCacheTest
 * CtsOsTestCases:IpcDataCacheTest
Change-Id: I281ecd59b506f64e625890d496d6dede4e178460
parent 4e69b471
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ int NonceStore::getMaxNonce() const {
    return kMaxNonce;
}

size_t NonceStore::getMaxByte() const {
int32_t NonceStore::getMaxByte() const {
    return kMaxByte;
}

@@ -68,13 +68,13 @@ int32_t NonceStore::getHash() const {
}

// Copy the byte block to the target and return the current hash.
int32_t NonceStore::getByteBlock(block_t* block, size_t len) const {
int32_t NonceStore::getByteBlock(block_t* block, int32_t len) const {
    memcpy(block, (void*) byteBlock(), std::min(kMaxByte, len));
    return mByteHash;
}

// Set the byte block and the hash.
void NonceStore::setByteBlock(int hash, const block_t* block, size_t len) {
void NonceStore::setByteBlock(int hash, const block_t* block, int32_t len) {
    memcpy((void*) byteBlock(), block, len = std::min(kMaxByte, len));
    mByteHash = hash;
}
+38 −16
Original line number Diff line number Diff line
@@ -27,8 +27,12 @@ namespace android::app::PropertyInvalidatedCache {
 * location.  Fields with a variable location are found via offsets.  The offsets make this
 * object position-independent, which is required because it is in shared memory and would be
 * mapped into different virtual addresses for different processes.
 *
 * This structure is shared between 64-bit and 32-bit processes.  Therefore it is imperative
 * that the structure not use any datatypes that are architecture-dependent (like size_t).
 * Additionally, care must be taken to avoid unexpected padding in the structure.
 */
class NonceStore {
class alignas(8) NonceStore {
  protected:
    // A convenient typedef.  The jbyteArray element type is jbyte, which the compiler treats as
    // signed char.
@@ -43,23 +47,27 @@ class NonceStore {
    // The value of an unset field.
    static constexpr int UNSET = 0;

    // The size of the nonce array.
    // The size of the nonce array.  This and the following sizes are int32_t to
    // be ABI independent.
    const int32_t kMaxNonce;

    // The size of the byte array.
    const size_t kMaxByte;
    const int32_t kMaxByte;

    // The offset to the nonce array.
    const size_t mNonceOffset;
    const int32_t mNonceOffset;

    // The offset to the byte array.
    const size_t mByteOffset;
    const int32_t mByteOffset;

    // The byte block hash.  This is fixed and at a known offset, so leave it in the base class.
    volatile std::atomic<int32_t> mByteHash;

    // A 4-byte padd that makes the size of this structure a multiple of 8 bytes.
    const int32_t _pad = 0;

    // The constructor is protected!  It only makes sense when called from a subclass.
    NonceStore(int kMaxNonce, size_t kMaxByte, volatile nonce_t* nonce, volatile block_t* block) :
    NonceStore(int kMaxNonce, int kMaxByte, volatile nonce_t* nonce, volatile block_t* block) :
            kMaxNonce(kMaxNonce),
            kMaxByte(kMaxByte),
            mNonceOffset(offset(this, const_cast<nonce_t*>(nonce))),
@@ -70,7 +78,7 @@ class NonceStore {

    // These provide run-time access to the sizing parameters.
    int getMaxNonce() const;
    size_t getMaxByte() const;
    int getMaxByte() const;

    // Fetch a nonce, returning UNSET if the index is out of range.  This method specifically
    // does not throw or generate an error if the index is out of range; this allows the method
@@ -86,10 +94,10 @@ class NonceStore {
    int32_t getHash() const;

    // Copy the byte block to the target and return the current hash.
    int32_t getByteBlock(block_t* block, size_t len) const;
    int32_t getByteBlock(block_t* block, int32_t len) const;

    // Set the byte block and the hash.
    void setByteBlock(int hash, const block_t* block, size_t len);
    void setByteBlock(int hash, const block_t* block, int32_t len);

  private:

@@ -113,6 +121,12 @@ class NonceStore {
    }
};

// Assert that the size of the object is fixed, independent of the CPU architecture.  There are
// four int32_t fields and one atomic<int32_t>, which sums to 20 bytes total.  This assertion
// uses a constant instead of computing the size of the objects in the compiler, to avoid
// different answers on different architectures.
static_assert(sizeof(NonceStore) == 24);

/**
 * A cache nonce block contains an array of std::atomic<int64_t> and an array of bytes.  The
 * byte array has an associated hash.  This class provides methods to read and write the fields
@@ -126,20 +140,22 @@ class NonceStore {
 * The template is parameterized by the number of nonces it supports and the number of bytes in
 * the string block.
 */
template<int maxNonce, size_t maxByte> class CacheNonce : public NonceStore {
template<int MAX_NONCE, int MAX_BYTE> class CacheNonce : public NonceStore {

    // The array of nonces
    volatile nonce_t mNonce[maxNonce];
    volatile nonce_t mNonce[MAX_NONCE];

    // The byte array.  This is not atomic but it is guarded by the mByteHash.
    volatile block_t mByteBlock[maxByte];
    volatile block_t mByteBlock[MAX_BYTE];

  public:
    // Export the parameters for use in compiler assertions.
    static constexpr int kMaxNonceCount = MAX_NONCE;
    static constexpr int kMaxByteCount = MAX_BYTE;

    // Construct and initialize the memory.
    CacheNonce() :
            NonceStore(maxNonce, maxByte, &mNonce[0], &mByteBlock[0])
    {
        for (int i = 0; i < maxNonce; i++) {
    CacheNonce() : NonceStore(MAX_NONCE, MAX_BYTE, &mNonce[0], &mByteBlock[0]) {
        for (int i = 0; i < MAX_NONCE; i++) {
            mNonce[i] = UNSET;
        }
        mByteHash = UNSET;
@@ -155,4 +171,10 @@ template<int maxNonce, size_t maxByte> class CacheNonce : public NonceStore {
typedef CacheNonce</* max nonce */ 128, /* byte block size */ 8192> SystemCacheNonce;
// LINT.ThenChange(/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java:system_nonce_config)

// Verify that there is no padding in the final class.
static_assert(sizeof(SystemCacheNonce) ==
              sizeof(NonceStore)
              + SystemCacheNonce::kMaxNonceCount*8
              + SystemCacheNonce::kMaxByteCount);

} // namespace android.app.PropertyInvalidatedCache