/* uaccess.c: userspace access functions1*2* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.3* Written by David Howells ([email protected])4*5* This program is free software; you can redistribute it and/or6* modify it under the terms of the GNU General Public License7* as published by the Free Software Foundation; either version8* 2 of the License, or (at your option) any later version.9*/1011#include <linux/mm.h>12#include <linux/module.h>13#include <asm/uaccess.h>1415/*****************************************************************************/16/*17* copy a null terminated string from userspace18*/19long strncpy_from_user(char *dst, const char __user *src, long count)20{21unsigned long max;22char *p, ch;23long err = -EFAULT;2425BUG_ON(count < 0);2627p = dst;2829#ifndef CONFIG_MMU30if ((unsigned long) src < memory_start)31goto error;32#endif3334if ((unsigned long) src >= get_addr_limit())35goto error;3637max = get_addr_limit() - (unsigned long) src;38if ((unsigned long) count > max) {39memset(dst + max, 0, count - max);40count = max;41}4243err = 0;44for (; count > 0; count--, p++, src++) {45__get_user_asm(err, ch, src, "ub", "=r");46if (err < 0)47goto error;48if (!ch)49break;50*p = ch;51}5253err = p - dst; /* return length excluding NUL */5455error:56if (count > 0)57memset(p, 0, count); /* clear remainder of buffer [security] */5859return err;6061} /* end strncpy_from_user() */6263EXPORT_SYMBOL(strncpy_from_user);6465/*****************************************************************************/66/*67* Return the size of a string (including the ending 0)68*69* Return 0 on exception, a value greater than N if too long70*/71long strnlen_user(const char __user *src, long count)72{73const char __user *p;74long err = 0;75char ch;7677BUG_ON(count < 0);7879#ifndef CONFIG_MMU80if ((unsigned long) src < memory_start)81return 0;82#endif8384if ((unsigned long) src >= get_addr_limit())85return 0;8687for (p = src; count > 0; count--, p++) {88__get_user_asm(err, ch, p, "ub", "=r");89if (err < 0)90return 0;91if (!ch)92break;93}9495return p - src + 1; /* return length including NUL */9697} /* end strnlen_user() */9899EXPORT_SYMBOL(strnlen_user);100101102