2022-09-02 13:42:41

by Cezary Rojewski

[permalink] [raw]
Subject: [PATCH v4 0/2] lib/string_helpers: Introduce parse_int_array_user()

Continuation of recent upstream discussion [1] regarding user string
tokenization.

First, parse_int_array_user() is introduced to allow for splitting
specified user string into a sequence of integers. Makes use of
get_options() internally so the parsing logic is not duplicated.

With that done, redundant parts of the sound driver are removed.

Originally similar functionality was added for the SOF sound driver. As
more users are on the horizon, it is desirable to update existing
string_helpers code and provide a unified solution.


Changes in v4:
- renamed the function to parse_int_array_user()
- at the name several local variable names have been reworded to match
the above

Changes in v3:
- relocated tokenize_user_input() implementation to string_helpers as
requested by Matthew

Changes in v2:
- reused get_options() so no parsing logic is duplicated
- simplified __user variant with help of memdup_user_nul()
Both suggested by Andy, thanks for thourough review


[1]: https://lore.kernel.org/alsa-devel/[email protected]/


Cezary Rojewski (2):
lib/string_helpers: Introduce parse_int_array_user()
ASoC: SOF: Remove strsplit_u32() and tokenize_input()

include/linux/string_helpers.h | 2 +
lib/string_helpers.c | 45 +++++++++++++
sound/soc/sof/sof-client-probes.c | 104 ++++++------------------------
3 files changed, 65 insertions(+), 86 deletions(-)

--
2.25.1


2022-09-02 13:53:36

by Cezary Rojewski

[permalink] [raw]
Subject: [PATCH v4 1/2] lib/string_helpers: Introduce parse_int_array_user()

Add new helper function to allow for splitting specified user string
into a sequence of integers. Internally it makes use of get_options() so
the returned sequence contains the integers extracted plus an additional
element that begins the sequence and specifies the integers count.

Suggested-by: Andy Shevchenko <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
Signed-off-by: Cezary Rojewski <[email protected]>
---
include/linux/string_helpers.h | 2 ++
lib/string_helpers.c | 45 ++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)

diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h
index 4d72258d42fd..dc2e726fd820 100644
--- a/include/linux/string_helpers.h
+++ b/include/linux/string_helpers.h
@@ -21,6 +21,8 @@ enum string_size_units {
void string_get_size(u64 size, u64 blk_size, enum string_size_units units,
char *buf, int len);

+int parse_int_array_user(const char __user *from, size_t count, int **array);
+
#define UNESCAPE_SPACE BIT(0)
#define UNESCAPE_OCTAL BIT(1)
#define UNESCAPE_HEX BIT(2)
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 5ed3beb066e6..d0c8f6ecf84c 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -131,6 +131,51 @@ void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
}
EXPORT_SYMBOL(string_get_size);

+/**
+ * parse_int_array_user - Split string into a sequence of integers
+ * @from: The user space buffer to read from
+ * @ppos: The current position in the buffer
+ * @count: The maximum number of bytes to read
+ * @tkns: Returned pointer to sequence of integers
+ *
+ * On success @tkns is allocated and initialized with a sequence of
+ * integers extracted from the @from plus an additional element that
+ * begins the sequence and specifies the integers count.
+ *
+ * Caller takes responsibility for freeing @tkns when it is no longer
+ * needed.
+ */
+int parse_int_array_user(const char __user *from, size_t count, int **array)
+{
+ int *ints, nints;
+ char *buf;
+ int ret = 0;
+
+ buf = memdup_user_nul(from, count);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ get_options(buf, 0, &nints);
+ if (!nints) {
+ ret = -ENOENT;
+ goto free_buf;
+ }
+
+ ints = kcalloc(nints + 1, sizeof(*ints), GFP_KERNEL);
+ if (!ints) {
+ ret = -ENOMEM;
+ goto free_buf;
+ }
+
+ get_options(buf, nints + 1, ints);
+ *array = ints;
+
+free_buf:
+ kfree(buf);
+ return ret;
+}
+EXPORT_SYMBOL(parse_int_array_user);
+
static bool unescape_space(char **src, char **dst)
{
char *p = *dst, *q = *src;
--
2.25.1