* [PATCH v3 1/6] uaccess: move probe_kernel_* functions to lib/uaccess.c
2009-02-26 18:54 [PATCH v3 0/6] [RFC] copy_strtok_from_user Steven Rostedt
@ 2009-02-26 18:54 ` Steven Rostedt
2009-02-26 18:54 ` [PATCH v3 2/6] string: add strtok_r to kernel Steven Rostedt
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2009-02-26 18:54 UTC (permalink / raw)
To: linux-kernel
Cc: Ingo Molnar, Andrew Morton, Peter Zijlstra, Frederic Weisbecker,
H. Peter Anvin, Steven Rostedt
[-- Attachment #1: 0001-uaccess-move-probe_kernel_-functions-to-lib-uacces.patch --]
[-- Type: text/plain, Size: 4955 bytes --]
From: Steven Rostedt <srostedt@redhat.com>
This patch moves the file mm/maccess.c to lib/uaccess.c. This
is a more generic location to find lib utils. Since probe_kernel_*
are declared in linux/uaccess.h, having them in a file named uaccess.c
seems to be a better place.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
lib/Makefile | 3 ++-
lib/uaccess.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
mm/Makefile | 2 +-
mm/maccess.c | 55 -------------------------------------------------------
4 files changed, 58 insertions(+), 57 deletions(-)
create mode 100644 lib/uaccess.c
delete mode 100644 mm/maccess.c
diff --git a/lib/Makefile b/lib/Makefile
index 32b0e64..46ce28c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -11,7 +11,8 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
rbtree.o radix-tree.o dump_stack.o \
idr.o int_sqrt.o extable.o prio_tree.o \
sha1.o irq_regs.o reciprocal_div.o argv_split.o \
- proportions.o prio_heap.o ratelimit.o show_mem.o is_single_threaded.o
+ proportions.o prio_heap.o ratelimit.o show_mem.o is_single_threaded.o \
+ uaccess.o
lib-$(CONFIG_MMU) += ioremap.o
lib-$(CONFIG_SMP) += cpumask.o
diff --git a/lib/uaccess.c b/lib/uaccess.c
new file mode 100644
index 0000000..ac40796
--- /dev/null
+++ b/lib/uaccess.c
@@ -0,0 +1,55 @@
+/*
+ * Access kernel memory without faulting.
+ */
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+
+/**
+ * probe_kernel_read(): safely attempt to read from a location
+ * @dst: pointer to the buffer that shall take the data
+ * @src: address to read from
+ * @size: size of the data chunk
+ *
+ * Safely read from address @src to the buffer at @dst. If a kernel fault
+ * happens, handle that and return -EFAULT.
+ */
+long probe_kernel_read(void *dst, void *src, size_t size)
+{
+ long ret;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ pagefault_disable();
+ ret = __copy_from_user_inatomic(dst,
+ (__force const void __user *)src, size);
+ pagefault_enable();
+ set_fs(old_fs);
+
+ return ret ? -EFAULT : 0;
+}
+EXPORT_SYMBOL_GPL(probe_kernel_read);
+
+/**
+ * probe_kernel_write(): safely attempt to write to a location
+ * @dst: address to write to
+ * @src: pointer to the data that shall be written
+ * @size: size of the data chunk
+ *
+ * Safely write to address @dst from the buffer at @src. If a kernel fault
+ * happens, handle that and return -EFAULT.
+ */
+long probe_kernel_write(void *dst, void *src, size_t size)
+{
+ long ret;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ pagefault_disable();
+ ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
+ pagefault_enable();
+ set_fs(old_fs);
+
+ return ret ? -EFAULT : 0;
+}
+EXPORT_SYMBOL_GPL(probe_kernel_write);
diff --git a/mm/Makefile b/mm/Makefile
index 72255be..90323d1 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -8,7 +8,7 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \
vmalloc.o
obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
- maccess.o page_alloc.o page-writeback.o pdflush.o \
+ page_alloc.o page-writeback.o pdflush.o \
readahead.o swap.o truncate.o vmscan.o shmem.o \
prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
page_isolation.o mm_init.o $(mmu-y)
diff --git a/mm/maccess.c b/mm/maccess.c
deleted file mode 100644
index ac40796..0000000
--- a/mm/maccess.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Access kernel memory without faulting.
- */
-#include <linux/uaccess.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-
-/**
- * probe_kernel_read(): safely attempt to read from a location
- * @dst: pointer to the buffer that shall take the data
- * @src: address to read from
- * @size: size of the data chunk
- *
- * Safely read from address @src to the buffer at @dst. If a kernel fault
- * happens, handle that and return -EFAULT.
- */
-long probe_kernel_read(void *dst, void *src, size_t size)
-{
- long ret;
- mm_segment_t old_fs = get_fs();
-
- set_fs(KERNEL_DS);
- pagefault_disable();
- ret = __copy_from_user_inatomic(dst,
- (__force const void __user *)src, size);
- pagefault_enable();
- set_fs(old_fs);
-
- return ret ? -EFAULT : 0;
-}
-EXPORT_SYMBOL_GPL(probe_kernel_read);
-
-/**
- * probe_kernel_write(): safely attempt to write to a location
- * @dst: address to write to
- * @src: pointer to the data that shall be written
- * @size: size of the data chunk
- *
- * Safely write to address @dst from the buffer at @src. If a kernel fault
- * happens, handle that and return -EFAULT.
- */
-long probe_kernel_write(void *dst, void *src, size_t size)
-{
- long ret;
- mm_segment_t old_fs = get_fs();
-
- set_fs(KERNEL_DS);
- pagefault_disable();
- ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
- pagefault_enable();
- set_fs(old_fs);
-
- return ret ? -EFAULT : 0;
-}
-EXPORT_SYMBOL_GPL(probe_kernel_write);
--
1.5.6.5
--
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v3 2/6] string: add strtok_r to kernel
2009-02-26 18:54 [PATCH v3 0/6] [RFC] copy_strtok_from_user Steven Rostedt
2009-02-26 18:54 ` [PATCH v3 1/6] uaccess: move probe_kernel_* functions to lib/uaccess.c Steven Rostedt
@ 2009-02-26 18:54 ` Steven Rostedt
2009-02-26 18:54 ` [PATCH v3 3/6] uaccess: add copy_strtok_from_user Steven Rostedt
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2009-02-26 18:54 UTC (permalink / raw)
To: linux-kernel
Cc: Ingo Molnar, Andrew Morton, Peter Zijlstra, Frederic Weisbecker,
H. Peter Anvin, Steven Rostedt
[-- Attachment #1: 0002-string-add-strtok_r-to-kernel.patch --]
[-- Type: text/plain, Size: 2491 bytes --]
From: Steven Rostedt <srostedt@redhat.com>
This patch adds the function strtok_r to the kernel. This acts just like
the strtok_r that is implemented in glibc, but trimmed down.
Note, this is strtok_r and not strtok. The _r version is reentrant,
where as strtok is not, and thus not suitable for the kernel.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
include/linux/string.h | 3 +++
lib/string.c | 43 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/include/linux/string.h b/include/linux/string.h
index d18fc19..c5973a5 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -76,6 +76,9 @@ extern char * strpbrk(const char *,const char *);
#ifndef __HAVE_ARCH_STRSEP
extern char * strsep(char **,const char *);
#endif
+#ifndef __HAVE_ARCH_STRTOK_R
+extern char *strtok_r(char *, const char *, char **);
+#endif
#ifndef __HAVE_ARCH_STRSPN
extern __kernel_size_t strspn(const char *,const char *);
#endif
diff --git a/lib/string.c b/lib/string.c
index b19b87a..04461b0 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -493,6 +493,49 @@ char *strsep(char **s, const char *ct)
EXPORT_SYMBOL(strsep);
#endif
+#ifndef __HAVE_ARCH_STRTOK_R
+/**
+ * strtok_r - extract tokens from strings
+ * @s: The string to be searched
+ * @ct: The characters to deliminate the tokens
+ * @saveptr: The pointer to the next token
+ *
+ * It returns the next token found outside of the @ct delimiters.
+ * Multiple occurrences of @ct characters will be considered
+ * a single delimiter. In other words, the returned token will
+ * always have a size greater than 0 (or NULL if no token found).
+ *
+ * A '\0' is placed at the end of the found token, and
+ * @saveptr is updated to point to the location after that.
+ */
+char *strtok_r(char *s, const char *ct, char **saveptr)
+{
+ char *ret;
+ int skip;
+
+ if (!s)
+ return NULL;
+
+ /* Find start of first token */
+ skip = strspn(s, ct);
+ *saveptr = s + skip;
+
+ /* return NULL if we found no token */
+ if (!*saveptr[0])
+ return NULL;
+
+ /*
+ * strsep is different than strtok, where as saveptr will be NULL
+ * if token not found. strtok makes it point to the end of the string.
+ */
+ ret = strsep(saveptr, ct);
+ if (!*saveptr)
+ *saveptr = &ret[strlen(ret)];
+ return ret;
+}
+EXPORT_SYMBOL(strtok_r);
+#endif
+
/**
* sysfs_streq - return true if strings are equal, modulo trailing newline
* @s1: one string
--
1.5.6.5
--
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v3 3/6] uaccess: add copy_strtok_from_user
2009-02-26 18:54 [PATCH v3 0/6] [RFC] copy_strtok_from_user Steven Rostedt
2009-02-26 18:54 ` [PATCH v3 1/6] uaccess: move probe_kernel_* functions to lib/uaccess.c Steven Rostedt
2009-02-26 18:54 ` [PATCH v3 2/6] string: add strtok_r to kernel Steven Rostedt
@ 2009-02-26 18:54 ` Steven Rostedt
2009-02-26 18:54 ` [PATCH v3 4/6] tracing: convert event_trace to use copy_strtok_from_user Steven Rostedt
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2009-02-26 18:54 UTC (permalink / raw)
To: linux-kernel
Cc: Ingo Molnar, Andrew Morton, Peter Zijlstra, Frederic Weisbecker,
H. Peter Anvin, Steven Rostedt
[-- Attachment #1: 0003-uaccess-add-copy_strtok_from_user.patch --]
[-- Type: text/plain, Size: 6289 bytes --]
From: Steven Rostedt <srostedt@redhat.com>
The ftrace utility reads delimited tokens from user space.
Andrew Morton did not like how ftrace open coded this. He had
a good point since more than one location performed this feature.
This patch creates a copy_strtok_from_user function that can copy
a delimited token from user space. This puts the code in the
lib/uaccess.c file. This keeps the code in a single location
and may be optimized in the future.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
include/linux/uaccess.h | 4 +
lib/uaccess.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 155 insertions(+), 1 deletions(-)
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 6b58367..0a3faf5 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -106,4 +106,8 @@ extern long probe_kernel_read(void *dst, void *src, size_t size);
*/
extern long probe_kernel_write(void *dst, void *src, size_t size);
+extern int copy_strtok_from_user(void *to, const void __user *from,
+ unsigned int copy, unsigned int read,
+ unsigned int *copied, const char *delim);
+
#endif /* __LINUX_UACCESS_H__ */
diff --git a/lib/uaccess.c b/lib/uaccess.c
index ac40796..a55db23 100644
--- a/lib/uaccess.c
+++ b/lib/uaccess.c
@@ -1,8 +1,19 @@
/*
- * Access kernel memory without faulting.
+ * lib/uaccess.c
+ * Generic memory access without faulting.
+ *
+ * Copyright (C) 2008 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * Added copy_strtok_from_user -
+ * Copyright (C) 2009 Red Hat, Inc., Steven Rostedt <srostedt@redhat.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ *
*/
#include <linux/uaccess.h>
#include <linux/module.h>
+#include <linux/ctype.h>
#include <linux/mm.h>
/**
@@ -53,3 +64,142 @@ long probe_kernel_write(void *dst, void *src, size_t size)
return ret ? -EFAULT : 0;
}
EXPORT_SYMBOL_GPL(probe_kernel_write);
+
+#define USER_BUF_SIZE 127
+
+/**
+ * copy_strtok_from_user - copy a delimited token from user space
+ * @to: The location to copy to
+ * @from: The location to copy from
+ * @copy: The number of bytes to copy
+ * @read: The number of bytes to read
+ * @copied: The number of bytes actually written to @to
+ * @delim: NULL terminated string of character delimiters
+ *
+ * This reads from a user buffer, a delimited token.
+ * It places the token into @to if one is found, up to the number of
+ * bytes specified by @copy. It adds a "\0" terminating character
+ * into @to if a delimiter is found after the token. Otherwise the
+ * @to does not end with a \0 delimiter.
+ * If only delimiters are found, @to is not modified and
+ * @copied will be zero.
+ *
+ * It reads at most @read bytes from the user @from buffer, and
+ * will copy at most @copy bytes into the kernel @to buffer.
+ *
+ * Example of use:
+ *
+ * in user space a write(fd, "foo bar zot", 12) is done. We want to
+ * read three words.
+ *
+ * len = 12; - length of user buffer
+ * ret = copy_strtok_from_user(buf, ubuf, 100, len, @copied, " ");
+ * ret will equal 3 ("foo" read - " " is also read but not counted.)
+ * buf will contain "foo\0"
+ * copied will equal 4 ("foo\0" written)
+ *
+ * len -= ret; - 3 bytes was read
+ * read = ret;
+ * ret = copy_strtok_from_user(buf, ubuf+read, 100, len, @copied, " ");
+ * ret will equal 5 (" bar" read, notice the double space between
+ * foo and bar in the original write.)
+ * buf will contain "bar\0"
+ * copied will equal 4 ("bar\0" written)
+ *
+ * len -= ret; - 5 bytes read
+ * read += ret;
+ * ret = copy_strtok_from_user(buf, ubuf+read, 100, len, @copied, " ");
+ * ret = 4 (" zot" read)
+ * buf will contain "zot" (notice that it does not contain \0)
+ * copied will equal 3 ("zot" written)
+ * The buf only has "zot" because no terminating delimiter was
+ * encountered.
+ *
+ * Returns:
+ * The number of bytes read from user space (@from). This may or may not
+ * be the same as what was copied into @to.
+ *
+ * if (@to[*@copied - 1] == '\0')
+ * token ended with a delimiter
+ * else
+ * token in @from was not followed by a delimiter
+ *
+ * @copied will contain the number of bytes written into @to.
+ *
+ * Note, if the token that was found was bigger than @to,
+ * @copied will equal copy, and @to[*@copied - 1] will not be '\0'
+ *
+ * -EFAULT, if we faulted during any part of the copy.
+ * @copied will be undefined.
+ */
+int copy_strtok_from_user(void *to, const void __user *from,
+ unsigned int copy, unsigned int read,
+ unsigned int *copied, const char *delim)
+{
+ unsigned int have_read = 0;
+ unsigned int have_copied = 0;
+ char user[USER_BUF_SIZE + 1];
+ char *token, *ptr;
+ int ret, cnt;
+
+ do {
+ cnt = USER_BUF_SIZE;
+
+ if (cnt > read - have_read)
+ cnt = read - have_read;
+
+ ret = copy_from_user(user, from + have_read, cnt);
+ if (ret)
+ return ret;
+
+ user[cnt] = 0;
+ ptr = user;
+ have_read += cnt;
+
+ token = strtok_r(ptr, delim, &ptr);
+ if (token) {
+ strncpy(to + have_copied, token, copy - have_copied);
+ have_copied += strlen(token);
+
+ /*
+ * We do not want to report that we read past the
+ * token.
+ */
+ have_read -= cnt - (ptr - user);
+
+ /*
+ * Check if the token was larger than the supplied
+ * buffer.
+ */
+ if (have_copied >= copy) {
+ /* do not report the part not copied */
+ have_read -= have_copied - copy;
+ /* account for the delim read by ptr */
+ if (ptr[-1] == '\0')
+ have_read--;
+ have_copied = copy;
+ break;
+ }
+
+ /*
+ * Now the tricky part. We must determine if the token
+ * was split between two reads from userspace.
+ * If strtok_r found a delimiter after the token, then
+ * the previous character to ptr would be NULL.
+ * Note: if strtok_r returned a token, ptr must be
+ * greater than user.
+ */
+ if (!ptr[-1]) {
+ /* add '\0' */
+ have_copied++;
+ break;
+ }
+ }
+
+ } while (have_read < read && have_copied < copy);
+
+ *copied = have_copied;
+
+ return have_read;
+}
+EXPORT_SYMBOL_GPL(copy_strtok_from_user);
--
1.5.6.5
--
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v3 4/6] tracing: convert event_trace to use copy_strtok_from_user
2009-02-26 18:54 [PATCH v3 0/6] [RFC] copy_strtok_from_user Steven Rostedt
` (2 preceding siblings ...)
2009-02-26 18:54 ` [PATCH v3 3/6] uaccess: add copy_strtok_from_user Steven Rostedt
@ 2009-02-26 18:54 ` Steven Rostedt
2009-02-26 18:54 ` [PATCH v3 5/6] tracing: convert ftrace_regex_write " Steven Rostedt
2009-02-26 18:54 ` [PATCH v3 6/6] tracing: convert ftrace_graph_write " Steven Rostedt
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2009-02-26 18:54 UTC (permalink / raw)
To: linux-kernel
Cc: Ingo Molnar, Andrew Morton, Peter Zijlstra, Frederic Weisbecker,
H. Peter Anvin, Steven Rostedt
[-- Attachment #1: 0004-tracing-convert-event_trace-to-use-copy_strtok_from.patch --]
[-- Type: text/plain, Size: 2658 bytes --]
From: Steven Rostedt <srostedt@redhat.com>
Impact: clean up
This patch converts the open coded retrieving of a word from user
space to use copy_strtok_from_user.
Also removed a cnt < 0 check that Andrew Morton pointed out saying
that it was irrelevant since cnt is unsigned.
Also changed file->pos += to (*ppos) += which is the proper way
to modify positions of the file.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
kernel/trace/trace.h | 2 +
kernel/trace/trace_events.c | 69 +++++++++++++++---------------------------
2 files changed, 27 insertions(+), 44 deletions(-)
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 6321917..e75b673 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -720,4 +720,6 @@ static inline void trace_branch_disable(void)
}
#endif /* CONFIG_BRANCH_TRACER */
+#define SPACES " \t\r\n"
+
#endif /* _LINUX_KERNEL_TRACE_H */
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 3bcb9df..9e71755 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -80,62 +80,43 @@ static ssize_t
ftrace_event_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{
- size_t read = 0;
- int i, set = 1;
+ unsigned int copied;
+ size_t read;
ssize_t ret;
+ int set = 1;
char *buf;
- char ch;
- if (!cnt || cnt < 0)
+ if (!cnt)
return 0;
- ret = get_user(ch, ubuf++);
- if (ret)
- return ret;
- read++;
- cnt--;
-
- /* skip white space */
- while (cnt && isspace(ch)) {
- ret = get_user(ch, ubuf++);
- if (ret)
- return ret;
- read++;
- cnt--;
- }
-
- /* Only white space found? */
- if (isspace(ch)) {
- file->f_pos += read;
- ret = read;
- return ret;
- }
-
buf = kmalloc(EVENT_BUF_SIZE+1, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- if (cnt > EVENT_BUF_SIZE)
- cnt = EVENT_BUF_SIZE;
-
- i = 0;
- while (cnt && !isspace(ch)) {
- if (!i && ch == '!')
- set = 0;
- else
- buf[i++] = ch;
-
- ret = get_user(ch, ubuf++);
- if (ret)
- goto out_free;
- read++;
- cnt--;
+ ret = copy_strtok_from_user(buf, ubuf, EVENT_BUF_SIZE,
+ cnt, &copied, SPACES);
+ if (ret < 0)
+ goto out_free;
+
+ if (!copied) {
+ ret = cnt;
+ (*ppos) += cnt;
+
+ /* TODO, handle split words */
+ goto out_free;
}
- buf[i] = 0;
- file->f_pos += read;
+ if (buf[0] == '!')
+ set = 0;
+
+ (*ppos) += ret;
+ read = ret;
- ret = ftrace_set_clr_event(buf, set);
+ /*
+ * A little hack here. If set is true, we want to use buf.
+ * Otherwise, we want to use buf+1 (to skip the '!').
+ */
+ ret = ftrace_set_clr_event(buf + !set, set);
if (ret)
goto out_free;
--
1.5.6.5
--
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v3 5/6] tracing: convert ftrace_regex_write to use copy_strtok_from_user
2009-02-26 18:54 [PATCH v3 0/6] [RFC] copy_strtok_from_user Steven Rostedt
` (3 preceding siblings ...)
2009-02-26 18:54 ` [PATCH v3 4/6] tracing: convert event_trace to use copy_strtok_from_user Steven Rostedt
@ 2009-02-26 18:54 ` Steven Rostedt
2009-02-26 18:54 ` [PATCH v3 6/6] tracing: convert ftrace_graph_write " Steven Rostedt
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2009-02-26 18:54 UTC (permalink / raw)
To: linux-kernel
Cc: Ingo Molnar, Andrew Morton, Peter Zijlstra, Frederic Weisbecker,
H. Peter Anvin, Steven Rostedt
[-- Attachment #1: 0005-tracing-convert-ftrace_regex_write-to-use-copy_strt.patch --]
[-- Type: text/plain, Size: 3496 bytes --]
From: Steven Rostedt <srostedt@redhat.com>
Impact: clean up
This removes the open coded parsing of a word sent in by the user
and replaces it with copy_strtok_from_user.
Also removes cnt < 0 check since cnt is unsigned.
Also uses (*ppos) += cnt, instead of file->pos += cnt.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
kernel/trace/ftrace.c | 101 +++++++++++++++++++++++++++++--------------------
1 files changed, 60 insertions(+), 41 deletions(-)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 5a3a06b..963dc14 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1690,11 +1690,13 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos, int enable)
{
struct ftrace_iterator *iter;
- char ch;
+ unsigned int copied;
size_t read = 0;
+ int len, skip;
ssize_t ret;
+ char *buf;
- if (!cnt || cnt < 0)
+ if (!cnt)
return 0;
mutex_lock(&ftrace_regex_lock);
@@ -1710,58 +1712,75 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
iter->buffer_idx = 0;
}
- ret = get_user(ch, ubuf++);
- if (ret)
- goto out;
- read++;
- cnt--;
+ if (iter->flags & FTRACE_ITER_CONT) {
+ /*
+ * We split on a word, continue from where
+ * we left off.
+ */
+ buf = &iter->buffer[iter->buffer_idx];
+ len = FTRACE_BUFF_MAX - iter->buffer_idx;
+ /* do not handle leading spaces. */
+ skip = 0;
+ } else {
+ buf = iter->buffer;
+ /* iter->buffer is size of FTRACE_BUFF_MAX + 1 */
+ len = FTRACE_BUFF_MAX;
+ iter->buffer_idx = 0;
+ /* Skip over any leading spaces */
+ skip = 1;
+ }
- if (!(iter->flags & ~FTRACE_ITER_CONT)) {
- /* skip white space */
- while (cnt && isspace(ch)) {
- ret = get_user(ch, ubuf++);
- if (ret)
- goto out;
- read++;
- cnt--;
- }
+ ret = copy_strtok_from_user(buf, ubuf, len, cnt, &copied, SPACES);
+ if (ret < 0)
+ goto out;
- if (isspace(ch)) {
- file->f_pos += read;
- ret = read;
- goto out;
+ if (!skip) {
+ /*
+ * This is a continuation. If we read spaces, then
+ * we need to truncate all that was read.
+ */
+ if (ret > copied) {
+ /* leading spaces were found */
+ iter->buffer[iter->buffer_idx] = 0;
+ /* make it look like we are ready to process */
+ buf = iter->buffer;
+ copied = iter->buffer_idx + 1;
}
+ }
- iter->buffer_idx = 0;
+ /* We only read white space. */
+ if (!copied) {
+ (*ppos) += cnt;
+ ret = cnt;
+ goto out;
}
- while (cnt && !isspace(ch)) {
- if (iter->buffer_idx < FTRACE_BUFF_MAX)
- iter->buffer[iter->buffer_idx++] = ch;
- else {
+ /* Check if we hit a terminating space */
+ if (buf[copied - 1] != 0) {
+ /* we split on a word */
+ iter->buffer_idx += copied;
+ if (iter->buffer_idx >= FTRACE_BUFF_MAX) {
+ /* too big of a word */
+ iter->buffer_idx = 0;
+ iter->flags &= ~FTRACE_ITER_CONT;
ret = -EINVAL;
goto out;
}
- ret = get_user(ch, ubuf++);
- if (ret)
- goto out;
- read++;
- cnt--;
- }
- if (isspace(ch)) {
- iter->filtered++;
- iter->buffer[iter->buffer_idx] = 0;
- ret = ftrace_process_regex(iter->buffer,
- iter->buffer_idx, enable);
- if (ret)
- goto out;
- iter->buffer_idx = 0;
- } else
+ (*ppos) += cnt;
+ ret = cnt;
iter->flags |= FTRACE_ITER_CONT;
+ goto out;
+ }
+ read = ret;
- file->f_pos += read;
+ ret = ftrace_process_regex(iter->buffer, iter->buffer_idx, enable);
+ if (ret)
+ goto out;
+ iter->buffer_idx = 0;
+
+ (*ppos) += read;
ret = read;
out:
--
1.5.6.5
--
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v3 6/6] tracing: convert ftrace_graph_write to use copy_strtok_from_user
2009-02-26 18:54 [PATCH v3 0/6] [RFC] copy_strtok_from_user Steven Rostedt
` (4 preceding siblings ...)
2009-02-26 18:54 ` [PATCH v3 5/6] tracing: convert ftrace_regex_write " Steven Rostedt
@ 2009-02-26 18:54 ` Steven Rostedt
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2009-02-26 18:54 UTC (permalink / raw)
To: linux-kernel
Cc: Ingo Molnar, Andrew Morton, Peter Zijlstra, Frederic Weisbecker,
H. Peter Anvin, Steven Rostedt
[-- Attachment #1: 0006-tracing-convert-ftrace_graph_write-to-use-copy_strt.patch --]
[-- Type: text/plain, Size: 2117 bytes --]
From: Steven Rostedt <srostedt@redhat.com>
Impact: clean up
This removes the open coded parsing of a word sent in by the user
and replaces it with copy_strtok_from_user.
Also removes cnt < 0 check since cnt is unsigned.
Also uses (*ppos) += cnt, instead of file->pos += cnt.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
kernel/trace/ftrace.c | 48 ++++++++++++++++--------------------------------
1 files changed, 16 insertions(+), 32 deletions(-)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 963dc14..4ed0a8e 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -2083,10 +2083,9 @@ ftrace_graph_write(struct file *file, const char __user *ubuf,
unsigned long *array;
size_t read = 0;
ssize_t ret;
- int index = 0;
- char ch;
+ int copied;
- if (!cnt || cnt < 0)
+ if (!cnt)
return 0;
mutex_lock(&graph_lock);
@@ -2102,48 +2101,33 @@ ftrace_graph_write(struct file *file, const char __user *ubuf,
} else
array = file->private_data;
- ret = get_user(ch, ubuf++);
- if (ret)
+ ret = copy_strtok_from_user(buffer, ubuf, FTRACE_BUFF_MAX + 1,
+ cnt, &copied, SPACES);
+ if (ret < 0)
goto out;
- read++;
- cnt--;
- /* skip white space */
- while (cnt && isspace(ch)) {
- ret = get_user(ch, ubuf++);
- if (ret)
- goto out;
- read++;
- cnt--;
+ /* We only read white space. */
+ if (!copied) {
+ (*ppos) += cnt;
+ ret = cnt;
+ goto out;
}
- if (isspace(ch)) {
- *ppos += read;
- ret = read;
+ /* Check if we hit a terminating space */
+ if (buffer[copied - 1] != 0) {
+ /* This does not deal with split words */
+ ret = -EINVAL;
goto out;
}
- while (cnt && !isspace(ch)) {
- if (index < FTRACE_BUFF_MAX)
- buffer[index++] = ch;
- else {
- ret = -EINVAL;
- goto out;
- }
- ret = get_user(ch, ubuf++);
- if (ret)
- goto out;
- read++;
- cnt--;
- }
- buffer[index] = 0;
+ read = ret;
/* we allow only one expression at a time */
ret = ftrace_set_func(array, &ftrace_graph_count, buffer);
if (ret)
goto out;
- file->f_pos += read;
+ (*ppos) += read;
ret = read;
out:
--
1.5.6.5
--
^ permalink raw reply related [flat|nested] 7+ messages in thread