]> sourceware.org Git - systemtap.git/blame - runtime/linux/copy.c
update copyrights
[systemtap.git] / runtime / linux / copy.c
CommitLineData
2466bf70
JS
1/* -*- linux-c -*-
2 * Copy from user space functions
ef36f781 3 * Copyright (C) 2005-2014 Red Hat Inc.
2466bf70
JS
4 * Copyright (C) 2005 Intel Corporation.
5 *
6 * This file is part of systemtap, and is free software. You can
7 * redistribute it and/or modify it under the terms of the GNU General
8 * Public License (GPL); either version 2, or (at your option) any
9 * later version.
10 */
11
12#ifndef _STAPLINUX_COPY_C_ /* -*- linux-c -*- */
13#define _STAPLINUX_COPY_C_
14
15/** @file copy.c
16 * @brief Functions to copy from user space.
17 */
18
19/** @addtogroup copy Functions to copy from user space.
20 * Functions to copy from user space.
21 * None of these functions will sleep (for example to allow pages
22 * to be swapped in). It is possible (although rare) that the data
23 * in user space will not present and these functions will return an error.
24 * @{
25 */
26
2466bf70
JS
27#ifdef CONFIG_GENERIC_STRNCPY_FROM_USER
28#define __stp_strncpy_from_user(dst,src,count,res) \
29 do { res = strncpy_from_user(dst, src, count); } while(0)
30#else /* !CONFIG_GENERIC_STRNCPY_FROM_USER */
31#if defined (__i386__)
32#define __stp_strncpy_from_user(dst,src,count,res) \
33do { \
34 int __d0, __d1, __d2; \
35 __asm__ __volatile__( \
36 " testl %1,%1\n" \
37 " jz 2f\n" \
38 "0: lodsb\n" \
39 " stosb\n" \
40 " testb %%al,%%al\n" \
41 " jz 1f\n" \
42 " decl %1\n" \
43 " jnz 0b\n" \
44 "1: subl %1,%0\n" \
45 "2:\n" \
46 ".section .fixup,\"ax\"\n" \
47 "3: movl %5,%0\n" \
48 " jmp 2b\n" \
49 ".previous\n" \
50 ".section __ex_table,\"a\"\n" \
51 " .align 4\n" \
52 " .long 0b,3b\n" \
53 ".previous" \
54 : "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \
55 "=&D" (__d2) \
56 : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
57 : "memory"); \
58} while (0)
59#elif defined (__x86_64__)
60#define __stp_strncpy_from_user(dst,src,count,res) \
61do { \
62 long __d0, __d1, __d2; \
63 __asm__ __volatile__( \
64 " testq %1,%1\n" \
65 " jz 2f\n" \
66 "0: lodsb\n" \
67 " stosb\n" \
68 " testb %%al,%%al\n" \
69 " jz 1f\n" \
70 " decq %1\n" \
71 " jnz 0b\n" \
72 "1: subq %1,%0\n" \
73 "2:\n" \
74 ".section .fixup,\"ax\"\n" \
75 "3: movq %5,%0\n" \
76 " jmp 2b\n" \
77 ".previous\n" \
78 ".section __ex_table,\"a\"\n" \
79 " .align 8\n" \
80 " .quad 0b,3b\n" \
81 ".previous" \
82 : "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \
83 "=&D" (__d2) \
84 : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
85 : "memory"); \
86} while (0)
87#elif defined (__powerpc__) || defined (__arm__)
88#define __stp_strncpy_from_user(dst,src,count,res) \
89 do { res = __strncpy_from_user(dst, src, count); } while(0)
90
930c64c1 91#elif defined (__s390__) || defined (__s390x__)|| defined (__aarch64__)
2466bf70
JS
92#define __stp_strncpy_from_user(dst,src,count,res) \
93 do { res = strncpy_from_user(dst, src, count); } while(0)
94#elif defined (__ia64__)
95#define __stp_strncpy_from_user(dst,src,count,res) \
b137ba9a 96 do { res = __strncpy_from_user(dst, src, count); } while(0)
2466bf70
JS
97#endif
98#endif /* !CONFIG_GENERIC_STRNCPY_FROM_USER */
99
b137ba9a 100
2466bf70
JS
101/** Copy a NULL-terminated string from userspace.
102 * On success, returns the length of the string (not including the trailing
103 * NULL).
104 *
105 * If access to userspace fails, returns -EFAULT (some data may have been
106 * copied).
107 * @param dst Destination address, in kernel space. This buffer must be at
108 * least <i>count</i> bytes long.
109 * @param src Source address, in user space.
110 * @param count Maximum number of bytes to copy, including the trailing NULL.
111 *
112 * If <i>count</i> is smaller than the length of the string, copies
113 * <i>count</i> bytes and returns <i>count</i>.
114 */
115
8fee9cc5 116/* XXX: see also kread/uread in loc2c-runtime.h */
2466bf70
JS
117static long _stp_strncpy_from_user(char *dst, const char __user *src, long count)
118{
119 long res = -EFAULT;
8fee9cc5
FCE
120 mm_segment_t _oldfs = get_fs();
121 set_fs(USER_DS);
122 pagefault_disable();
123 if (access_ok(VERIFY_READ, src, count)) /* XXX: bad_addr? */
2466bf70 124 __stp_strncpy_from_user(dst, src, count, res);
8fee9cc5
FCE
125 pagefault_enable();
126 set_fs(_oldfs);
2466bf70
JS
127 return res;
128}
129
130/** Copy a block of data from user space.
131 *
7d860223
DS
132 * If data could not be copied, this function will not modify the
133 * destination.
134 *
2466bf70
JS
135 * @param dst Destination address, in kernel space.
136 * @param src Source address, in user space.
137 * @param count Number of bytes to copy.
138 * @return number of bytes that could not be copied. On success,
139 * this will be zero.
140 *
141 */
142
b137ba9a 143/* XXX: see also kread/uread in loc2c-runtime.h */
2466bf70
JS
144static unsigned long _stp_copy_from_user(char *dst, const char __user *src, unsigned long count)
145{
146 if (count) {
b137ba9a
FCE
147 mm_segment_t _oldfs = get_fs();
148 set_fs(USER_DS);
149 pagefault_disable();
2466bf70
JS
150 if (access_ok(VERIFY_READ, src, count))
151 count = __copy_from_user_inatomic(dst, src, count);
152 else
7d860223
DS
153 /* Notice that if we fail, we don't modify
154 * the destination. In the failure case, we
155 * can't trust 'count' to be reasonable. */
156 count = -EFAULT;
b137ba9a
FCE
157 pagefault_enable();
158 set_fs(_oldfs);
2466bf70
JS
159 }
160 return count;
161}
162
163/** @} */
164#endif /* _STAPLINUX_COPY_C_ */
This page took 0.072578 seconds and 5 git commands to generate.