diff options
Diffstat (limited to 'dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.c')
-rw-r--r-- | dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.c | 104 |
1 files changed, 85 insertions, 19 deletions
diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.c index 37e507b..973739f 100644 --- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.c +++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.c @@ -1,11 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2019 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2021 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 * Foundation, and any use by you of this program is subject to the terms - * of such GNU licence. + * of such GNU license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,8 +17,6 @@ * along with this program; if not, you can access it online at * http://www.gnu.org/licenses/gpl-2.0.html. * - * SPDX-License-Identifier: GPL-2.0 - * */ #include <linux/debugfs.h> @@ -46,10 +45,9 @@ * * Return: 0 if success, negative error code otherwise. */ -static int set_attr_from_string( - char *const buf, - void *const array, size_t const nelems, - kbase_debugfs_helper_set_attr_fn const set_attr_fn) +static int +set_attr_from_string(char *const buf, void *const array, size_t const nelems, + kbase_debugfs_helper_set_attr_fn *const set_attr_fn) { size_t index, err = 0; char *ptr = buf; @@ -90,9 +88,62 @@ static int set_attr_from_string( return err; } +int kbase_debugfs_string_validator(char *const buf) +{ + size_t index; + int err = 0; + char *ptr = buf; + + for (index = 0; *ptr; ++index) { + unsigned long test_number; + size_t len; + + /* Drop leading spaces */ + while (*ptr == ' ') + ptr++; + + /* Strings passed into the validator will be NULL terminated + * by nature, so here strcspn only needs to delimit by + * newlines, spaces and NULL terminator (delimited natively). + */ + len = strcspn(ptr, "\n "); + if (len == 0) { + /* No more values (allow this) */ + break; + } + + /* Substitute a nul terminator for a space character to make + * the substring valid for kstrtoul, and then replace it back. + */ + if (ptr[len] == ' ') { + ptr[len] = '\0'; + err = kstrtoul(ptr, 0, &test_number); + ptr[len] = ' '; + + /* len should only be incremented if there is a valid + * number to follow - otherwise this will skip over + * the NULL terminator in cases with no ending newline + */ + len++; + } else { + /* This would occur at the last element before a space + * or a NULL terminator. + */ + err = kstrtoul(ptr, 0, &test_number); + } + + if (err) + break; + /* Skip the substring (including any premature nul terminator) + */ + ptr += len; + } + return err; +} + int kbase_debugfs_helper_set_attr_from_string( const char *const buf, void *const array, size_t const nelems, - kbase_debugfs_helper_set_attr_fn const set_attr_fn) + kbase_debugfs_helper_set_attr_fn *const set_attr_fn) { char *const wbuf = kstrdup(buf, GFP_KERNEL); int err = 0; @@ -100,6 +151,13 @@ int kbase_debugfs_helper_set_attr_from_string( if (!wbuf) return -ENOMEM; + /* validate string before actually writing values */ + err = kbase_debugfs_string_validator(wbuf); + if (err) { + kfree(wbuf); + return err; + } + err = set_attr_from_string(wbuf, array, nelems, set_attr_fn); @@ -108,9 +166,9 @@ int kbase_debugfs_helper_set_attr_from_string( } ssize_t kbase_debugfs_helper_get_attr_to_string( - char *const buf, size_t const size, - void *const array, size_t const nelems, - kbase_debugfs_helper_get_attr_fn const get_attr_fn) + char *const buf, size_t const size, void *const array, + size_t const nelems, + kbase_debugfs_helper_get_attr_fn *const get_attr_fn) { ssize_t total = 0; size_t index; @@ -128,10 +186,10 @@ ssize_t kbase_debugfs_helper_get_attr_to_string( return total; } -int kbase_debugfs_helper_seq_write(struct file *const file, - const char __user *const ubuf, size_t const count, - size_t const nelems, - kbase_debugfs_helper_set_attr_fn const set_attr_fn) +int kbase_debugfs_helper_seq_write( + struct file *const file, const char __user *const ubuf, + size_t const count, size_t const nelems, + kbase_debugfs_helper_set_attr_fn *const set_attr_fn) { const struct seq_file *const sfile = file->private_data; void *const array = sfile->private; @@ -154,6 +212,14 @@ int kbase_debugfs_helper_seq_write(struct file *const file, } buf[count] = '\0'; + + /* validate string before actually writing values */ + err = kbase_debugfs_string_validator(buf); + if (err) { + kfree(buf); + return err; + } + err = set_attr_from_string(buf, array, nelems, set_attr_fn); kfree(buf); @@ -161,9 +227,9 @@ int kbase_debugfs_helper_seq_write(struct file *const file, return err; } -int kbase_debugfs_helper_seq_read(struct seq_file *const sfile, - size_t const nelems, - kbase_debugfs_helper_get_attr_fn const get_attr_fn) +int kbase_debugfs_helper_seq_read( + struct seq_file *const sfile, size_t const nelems, + kbase_debugfs_helper_get_attr_fn *const get_attr_fn) { void *const array = sfile->private; size_t index; |