Validate audio data instead of santinize in binder call.
In binder call, if the data is silently santinized, there may be
unexpected behavior. In that case, it is better to just validate the
data and returned error code if there is any error with the data.
Test: audio smoke test
Bug: 174189330
Change-Id: I2f0534f3013f9127a441306c3ff7d5ca8cc0e223
diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp
index 0779a8e..6c43fe0 100644
--- a/media/libmediahelper/Android.bp
+++ b/media/libmediahelper/Android.bp
@@ -20,7 +20,7 @@
double_loadable: true,
srcs: [
"AudioParameter.cpp",
- "AudioSanitizer.cpp",
+ "AudioValidator.cpp",
"TypeConverter.cpp",
],
cflags: [
diff --git a/media/libmediahelper/AudioSanitizer.cpp b/media/libmediahelper/AudioSanitizer.cpp
deleted file mode 100644
index 9223823..0000000
--- a/media/libmediahelper/AudioSanitizer.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-#include <media/AudioSanitizer.h>
-
-namespace android {
-
- /** returns true if string overflow was prevented by zero termination */
-template <size_t size>
-bool preventStringOverflow(char (&s)[size]) {
- if (strnlen(s, size) < size) return false;
- s[size - 1] = '\0';
- return true;
-}
-
-status_t safetyNetLog(status_t status, const char *bugNumber) {
- if (status != NO_ERROR && bugNumber != nullptr) {
- android_errorWriteLog(0x534e4554, bugNumber); // SafetyNet logging
- }
- return status;
-}
-
-status_t AudioSanitizer::sanitizeAudioAttributes(
- audio_attributes_t *attr, const char *bugNumber)
-{
- status_t status = NO_ERROR;
- const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE;
- if (strnlen(attr->tags, tagsMaxSize) >= tagsMaxSize) {
- status = BAD_VALUE;
- }
- attr->tags[tagsMaxSize - 1] = '\0';
- return safetyNetLog(status, bugNumber);
-}
-
-/** returns BAD_VALUE if sanitization was required. */
-status_t AudioSanitizer::sanitizeEffectDescriptor(
- effect_descriptor_t *desc, const char *bugNumber)
-{
- status_t status = NO_ERROR;
- if (preventStringOverflow(desc->name)
- | /* always */ preventStringOverflow(desc->implementor)) {
- status = BAD_VALUE;
- }
- return safetyNetLog(status, bugNumber);
-}
-
-/** returns BAD_VALUE if sanitization was required. */
-status_t AudioSanitizer::sanitizeAudioPortConfig(
- struct audio_port_config *config, const char *bugNumber)
-{
- status_t status = NO_ERROR;
- if (config->type == AUDIO_PORT_TYPE_DEVICE &&
- preventStringOverflow(config->ext.device.address)) {
- status = BAD_VALUE;
- }
- return safetyNetLog(status, bugNumber);
-}
-
-namespace {
-
-template <typename T, std::enable_if_t<std::is_same<T, struct audio_port>::value
- || std::is_same<T, struct audio_port_v7>::value, int> = 0>
-static status_t sanitizeAudioPortInternal(T *port, const char *bugNumber = nullptr) {
- status_t status = NO_ERROR;
- if (preventStringOverflow(port->name)) {
- status = BAD_VALUE;
- }
- if (AudioSanitizer::sanitizeAudioPortConfig(&port->active_config) != NO_ERROR) {
- status = BAD_VALUE;
- }
- if (port->type == AUDIO_PORT_TYPE_DEVICE &&
- preventStringOverflow(port->ext.device.address)) {
- status = BAD_VALUE;
- }
- return safetyNetLog(status, bugNumber);
-}
-
-} // namespace
-
-/** returns BAD_VALUE if sanitization was required. */
-status_t AudioSanitizer::sanitizeAudioPort(
- struct audio_port *port, const char *bugNumber)
-{
- return sanitizeAudioPortInternal(port, bugNumber);
-}
-
-/** returns BAD_VALUE if sanitization was required. */
-status_t AudioSanitizer::sanitizeAudioPort(
- struct audio_port_v7 *port, const char *bugNumber)
-{
- return sanitizeAudioPortInternal(port, bugNumber);
-}
-
-/** returns BAD_VALUE if sanitization was required. */
-status_t AudioSanitizer::sanitizeAudioPatch(
- struct audio_patch *patch, const char *bugNumber)
-{
- status_t status = NO_ERROR;
- if (patch->num_sources > AUDIO_PATCH_PORTS_MAX) {
- patch->num_sources = AUDIO_PATCH_PORTS_MAX;
- status = BAD_VALUE;
- }
- if (patch->num_sinks > AUDIO_PATCH_PORTS_MAX) {
- patch->num_sinks = AUDIO_PATCH_PORTS_MAX;
- status = BAD_VALUE;
- }
- for (size_t i = 0; i < patch->num_sources; i++) {
- if (sanitizeAudioPortConfig(&patch->sources[i]) != NO_ERROR) {
- status = BAD_VALUE;
- }
- }
- for (size_t i = 0; i < patch->num_sinks; i++) {
- if (sanitizeAudioPortConfig(&patch->sinks[i]) != NO_ERROR) {
- status = BAD_VALUE;
- }
- }
- return safetyNetLog(status, bugNumber);
-}
-
-}; // namespace android
diff --git a/media/libmediahelper/AudioValidator.cpp b/media/libmediahelper/AudioValidator.cpp
new file mode 100644
index 0000000..e2fd8ae
--- /dev/null
+++ b/media/libmediahelper/AudioValidator.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include <media/AudioValidator.h>
+
+namespace android {
+
+/** returns true if string is overflow */
+template <size_t size>
+bool checkStringOverflow(const char (&s)[size]) {
+ return strnlen(s, size) >= size;
+}
+
+status_t safetyNetLog(status_t status, std::string_view bugNumber) {
+ if (status != NO_ERROR && !bugNumber.empty()) {
+ android_errorWriteLog(0x534e4554, bugNumber.data()); // SafetyNet logging
+ }
+ return status;
+}
+
+status_t AudioValidator::validateAudioAttributes(
+ const audio_attributes_t& attr, std::string_view bugNumber)
+{
+ status_t status = NO_ERROR;
+ const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE;
+ if (strnlen(attr.tags, tagsMaxSize) >= tagsMaxSize) {
+ status = BAD_VALUE;
+ }
+ return safetyNetLog(status, bugNumber);
+}
+
+status_t AudioValidator::validateEffectDescriptor(
+ const effect_descriptor_t& desc, std::string_view bugNumber)
+{
+ status_t status = NO_ERROR;
+ if (checkStringOverflow(desc.name)
+ | /* always */ checkStringOverflow(desc.implementor)) {
+ status = BAD_VALUE;
+ }
+ return safetyNetLog(status, bugNumber);
+}
+
+status_t AudioValidator::validateAudioPortConfig(
+ const struct audio_port_config& config, std::string_view bugNumber)
+{
+ status_t status = NO_ERROR;
+ if (config.type == AUDIO_PORT_TYPE_DEVICE &&
+ checkStringOverflow(config.ext.device.address)) {
+ status = BAD_VALUE;
+ }
+ return safetyNetLog(status, bugNumber);
+}
+
+namespace {
+
+template <typename T, std::enable_if_t<std::is_same<T, struct audio_port>::value
+ || std::is_same<T, struct audio_port_v7>::value, int> = 0>
+static status_t validateAudioPortInternal(const T& port, std::string_view bugNumber = {}) {
+ status_t status = NO_ERROR;
+ if (checkStringOverflow(port.name)) {
+ status = BAD_VALUE;
+ }
+ if (AudioValidator::validateAudioPortConfig(port.active_config) != NO_ERROR) {
+ status = BAD_VALUE;
+ }
+ if (port.type == AUDIO_PORT_TYPE_DEVICE &&
+ checkStringOverflow(port.ext.device.address)) {
+ status = BAD_VALUE;
+ }
+ return safetyNetLog(status, bugNumber);
+}
+
+} // namespace
+
+status_t AudioValidator::validateAudioPort(
+ const struct audio_port& port, std::string_view bugNumber)
+{
+ return validateAudioPortInternal(port, bugNumber);
+}
+
+status_t AudioValidator::validateAudioPort(
+ const struct audio_port_v7& port, std::string_view bugNumber)
+{
+ return validateAudioPortInternal(port, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioValidator::validateAudioPatch(
+ const struct audio_patch& patch, std::string_view bugNumber)
+{
+ status_t status = NO_ERROR;
+ if (patch.num_sources > AUDIO_PATCH_PORTS_MAX) {
+ status = BAD_VALUE;
+ }
+ if (patch.num_sinks > AUDIO_PATCH_PORTS_MAX) {
+ status = BAD_VALUE;
+ }
+ for (size_t i = 0; i < patch.num_sources; i++) {
+ if (validateAudioPortConfig(patch.sources[i]) != NO_ERROR) {
+ status = BAD_VALUE;
+ }
+ }
+ for (size_t i = 0; i < patch.num_sinks; i++) {
+ if (validateAudioPortConfig(patch.sinks[i]) != NO_ERROR) {
+ status = BAD_VALUE;
+ }
+ }
+ return safetyNetLog(status, bugNumber);
+}
+
+}; // namespace android
diff --git a/media/libmediahelper/include/media/AudioSanitizer.h b/media/libmediahelper/include/media/AudioSanitizer.h
deleted file mode 100644
index 84bcb62..0000000
--- a/media/libmediahelper/include/media/AudioSanitizer.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-#ifndef ANDROID_AUDIO_SANITIZER_H_
-#define ANDROID_AUDIO_SANITIZER_H_
-
-#include <system/audio.h>
-#include <system/audio_effect.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-namespace android {
-
-class AudioSanitizer {
-public:
- static status_t sanitizeAudioAttributes(
- audio_attributes_t *attr, const char *bugNumber = nullptr);
-
- static status_t sanitizeEffectDescriptor(
- effect_descriptor_t *desc, const char *bugNumber = nullptr);
-
- static status_t sanitizeAudioPortConfig(
- struct audio_port_config *config, const char *bugNumber = nullptr);
-
- static status_t sanitizeAudioPort(
- struct audio_port *port, const char *bugNumber = nullptr);
-
- static status_t sanitizeAudioPort(
- struct audio_port_v7 *port, const char *bugNumber = nullptr);
-
- static status_t sanitizeAudioPatch(
- struct audio_patch *patch, const char *bugNumber = nullptr);
-};
-
-}; // namespace android
-
-#endif /*ANDROID_AUDIO_SANITIZER_H_*/
diff --git a/media/libmediahelper/include/media/AudioValidator.h b/media/libmediahelper/include/media/AudioValidator.h
new file mode 100644
index 0000000..008868e
--- /dev/null
+++ b/media/libmediahelper/include/media/AudioValidator.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef ANDROID_AUDIO_VALIDATOR_H_
+#define ANDROID_AUDIO_VALIDATOR_H_
+
+#include <system/audio.h>
+#include <system/audio_effect.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <string_view>
+
+namespace android {
+
+/**
+ * AudioValidator is a class to validate audio data in binder call. NO_ERROR will be returned only
+ * when there is no error with the data.
+ */
+class AudioValidator {
+public:
+ /**
+ * Return NO_ERROR only when there is no error with the given audio attributes.
+ * Otherwise, return BAD_VALUE.
+ */
+ static status_t validateAudioAttributes(
+ const audio_attributes_t& attr, std::string_view bugNumber = {});
+
+ /**
+ * Return NO_ERROR only when there is no error with the given effect descriptor.
+ * Otherwise, return BAD_VALUE.
+ */
+ static status_t validateEffectDescriptor(
+ const effect_descriptor_t& desc, std::string_view bugNumber = {});
+
+ /**
+ * Return NO_ERROR only when there is no error with the given audio port config.
+ * Otherwise, return BAD_VALUE.
+ */
+ static status_t validateAudioPortConfig(
+ const struct audio_port_config& config, std::string_view bugNumber = {});
+
+ /**
+ * Return NO_ERROR only when there is no error with the given audio port.
+ * Otherwise, return BAD_VALUE.
+ */
+ static status_t validateAudioPort(
+ const struct audio_port& port, std::string_view bugNumber = {});
+
+ /**
+ * Return NO_ERROR only when there is no error with the given audio_port_v7.
+ * Otherwise, return BAD_VALUE.
+ */
+ static status_t validateAudioPort(
+ const struct audio_port_v7& port, std::string_view ugNumber = {});
+
+ /**
+ * Return NO_ERROR only when there is no error with the given audio patch.
+ * Otherwise, return BAD_VALUE.
+ */
+ static status_t validateAudioPatch(
+ const struct audio_patch& patch, std::string_view bugNumber = {});
+};
+
+}; // namespace android
+
+#endif /*ANDROID_AUDIO_VALIDATOR_H_*/