1/* uaccess.c: userspace access functions 2 * 3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12#include <linux/mm.h> 13#include <linux/module.h> 14#include <asm/uaccess.h> 15 16/*****************************************************************************/ 17/* 18 * copy a null terminated string from userspace 19 */ 20long strncpy_from_user(char *dst, const char __user *src, long count) 21{ 22 unsigned long max; 23 char *p, ch; 24 long err = -EFAULT; 25 26 BUG_ON(count < 0); 27 28 p = dst; 29 30#ifndef CONFIG_MMU 31 if ((unsigned long) src < memory_start) 32 goto error; 33#endif 34 35 if ((unsigned long) src >= get_addr_limit()) 36 goto error; 37 38 max = get_addr_limit() - (unsigned long) src; 39 if ((unsigned long) count > max) { 40 memset(dst + max, 0, count - max); 41 count = max; 42 } 43 44 err = 0; 45 for (; count > 0; count--, p++, src++) { 46 __get_user_asm(err, ch, src, "ub", "=r"); 47 if (err < 0) 48 goto error; 49 if (!ch) 50 break; 51 *p = ch; 52 } 53 54 err = p - dst; /* return length excluding NUL */ 55 56 error: 57 if (count > 0) 58 memset(p, 0, count); /* clear remainder of buffer [security] */ 59 60 return err; 61 62} /* end strncpy_from_user() */ 63 64EXPORT_SYMBOL(strncpy_from_user); 65 66/*****************************************************************************/ 67/* 68 * Return the size of a string (including the ending 0) 69 * 70 * Return 0 on exception, a value greater than N if too long 71 */ 72long strnlen_user(const char __user *src, long count) 73{ 74 const char __user *p; 75 long err = 0; 76 char ch; 77 78 BUG_ON(count < 0); 79 80#ifndef CONFIG_MMU 81 if ((unsigned long) src < memory_start) 82 return 0; 83#endif 84 85 if ((unsigned long) src >= get_addr_limit()) 86 return 0; 87 88 for (p = src; count > 0; count--, p++) { 89 __get_user_asm(err, ch, p, "ub", "=r"); 90 if (err < 0) 91 return 0; 92 if (!ch) 93 break; 94 } 95 96 return p - src + 1; /* return length including NUL */ 97 98} /* end strnlen_user() */ 99 100EXPORT_SYMBOL(strnlen_user); 101