__strcpy_chk.S revision 32bbf8a63bb43a540cc0f1dd5037736d10b70e0b
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *  * Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in
12 *    the documentation and/or other materials provided with the
13 *    distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <machine/asm.h>
30#include "libc_events.h"
31
32    .syntax unified
33    .fpu    neon
34    .thumb
35    .thumb_func
36
37// Get the length of the source string first, then do a memcpy of the data
38// instead of a strcpy.
39ENTRY(__strcpy_chk)
40    .cfi_startproc
41    pld     [r0, #0]
42    push    {r0, lr}
43    .save   {r0, lr}
44    .cfi_def_cfa_offset 8
45    .cfi_rel_offset r0, 0
46    .cfi_rel_offset lr, 4
47
48    mov     lr, r2
49    mov     r0, r1
50
51    ands    r3, r0, #7
52    bne     .L_align_src
53
54    .p2align 2
55.L_mainloop:
56    ldmia   r0!, {r2, r3}
57
58    pld     [r0, #64]
59
60    sub     ip, r2, #0x01010101
61    bic     ip, ip, r2
62    ands    ip, ip, #0x80808080
63    bne     .L_zero_in_first_register
64
65    sub     ip, r3, #0x01010101
66    bic     ip, ip, r3
67    ands    ip, ip, #0x80808080
68    bne     .L_zero_in_second_register
69    b       .L_mainloop
70
71.L_zero_in_first_register:
72    sub     r3, r0, r1
73    // Check for zero in byte 0.
74    lsls    r2, ip, #17
75    beq     .L_check_byte1_reg1
76
77    sub     r3, r3, #8
78    b       .L_check_size
79
80.L_check_byte1_reg1:
81    bcc     .L_check_byte2_reg1
82
83    sub     r3, r3, #7
84    b       .L_check_size
85
86.L_check_byte2_reg1:
87    // Check for zero in byte 2.
88    tst     ip, #0x800000
89    it      ne
90    subne   r3, r3, #6
91    bne     .L_check_size
92    sub     r3, r3, #5
93    b       .L_check_size
94
95.L_zero_in_second_register:
96    sub     r3, r0, r1
97    // Check for zero in byte 0.
98    lsls    r2, ip, #17
99    beq     .L_check_byte1_reg2
100
101    sub     r3, r3, #4
102    b       .L_check_size
103
104.L_check_byte1_reg2:
105    bcc     .L_check_byte2_reg2
106
107    sub     r3, r3, #3
108    b       .L_check_size
109
110.L_check_byte2_reg2:
111    // Check for zero in byte 2.
112    tst     ip, #0x800000
113    it      ne
114    subne   r3, r3, #2
115    bne     .L_check_size
116    sub     r3, r3, #1
117    b       .L_check_size
118
119.L_align_src:
120    // Align to a double word (64 bits).
121    rsb     r3, r3, #8
122    lsls    ip, r3, #31
123    beq     .L_align_to_32
124
125    ldrb    r2, [r0], #1
126    cbz     r2, .L_done
127
128.L_align_to_32:
129    bcc     .L_align_to_64
130
131    ldrb    r2, [r0], #1
132    cbz     r2, .L_done
133    ldrb    r2, [r0], #1
134    cbz     r2, .L_done
135
136.L_align_to_64:
137    tst     r3, #4
138    beq     .L_mainloop
139    ldr     r2, [r0], #4
140
141    sub     ip, r2, #0x01010101
142    bic     ip, ip, r2
143    ands    ip, ip, #0x80808080
144    bne     .L_zero_in_second_register
145    b       .L_mainloop
146
147.L_done:
148    sub     r3, r0, r1
149    sub     r3, r3, #1
150
151.L_check_size:
152    pld     [r1, #0]
153    pld     [r1, #64]
154    ldr     r0, [sp]
155    cmp     r3, lr
156    bhs     __strcpy_chk_fail
157
158    // Add 1 for copy length to get the string terminator.
159    add     r2, r3, #1
160
161    .cfi_endproc
162
163    // Fall through into the memcpy_base function.
164END(__strcpy_chk)
165
166#define MEMCPY_BASE         __strcpy_chk_memcpy_base
167#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
168#include "memcpy_base.S"
169
170ENTRY_PRIVATE(__strcpy_chk_fail)
171    .cfi_startproc
172
173    .save   {r0, lr}
174    .cfi_def_cfa_offset 8
175    .cfi_rel_offset r0, 0
176    .cfi_rel_offset lr, 4
177
178    ldr     r0, error_message
179    ldr     r1, error_code
1801:
181    add     r0, pc
182    bl      __fortify_chk_fail
183
184error_code:
185    .word   BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
186error_message:
187    .word   error_string-(1b+4)
188
189    .cfi_endproc
190END(__strcpy_chk_fail)
191
192    .data
193error_string:
194    .string "strcpy buffer overflow"
195