1//!
2//! Small Zig reimplementation of gcc's libssp.
3//!
4//! This library implements most of the builtins required by the stack smashing
5//! protection as implemented by gcc&clang.
6//! Missing exports:
7//! - __gets_chk
8//! - __mempcpy_chk
9//! - __snprintf_chk
10//! - __sprintf_chk
11//! - __stpcpy_chk
12//! - __vsnprintf_chk
13//! - __vsprintf_chk
14
15const std = @import("std");
16const compiler_rt = @import("../compiler_rt.zig");
17const symbol = compiler_rt.symbol;
18const builtin = @import("builtin");
19
20extern fn memset(dest: ?[*]u8, c: c_int, n: usize) callconv(.c) ?[*]u8;
21extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8;
22extern fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8;
23
24comptime {
25 @export(&__stack_chk_fail, .{ .name = if (builtin.os.tag == .openbsd) "__stack_smash_handler" else "__stack_chk_fail", .linkage = compiler_rt.linkage, .visibility = compiler_rt.visibility });
26 symbol(&__chk_fail, "__chk_fail");
27 symbol(&__stack_chk_guard, if (builtin.os.tag == .openbsd) "__guard_local" else "__stack_chk_guard");
28 symbol(&__strcpy_chk, "__strcpy_chk");
29 symbol(&__strncpy_chk, "__strncpy_chk");
30 symbol(&__strcat_chk, "__strcat_chk");
31 symbol(&__strncat_chk, "__strncat_chk");
32 symbol(&__memcpy_chk, "__memcpy_chk");
33 symbol(&__memmove_chk, "__memmove_chk");
34 symbol(&__memset_chk, "__memset_chk");
35}
36
37fn __stack_chk_fail() callconv(.c) noreturn {
38 @panic("stack smashing detected");
39}
40
41fn __chk_fail() callconv(.c) noreturn {
42 @panic("buffer overflow detected");
43}
44
45// TODO: Initialize the canary with random data
46var __stack_chk_guard: usize = blk: {
47 var buf: [@sizeOf(usize)]u8 = @splat(0);
48 buf[@sizeOf(usize) - 1] = 255;
49 buf[@sizeOf(usize) - 2] = '\n';
50 break :blk @bitCast(buf);
51};
52
53fn __strcpy_chk(dest: [*:0]u8, src: [*:0]const u8, dest_n: usize) callconv(.c) [*:0]u8 {
54 @setRuntimeSafety(false);
55
56 var i: usize = 0;
57 while (i < dest_n and src[i] != 0) : (i += 1) {
58 dest[i] = src[i];
59 }
60
61 if (i == dest_n) __chk_fail();
62
63 dest[i] = 0;
64
65 return dest;
66}
67
68fn __strncpy_chk(dest: [*:0]u8, src: [*:0]const u8, n: usize, dest_n: usize) callconv(.c) [*:0]u8 {
69 @setRuntimeSafety(false);
70 if (dest_n < n) __chk_fail();
71 var i: usize = 0;
72 while (i < n and src[i] != 0) : (i += 1) {
73 dest[i] = src[i];
74 }
75 while (i < n) : (i += 1) {
76 dest[i] = 0;
77 }
78 return dest;
79}
80
81fn __strcat_chk(dest: [*:0]u8, src: [*:0]const u8, dest_n: usize) callconv(.c) [*:0]u8 {
82 @setRuntimeSafety(false);
83
84 var avail = dest_n;
85
86 var dest_end: usize = 0;
87 while (avail > 0 and dest[dest_end] != 0) : (dest_end += 1) {
88 avail -= 1;
89 }
90
91 if (avail < 1) __chk_fail();
92
93 var i: usize = 0;
94 while (avail > 0 and src[i] != 0) : (i += 1) {
95 dest[dest_end + i] = src[i];
96 avail -= 1;
97 }
98
99 if (avail < 1) __chk_fail();
100
101 dest[dest_end + i] = 0;
102
103 return dest;
104}
105
106fn __strncat_chk(dest: [*:0]u8, src: [*:0]const u8, n: usize, dest_n: usize) callconv(.c) [*:0]u8 {
107 @setRuntimeSafety(false);
108
109 var avail = dest_n;
110
111 var dest_end: usize = 0;
112 while (avail > 0 and dest[dest_end] != 0) : (dest_end += 1) {
113 avail -= 1;
114 }
115
116 if (avail < 1) __chk_fail();
117
118 var i: usize = 0;
119 while (avail > 0 and i < n and src[i] != 0) : (i += 1) {
120 dest[dest_end + i] = src[i];
121 avail -= 1;
122 }
123
124 if (avail < 1) __chk_fail();
125
126 dest[dest_end + i] = 0;
127
128 return dest;
129}
130
131fn __memcpy_chk(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize, dest_n: usize) callconv(.c) ?[*]u8 {
132 if (dest_n < n) __chk_fail();
133 return memcpy(dest, src, n);
134}
135
136fn __memmove_chk(dest: ?[*]u8, src: ?[*]const u8, n: usize, dest_n: usize) callconv(.c) ?[*]u8 {
137 if (dest_n < n) __chk_fail();
138 return memmove(dest, src, n);
139}
140
141fn __memset_chk(dest: ?[*]u8, c: c_int, n: usize, dest_n: usize) callconv(.c) ?[*]u8 {
142 if (dest_n < n) __chk_fail();
143 return memset(dest, c, n);
144}