1*ec63e07aSXin Li // Copyright 2019 Google LLC
2*ec63e07aSXin Li //
3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*ec63e07aSXin Li // you may not use this file except in compliance with the License.
5*ec63e07aSXin Li // You may obtain a copy of the License at
6*ec63e07aSXin Li //
7*ec63e07aSXin Li // https://www.apache.org/licenses/LICENSE-2.0
8*ec63e07aSXin Li //
9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software
10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*ec63e07aSXin Li // See the License for the specific language governing permissions and
13*ec63e07aSXin Li // limitations under the License.
14*ec63e07aSXin Li
15*ec63e07aSXin Li #include <sys/ptrace.h>
16*ec63e07aSXin Li
17*ec63e07aSXin Li #include <algorithm>
18*ec63e07aSXin Li #include <cstdlib>
19*ec63e07aSXin Li #include <string>
20*ec63e07aSXin Li
21*ec63e07aSXin Li #include "absl/base/attributes.h"
22*ec63e07aSXin Li #include "sandboxed_api/examples/stringop/stringop_params.pb.h"
23*ec63e07aSXin Li #include "sandboxed_api/lenval_core.h"
24*ec63e07aSXin Li
25*ec63e07aSXin Li // Protobuf examples.
pb_reverse_string(stringop::StringReverse * pb)26*ec63e07aSXin Li extern "C" int pb_reverse_string(stringop::StringReverse* pb) {
27*ec63e07aSXin Li if (pb->payload_case() == pb->kInput) {
28*ec63e07aSXin Li std::string output = pb->input();
29*ec63e07aSXin Li std::reverse(output.begin(), output.end());
30*ec63e07aSXin Li pb->set_output(output);
31*ec63e07aSXin Li return 1;
32*ec63e07aSXin Li }
33*ec63e07aSXin Li return 0;
34*ec63e07aSXin Li }
35*ec63e07aSXin Li
pb_duplicate_string(stringop::StringDuplication * pb)36*ec63e07aSXin Li extern "C" int pb_duplicate_string(stringop::StringDuplication* pb) {
37*ec63e07aSXin Li if (pb->payload_case() == pb->kInput) {
38*ec63e07aSXin Li auto output = pb->input();
39*ec63e07aSXin Li pb->set_output(output + output);
40*ec63e07aSXin Li return 1;
41*ec63e07aSXin Li }
42*ec63e07aSXin Li return 0;
43*ec63e07aSXin Li }
44*ec63e07aSXin Li
45*ec63e07aSXin Li // Examples on raw data - both allocate and replace the data pointer.
reverse_string(sapi::LenValStruct * input)46*ec63e07aSXin Li extern "C" int reverse_string(sapi::LenValStruct* input) {
47*ec63e07aSXin Li char* new_buf = static_cast<char*>(malloc(input->size));
48*ec63e07aSXin Li const char* src_buf = static_cast<const char*>(input->data);
49*ec63e07aSXin Li input->size = input->size;
50*ec63e07aSXin Li for (size_t i = 0; i < input->size; i++) {
51*ec63e07aSXin Li new_buf[i] = src_buf[input->size - i - 1];
52*ec63e07aSXin Li }
53*ec63e07aSXin Li // Free old value.
54*ec63e07aSXin Li free(input->data);
55*ec63e07aSXin Li // Replace pointer to our new string.
56*ec63e07aSXin Li input->data = new_buf;
57*ec63e07aSXin Li return 1;
58*ec63e07aSXin Li }
59*ec63e07aSXin Li
duplicate_string(sapi::LenValStruct * input)60*ec63e07aSXin Li extern "C" int duplicate_string(sapi::LenValStruct* input) {
61*ec63e07aSXin Li char* new_buf = static_cast<char*>(malloc(2 * input->size));
62*ec63e07aSXin Li const char* src_buf = static_cast<const char*>(input->data);
63*ec63e07aSXin Li
64*ec63e07aSXin Li for (size_t c = 0; c < 2; c++) {
65*ec63e07aSXin Li for (size_t i = 0; i < input->size; i++) {
66*ec63e07aSXin Li new_buf[i + input->size * c] = src_buf[i];
67*ec63e07aSXin Li }
68*ec63e07aSXin Li }
69*ec63e07aSXin Li
70*ec63e07aSXin Li // Free old value.
71*ec63e07aSXin Li free(input->data);
72*ec63e07aSXin Li // Update structure.
73*ec63e07aSXin Li input->size = 2 * input->size;
74*ec63e07aSXin Li input->data = new_buf;
75*ec63e07aSXin Li return 1;
76*ec63e07aSXin Li }
77*ec63e07aSXin Li
get_raw_c_string()78*ec63e07aSXin Li extern "C" const void* get_raw_c_string() { return "Ten chars."; }
79*ec63e07aSXin Li
nop()80*ec63e07aSXin Li extern "C" void nop() {}
81*ec63e07aSXin Li
82*ec63e07aSXin Li // The "no tail-call" annotation and the additional indirection ensure that
83*ec63e07aSXin Li // either this function or its calling function shows up in the violation stack
84*ec63e07aSXin Li // trace. Otherwise, depending on optimization level and optimizer
85*ec63e07aSXin Li // aggressiveness, functions may be inlined, hoisted or omitted (in case of tail
86*ec63e07aSXin Li // calls).
87*ec63e07aSXin Li static ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL void
ViolateIndirect()88*ec63e07aSXin Li ViolateIndirect() {
89*ec63e07aSXin Li ptrace((__ptrace_request)990, 991, 992, 993);
90*ec63e07aSXin Li }
91*ec63e07aSXin Li
92*ec63e07aSXin Li // Using block syntax here, because SAPI's libclang based header generator won't
93*ec63e07aSXin Li // parse the attribute annotations otherwise.
94*ec63e07aSXin Li extern "C" {
violate()95*ec63e07aSXin Li ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL void violate() {
96*ec63e07aSXin Li ViolateIndirect();
97*ec63e07aSXin Li }
98*ec63e07aSXin Li }
99