diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2015-08-05 17:04:01 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2015-08-05 17:04:01 -0300 |
commit | 57f0f512b273f60d52568b8c6b77e17f5636edc0 (patch) | |
tree | 5e910f0e82173f4ef4f51111366a3f1299037a7b /arch/frv/kernel/uaccess.c |
Initial import
Diffstat (limited to 'arch/frv/kernel/uaccess.c')
-rw-r--r-- | arch/frv/kernel/uaccess.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c new file mode 100644 index 000000000..374f88d6c --- /dev/null +++ b/arch/frv/kernel/uaccess.c @@ -0,0 +1,100 @@ +/* uaccess.c: userspace access functions + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/mm.h> +#include <linux/module.h> +#include <asm/uaccess.h> + +/*****************************************************************************/ +/* + * copy a null terminated string from userspace + */ +long strncpy_from_user(char *dst, const char __user *src, long count) +{ + unsigned long max; + char *p, ch; + long err = -EFAULT; + + BUG_ON(count < 0); + + p = dst; + +#ifndef CONFIG_MMU + if ((unsigned long) src < memory_start) + goto error; +#endif + + if ((unsigned long) src >= get_addr_limit()) + goto error; + + max = get_addr_limit() - (unsigned long) src; + if ((unsigned long) count > max) { + memset(dst + max, 0, count - max); + count = max; + } + + err = 0; + for (; count > 0; count--, p++, src++) { + __get_user_asm(err, ch, src, "ub", "=r"); + if (err < 0) + goto error; + if (!ch) + break; + *p = ch; + } + + err = p - dst; /* return length excluding NUL */ + + error: + if (count > 0) + memset(p, 0, count); /* clear remainder of buffer [security] */ + + return err; + +} /* end strncpy_from_user() */ + +EXPORT_SYMBOL(strncpy_from_user); + +/*****************************************************************************/ +/* + * Return the size of a string (including the ending 0) + * + * Return 0 on exception, a value greater than N if too long + */ +long strnlen_user(const char __user *src, long count) +{ + const char __user *p; + long err = 0; + char ch; + + BUG_ON(count < 0); + +#ifndef CONFIG_MMU + if ((unsigned long) src < memory_start) + return 0; +#endif + + if ((unsigned long) src >= get_addr_limit()) + return 0; + + for (p = src; count > 0; count--, p++) { + __get_user_asm(err, ch, p, "ub", "=r"); + if (err < 0) + return 0; + if (!ch) + break; + } + + return p - src + 1; /* return length including NUL */ + +} /* end strnlen_user() */ + +EXPORT_SYMBOL(strnlen_user); |