GPUCORE-37217 Restrict permissions for TLSTREAM interface Permissions have been restricted for the interface to acquire a file descriptor for the Timeline Stream. Unless the user process is privileged, now at least one of these conditions must be satisftied: * The kbase_unprivileged_global_profiling module parameter has been set to 1. * The user process has the CAP_SYS_ADMIN capability. * The user process has the CAP_PERFMON capability. The parameter callbacks only allow enabling the feature if it's disabled, but not disabling it once it is enabled. Global profiling is allowed for unprivileged processes when Kbase development support is not stripped. The permissions for the debugfs entry of TLSTREAM have been restricted, too, in order to prevent non-privileged processes to access this entry even in systems where /sys/kernel/debug is accessible to non-privileged processes (which is usually not the case). Change-Id: Ie5f113a8beea5b5ce5c1991b4c863ab8cb64c455 (cherry picked from commit ef2064d3e9cf8a351411bdb28baa1cc22b3e293c) Bug: 272345974 Provenance: https://code.ipdelivery.arm.com/c/GPU/mali-ddk/+/4942 Signed-off-by: Guus Sliepen <gsliepen@google.com>
diff --git a/mali_kbase/tl/mali_kbase_timeline_io.c b/mali_kbase/tl/mali_kbase_timeline_io.c index 03178cc..359ee4e 100644 --- a/mali_kbase/tl/mali_kbase_timeline_io.c +++ b/mali_kbase/tl/mali_kbase_timeline_io.c
@@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -30,6 +30,64 @@ #include <linux/version_compat_defs.h> #include <linux/anon_inodes.h> +/* Explicitly include epoll header for old kernels. Not required from 4.16. */ +#if KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE +#include <uapi/linux/eventpoll.h> +#endif + +#ifndef MALI_STRIP_KBASE_DEVELOPMENT +/* Development builds need to test instrumentation and enable unprivileged + * processes to acquire timeline streams, in order to avoid complications + * with configurations across multiple platforms and systems. + * + * Release builds, instead, shall deny access to unprivileged processes + * because there are no use cases where they are allowed to acquire timeline + * streams, unless they're given special permissions by a privileged process. + */ +static int kbase_unprivileged_global_profiling = 1; +#else +static int kbase_unprivileged_global_profiling; +#endif + +/** + * kbase_unprivileged_global_profiling_set - set permissions for unprivileged processes + * + * @val: String containing value to set. Only strings representing positive + * integers are accepted as valid; any non-positive integer (including 0) + * is rejected. + * @kp: Module parameter associated with this method. + * + * This method can only be used to enable permissions for unprivileged processes, + * if they are disabled: for this reason, the only values which are accepted are + * strings representing positive integers. Since it's impossible to disable + * permissions once they're set, any integer which is non-positive is rejected, + * including 0. + * + * Return: 0 if success, otherwise error code. + */ +static int kbase_unprivileged_global_profiling_set(const char *val, const struct kernel_param *kp) +{ + int new_val; + int ret = kstrtoint(val, 0, &new_val); + + if (ret == 0) { + if (new_val < 1) + return -EINVAL; + + kbase_unprivileged_global_profiling = 1; + } + + return ret; +} + +static const struct kernel_param_ops kbase_global_unprivileged_profiling_ops = { + .get = param_get_int, + .set = kbase_unprivileged_global_profiling_set, +}; + +module_param_cb(kbase_unprivileged_global_profiling, &kbase_global_unprivileged_profiling_ops, + &kbase_unprivileged_global_profiling, 0600); + /* The timeline stream file operations functions. */ static ssize_t kbasep_timeline_io_read(struct file *filp, char __user *buffer, size_t size, loff_t *f_pos); @@ -38,6 +96,15 @@ static int kbasep_timeline_io_fsync(struct file *filp, loff_t start, loff_t end, int datasync); +static bool timeline_is_permitted(void) +{ +#if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE + return kbase_unprivileged_global_profiling || perfmon_capable(); +#else + return kbase_unprivileged_global_profiling || capable(CAP_SYS_ADMIN); +#endif +} + /** * kbasep_timeline_io_packet_pending - check timeline streams for pending * packets @@ -321,6 +388,9 @@ }; int err; + if (!timeline_is_permitted()) + return -EPERM; + if (WARN_ON(!kbdev) || (flags & ~BASE_TLSTREAM_FLAGS_MASK)) return -EINVAL; @@ -364,7 +434,7 @@ if (WARN_ON(!kbdev) || WARN_ON(IS_ERR_OR_NULL(kbdev->mali_debugfs_directory))) return; - file = debugfs_create_file("tlstream", 0444, kbdev->mali_debugfs_directory, kbdev, + file = debugfs_create_file("tlstream", 0400, kbdev->mali_debugfs_directory, kbdev, &kbasep_tlstream_debugfs_fops); if (IS_ERR_OR_NULL(file))