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

Commit 3385a2c8 authored by Peter Collingbourne's avatar Peter Collingbourne
Browse files

Preserve x18 while calling aptX encoder libraries.

Shadow call stack (SCS) is a security mitigation that uses a
separate stack (the SCS) for return addresses. In versions of
Android newer than P, the compiler normally cooperates with the
system to ensure that the SCS address is always stored in register
x18. This requires that everything in a process that uses SCS is
built with -ffixed-x18. However, two libraries (libaptX_encoder.so
and libaptXHD_encoder.so) are supplied in binary format and were
not compiled with -ffixed-x18. We are working with the vendor to get
these libraries rebuilt with -ffixed-x18, but until then, we need to
prevent this library from clobbering x18 so that we can turn on SCS
in the Bluetooth process.

Bug: 112907825
Bug: 120621517
Change-Id: Id27829ed5696903c42b4aeb75c3b3880c97a3a36
parent 340bd680
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

// Prevent x18 (shadow call stack address) from being clobbered by functions
// called by a function that declares a variable of this type by temporarily
// storing the value on the stack. This is used only when calling out to certain
// vendor libraries.
struct ScopedSCSExit {
#ifdef __aarch64__
    void* scs;

    __attribute__((always_inline, no_sanitize("shadow-call-stack"))) ScopedSCSExit() {
        __asm__ __volatile__("str x18, [%0]" ::"r"(&scs));
    }

    __attribute__((always_inline, no_sanitize("shadow-call-stack"))) ~ScopedSCSExit() {
        __asm__ __volatile__("ldr x18, [%0]; str xzr, [%0]" ::"r"(&scs));
    }
#else
    // Silence unused variable warnings in non-SCS builds.
    __attribute__((no_sanitize("shadow-call-stack"))) ScopedSCSExit() {}
    __attribute__((no_sanitize("shadow-call-stack"))) ~ScopedSCSExit() {}
#endif
};
+24 −4
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "a2dp_vendor.h"
#include "a2dp_vendor_aptx.h"
#include "bt_common.h"
#include "common/scoped_scs_exit.h"
#include "common/time_util.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -54,6 +55,25 @@ static tAPTX_ENCODER_INIT aptx_encoder_init_func;
static tAPTX_ENCODER_ENCODE_STEREO aptx_encoder_encode_stereo_func;
static tAPTX_ENCODER_SIZEOF_PARAMS aptx_encoder_sizeof_params_func;

__attribute__((no_sanitize("shadow-call-stack")))
static int aptx_encoder_init(void* state, short endian) {
  ScopedSCSExit x;
  return aptx_encoder_init_func(state, endian);
}

__attribute__((no_sanitize("shadow-call-stack")))
static int aptx_encoder_encode_stereo(void* state, void* pcmL, void* pcmR,
                                      void* buffer) {
  ScopedSCSExit x;
  return aptx_encoder_encode_stereo_func(state, pcmL, pcmR, buffer);
}

__attribute__((no_sanitize("shadow-call-stack")))
static int aptx_encoder_sizeof_params() {
  ScopedSCSExit x;
  return aptx_encoder_sizeof_params_func();
}

// offset
#if (BTA_AV_CO_CP_SCMS_T == TRUE)
#define A2DP_APTX_OFFSET (AVDT_MEDIA_OFFSET + 1)
@@ -192,9 +212,9 @@ void a2dp_vendor_aptx_encoder_init(
#endif

  a2dp_aptx_encoder_cb.aptx_encoder_state =
      osi_malloc(aptx_encoder_sizeof_params_func());
      osi_malloc(aptx_encoder_sizeof_params());
  if (a2dp_aptx_encoder_cb.aptx_encoder_state != NULL) {
    aptx_encoder_init_func(a2dp_aptx_encoder_cb.aptx_encoder_state, 0);
    aptx_encoder_init(a2dp_aptx_encoder_cb.aptx_encoder_state, 0);
  } else {
    LOG_ERROR(LOG_TAG, "%s: Cannot allocate aptX encoder state", __func__);
    // TODO: Return an error?
@@ -466,8 +486,8 @@ static size_t aptx_encode_16bit(tAPTX_FRAMING_PARAMS* framing_params,
      pcmR[i] = (uint16_t) * (data16_in + ((2 * j) + 1));
    }

    aptx_encoder_encode_stereo_func(a2dp_aptx_encoder_cb.aptx_encoder_state,
                                    &pcmL, &pcmR, &encoded_sample);
    aptx_encoder_encode_stereo(a2dp_aptx_encoder_cb.aptx_encoder_state, &pcmL,
                               &pcmR, &encoded_sample);

    data_out[*data_out_index + 0] = (uint8_t)((encoded_sample[0] >> 8) & 0xff);
    data_out[*data_out_index + 1] = (uint8_t)((encoded_sample[0] >> 0) & 0xff);
+23 −3
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "a2dp_vendor.h"
#include "a2dp_vendor_aptx_hd.h"
#include "bt_common.h"
#include "common/scoped_scs_exit.h"
#include "common/time_util.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -55,6 +56,25 @@ static tAPTX_HD_ENCODER_INIT aptx_hd_encoder_init_func;
static tAPTX_HD_ENCODER_ENCODE_STEREO aptx_hd_encoder_encode_stereo_func;
static tAPTX_HD_ENCODER_SIZEOF_PARAMS aptx_hd_encoder_sizeof_params_func;

__attribute__((no_sanitize("shadow-call-stack")))
static int aptx_hd_encoder_init(void* state, short endian) {
  ScopedSCSExit x;
  return aptx_hd_encoder_init_func(state, endian);
}

__attribute__((no_sanitize("shadow-call-stack")))
static int aptx_hd_encoder_encode_stereo(void* state, void* pcmL, void* pcmR,
                                         void* buffer) {
  ScopedSCSExit x;
  return aptx_hd_encoder_encode_stereo_func(state, pcmL, pcmR, buffer);
}

__attribute__((no_sanitize("shadow-call-stack")))
static int aptx_hd_encoder_sizeof_params() {
  ScopedSCSExit x;
  return aptx_hd_encoder_sizeof_params_func();
}

// offset
#if (BTA_AV_CO_CP_SCMS_T == TRUE)
#define A2DP_APTX_HD_OFFSET (AVDT_MEDIA_OFFSET + 1)
@@ -193,9 +213,9 @@ void a2dp_vendor_aptx_hd_encoder_init(
#endif

  a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state =
      osi_malloc(aptx_hd_encoder_sizeof_params_func());
      osi_malloc(aptx_hd_encoder_sizeof_params());
  if (a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state != NULL) {
    aptx_hd_encoder_init_func(a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state, 0);
    aptx_hd_encoder_init(a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state, 0);
  } else {
    LOG_ERROR(LOG_TAG, "%s: Cannot allocate aptX-HD encoder state", __func__);
    // TODO: Return an error?
@@ -460,7 +480,7 @@ static size_t aptx_hd_encode_24bit(tAPTX_HD_FRAMING_PARAMS* framing_params,
      p += 3;
    }

    aptx_hd_encoder_encode_stereo_func(
    aptx_hd_encoder_encode_stereo(
        a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state, &pcmL, &pcmR,
        &encoded_sample);