summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Zajc <marko@zajc.eu.org>2024-04-05 15:39:04 +0200
committerMarko Zajc <marko@zajc.eu.org>2024-04-05 15:39:04 +0200
commit8763977280be49c599cb452ee29bfb21a2c9b722 (patch)
tree75b855f336a5bedba02ca19c868294af63186e74
parent693af38cc0a6e467841575107e30f60e1e215458 (diff)
Improve the project structure, update the protocol5.0.5
-rw-r--r--.gitignore8
-rw-r--r--Makefile13
-rw-r--r--include/config.h9
-rw-r--r--include/exchange_update_exception.h10
-rw-r--r--include/qalculate_exception.h15
-rw-r--r--include/security_util.h9
-rw-r--r--include/timeout_exception.h10
-rw-r--r--qalculate-helper.cpp232
-rw-r--r--src/exchange_update_exception.cpp7
-rw-r--r--src/qalculate-helper.cpp228
-rw-r--r--src/qalculate_exception.cpp12
-rw-r--r--src/security_util.cpp82
-rw-r--r--src/timeout_exception.cpp7
13 files changed, 406 insertions, 236 deletions
diff --git a/.gitignore b/.gitignore
index cd47243..ea0f573 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,13 @@
1# IDE
2/.project
3/.cproject
4/.vscode/
5/.settings/
6
1# environment 7# environment
2/.build_env 8/.build_env
3 9
4# binary 10# binary
5/qalculate-helper 11/qalculate-helper
12/target/
13/.debug/
diff --git a/Makefile b/Makefile
index 794f9ed..85e2be4 100644
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,13 @@ include .build_env
2export 2export
3 3
4NAME='qalculate-helper' 4NAME='qalculate-helper'
5FLAGS+=-I${QALCULATE_INCLUDE_PATH} 5FLAGS+=-Iinclude/
6FLAGS+=-L${QALCULATE_LIBRARY_PATH} 6ifneq ($(origin QALCULATE_INCLUDE_PATH), undefined)
7 FLAGS+=-I${QALCULATE_INCLUDE_PATH}
8endif
9ifneq ($(origin QALCULATE_LIBRARY_PATH), undefined)
10 FLAGS+=-L${QALCULATE_LIBRARY_PATH}
11endif
7FLAGS+=-Wl,-Bstatic 12FLAGS+=-Wl,-Bstatic
8FLAGS+=-lqalculate 13FLAGS+=-lqalculate
9FLAGS+=-Wl,-Bdynamic 14FLAGS+=-Wl,-Bdynamic
@@ -24,7 +29,7 @@ FLAGS+=-ansi
24FLAGS+=-O3 29FLAGS+=-O3
25FLAGS+=-D_FORTIFY_SOURCE=2 30FLAGS+=-D_FORTIFY_SOURCE=2
26FLAGS+=-fPIE 31FLAGS+=-fPIE
27FLAGS+=-std=c++2a 32FLAGS+=-std=c++17
28FLAGS+=-o $(NAME) 33FLAGS+=-o $(NAME)
29FLAGS+=-march=native 34FLAGS+=-march=native
30ifneq ($(origin SETUID), undefined) 35ifneq ($(origin SETUID), undefined)
@@ -35,5 +40,5 @@ ifneq ($(origin SECCOMP), undefined)
35endif 40endif
36 41
37all: 42all:
38 g++ qalculate-helper.cpp $(FLAGS) 43 g++ src/security_util.cpp src/exchange_update_exception.cpp src/qalculate_exception.cpp src/qalculate-helper.cpp src/timeout_exception.cpp $(FLAGS)
39 strip $(NAME) 44 strip $(NAME)
diff --git a/include/config.h b/include/config.h
new file mode 100644
index 0000000..b624351
--- /dev/null
+++ b/include/config.h
@@ -0,0 +1,9 @@
1#pragma once
2
3#define PRECISION_DEFAULT 20
4#define PRECISION_HIGH 900
5
6#define MIN_DECIMALS 20
7#define TIMEOUT_CALC 2000
8#define TIMEOUT_PRINT 2000
9#define TIMEOUT_UPDATE 30
diff --git a/include/exchange_update_exception.h b/include/exchange_update_exception.h
new file mode 100644
index 0000000..4adab32
--- /dev/null
+++ b/include/exchange_update_exception.h
@@ -0,0 +1,10 @@
1//SPDX-License-Identifier: GPL-3.0
2#pragma once
3
4#include <qalculate_exception.h>
5
6class exchange_update_exception : public qalculate_exception {
7 public:
8 exchange_update_exception();
9};
10
diff --git a/include/qalculate_exception.h b/include/qalculate_exception.h
new file mode 100644
index 0000000..c7e042b
--- /dev/null
+++ b/include/qalculate_exception.h
@@ -0,0 +1,15 @@
1//SPDX-License-Identifier: GPL-3.0
2#pragma once
3
4#include <stdexcept>
5
6class qalculate_exception : public std::runtime_error {
7 protected:
8 int code;
9
10 qalculate_exception(int code);
11
12 public:
13 int getCode() const;
14};
15
diff --git a/include/security_util.h b/include/security_util.h
new file mode 100644
index 0000000..a6b24f1
--- /dev/null
+++ b/include/security_util.h
@@ -0,0 +1,9 @@
1#pragma once
2
3#include <libqalculate/Calculator.h>
4
5void do_setuid();
6
7void do_defang_calculator(Calculator *calc);
8
9void do_seccomp();
diff --git a/include/timeout_exception.h b/include/timeout_exception.h
new file mode 100644
index 0000000..de2d628
--- /dev/null
+++ b/include/timeout_exception.h
@@ -0,0 +1,10 @@
1//SPDX-License-Identifier: GPL-3.0
2#pragma once
3
4#include <qalculate_exception.h>
5
6class timeout_exception : public qalculate_exception {
7 public:
8 timeout_exception();
9};
10
diff --git a/qalculate-helper.cpp b/qalculate-helper.cpp
deleted file mode 100644
index 4437476..0000000
--- a/qalculate-helper.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
1#include <sstream>
2#include <libqalculate/qalculate.h>
3#ifdef UID
4 #include <grp.h>
5 #include <cap-ng.h>
6#else
7 #warning "Not doing setuid/setgid, do not use in production!"
8#endif
9
10#ifdef SECCOMP
11 #include <seccomp.h>
12#else
13 #warning "Not doing seccomp, do not use in production!"
14#endif
15
16#define PRECISION_DEFAULT 20
17#define PRECISION_HIGH 900
18
19#define MIN_DECIMALS 20
20#define TIMEOUT_CALC 2000
21#define TIMEOUT_PRINT 2000
22#define TIMEOUT_UPDATE 30
23
24#define TYPE_MESSAGE putchar(1)
25#define TYPE_RESULT putchar(2)
26
27#define RESULT_APPROXIMATION_NO putchar(1);
28#define RESULT_APPROXIMATION_YES putchar(2);
29
30#define LEVEL_INFO putchar(1)
31#define LEVEL_WARNING putchar(2)
32#define LEVEL_ERROR putchar(3)
33#define LEVEL_UNKNOWN putchar(4)
34#define SEPARATOR putchar(0)
35
36#define COMMAND_UPDATE "update"
37
38#define MODE_HIGH_PRECISION 2
39#define MODE_EXACT 3
40
41#define ENOARG 101;
42#define ETIMEOUT 102;
43#define ECANTFETCH 103;
44
45using std::string;
46using std::stringstream;
47using std::getline;
48using std::atoi;
49
50int evaluate_single(EvaluationOptions *eo, MathStructure *result, int line_number, string expression) {
51 if (!CALCULATOR->calculate(result, CALCULATOR->unlocalizeExpression(expression), TIMEOUT_CALC, *eo))
52 return ETIMEOUT;
53
54 CalculatorMessage* message;
55 while ((message = CALCULATOR->message())) {
56 TYPE_MESSAGE;
57 switch (message->type()) {
58 case MESSAGE_INFORMATION:
59 LEVEL_INFO;
60 break;
61 case MESSAGE_WARNING:
62 LEVEL_WARNING;
63 break;
64 case MESSAGE_ERROR:
65 LEVEL_ERROR;
66 break;
67 default:
68 LEVEL_UNKNOWN;
69 break;
70 }
71 printf("line %d: ", line_number);
72 fputs(message->c_message(), stdout); SEPARATOR;
73 CALCULATOR->nextMessage();
74 }
75 return 0;
76}
77
78int evaluate(char *expression, char *mode, char *base) {
79 CALCULATOR->setExchangeRatesWarningEnabled(false);
80 CALCULATOR->loadExchangeRates();
81 CALCULATOR->loadGlobalDefinitions();
82
83 CALCULATOR->getActiveFunction("command")->destroy(); // rce
84#ifdef HAS_PLOT
85 CALCULATOR->getActiveFunction("plot")->destroy(); // no use
86#endif
87 CALCULATOR->getActiveVariable("uptime")->destroy(); // why would you
88
89 PrintOptions po;
90
91 po.base = atoi(base);
92
93 po.number_fraction_format = FRACTION_DECIMAL;
94 po.interval_display = INTERVAL_DISPLAY_PLUSMINUS;
95 po.use_unicode_signs = true;
96 //po.min_decimals = MIN_DECIMALS;
97 po.time_zone = TIME_ZONE_UTC;
98 po.abbreviate_names = true;
99 po.show_ending_zeroes = false;
100 //po.preserve_precision = true;
101 //po.restrict_to_parent_precision = false;
102
103 bool approximate = false;
104 po.is_approximate = &approximate;
105 CALCULATOR->setMessagePrintOptions(po);
106
107 EvaluationOptions eo;
108
109 eo.approximation = APPROXIMATION_TRY_EXACT;
110 eo.parse_options.unknowns_enabled = false;
111 eo.sync_units = false;
112
113#ifdef SECCOMP
114 scmp_filter_ctx ctx;
115 ctx = seccomp_init(SCMP_ACT_KILL);
116 /* 0 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
117 /* 1 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
118 /* 9 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
119 /* 10 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0);
120 /* 11 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0);
121 /* 13 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0);
122 /* 14 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0);
123 /* 24 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sched_yield), 0);
124 /* 230 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clock_nanosleep), 0);
125 /* 231 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
126 /* 262 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat), 0);
127 /* 273 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list), 0);
128 /* 334 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rseq), 0);
129 /* 435 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone3), 0);
130 int err = seccomp_load(ctx);
131 if (err) {
132 printf("couldn't seccomp: %d\n", err);
133 abort();
134 }
135#endif
136
137 int precision = PRECISION_DEFAULT;
138 switch (atoi(mode)) {
139 case MODE_EXACT:
140 eo.approximation = APPROXIMATION_EXACT;
141 po.number_fraction_format = FRACTION_DECIMAL_EXACT;
142 break;
143
144 case MODE_HIGH_PRECISION:
145 precision = PRECISION_HIGH;
146 po.indicate_infinite_series = false;
147 break;
148 }
149
150 CALCULATOR->setPrecision(precision);
151
152 MathStructure result;
153 stringstream expressions(expression);
154 string single_expression;
155 int line_number = 1;
156 int return_value;
157 while (getline(expressions, single_expression, '\n')) {
158 if ((return_value = evaluate_single(&eo, &result, line_number, single_expression)))
159 return return_value;
160 line_number++;
161 }
162
163 string string_result = CALCULATOR->print(result, TIMEOUT_PRINT, po, false, 1, TAG_TYPE_TERMINAL);
164
165 if (string_result.ends_with(CALCULATOR->timedOutString())) {
166 return ETIMEOUT;
167
168 } else {
169 TYPE_RESULT;
170 if (approximate) {
171 RESULT_APPROXIMATION_YES;
172 } else {
173 RESULT_APPROXIMATION_NO;
174 }
175
176 fputs(string_result.c_str(), stdout);
177 }
178 SEPARATOR;
179 return 0;
180}
181
182int update() {
183 if (!CALCULATOR->canFetch())
184 return ECANTFETCH;
185 CALCULATOR->fetchExchangeRates(TIMEOUT_UPDATE);
186 // for some reason this returns false even when it's successful so I'm not going to check it
187 return 0;
188}
189
190int main(int argc, char** argv) {
191#ifdef UID
192 if (setgroups(0, {})) {
193 perror("couldn't remove groups");
194 abort();
195 }
196
197 if (setresgid(UID, UID, UID)) {
198 perror("couldn't set gid");
199 abort();
200 }
201
202 if (setresuid(UID, UID, UID)) {
203 perror("couldn't set uid");
204 abort();
205 }
206
207 capng_clear(CAPNG_SELECT_BOTH);
208 if (capng_update(CAPNG_DROP, (capng_type_t)(CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SETGID)) {
209 printf("couldn't drop caps: can't select\n");
210 abort();
211 }
212 int err = capng_apply(CAPNG_SELECT_BOTH);
213 if (err) {
214 printf("couldn't drop caps: %d\n", err);
215 abort();
216 }
217#endif
218
219 if (argc < 2)
220 return ENOARG;
221
222 new Calculator(true);
223 if (argc == 2) {
224 if (strcmp(argv[1], COMMAND_UPDATE) == 0)
225 return update();
226 else
227 return 1;
228 } else {
229 return evaluate(argv[1], argv[2], argv[3]);
230 }
231}
232
diff --git a/src/exchange_update_exception.cpp b/src/exchange_update_exception.cpp
new file mode 100644
index 0000000..125ed21
--- /dev/null
+++ b/src/exchange_update_exception.cpp
@@ -0,0 +1,7 @@
1//SPDX-License-Identifier: GPL-3.0
2
3#include <exchange_update_exception.h>
4
5exchange_update_exception::exchange_update_exception() :
6 qalculate_exception(103) {
7}
diff --git a/src/qalculate-helper.cpp b/src/qalculate-helper.cpp
new file mode 100644
index 0000000..3356fb2
--- /dev/null
+++ b/src/qalculate-helper.cpp
@@ -0,0 +1,228 @@
1//SPDX-License-Identifier: GPL-3.0
2/*
3 * qalculate-helper.cpp
4 * Copyright (C) 2024 Marko Zajc
5 *
6 * This program is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, version 3.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
12 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this
15 * program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#include <config.h>
19#include <exchange_update_exception.h>
20#include <libqalculate/Calculator.h>
21#include <libqalculate/includes.h>
22#include <libqalculate/MathStructure.h>
23#include <security_util.h>
24#include <timeout_exception.h>
25#include <cstddef>
26#include <cstdio>
27#include <cstdlib>
28#include <cstring>
29#include <sstream>
30#include <string>
31#include <vector>
32
33using std::string;
34using std::stringstream;
35using std::getline;
36using std::vector;
37using std::string_view;
38using std::size_t;
39
40#if __cplusplus >= 201703L
41#include <string_view>
42
43static bool ends_with(string_view str, string_view suffix) {
44 return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
45}
46
47#endif
48
49const char TYPE_MESSAGE = 1;
50const char TYPE_RESULT = 2;
51
52const char RESULT_APPROXIMATION_NO = 1;
53const char RESULT_APPROXIMATION_YES = 2;
54
55const char LEVEL_INFO = 1;
56const char LEVEL_WARNING = 2;
57const char LEVEL_ERROR = 3;
58const char LEVEL_UNKNOWN = 4;
59const char SEPARATOR = 0;
60
61#define COMMAND_UPDATE "update"
62
63const unsigned long MODE_PRECISION = 1 << 0;
64const unsigned long MODE_EXACT = 1 << 1;
65const unsigned long MODE_NOCOLOR = 1 << 2;
66
67const int ETIMEOUT = 102;
68const int ECANTFETCH = 103;
69
70static MathStructure evaluate_single(Calculator *calc, const EvaluationOptions &eo, unsigned long line_number,
71 const string &expression) {
72 MathStructure result;
73 if (!calc->calculate(&result, calc->unlocalizeExpression(expression), TIMEOUT_CALC, eo))
74 throw timeout_exception();
75
76 const CalculatorMessage *message;
77 while ((message = CALCULATOR->message())) {
78 putchar(TYPE_MESSAGE);
79 switch (message->type()) {
80 case MESSAGE_INFORMATION:
81 putchar(LEVEL_INFO);
82 break;
83 case MESSAGE_WARNING:
84 putchar(LEVEL_WARNING);
85 break;
86 case MESSAGE_ERROR:
87 putchar(LEVEL_ERROR);
88 break;
89 default:
90 putchar(LEVEL_UNKNOWN);
91 break;
92 }
93 printf("line %lu: ", line_number);
94 fputs(message->c_message(), stdout);
95 putchar(SEPARATOR);
96 calc->nextMessage();
97 }
98 return result;
99}
100
101static bool mode_set(unsigned long mode, unsigned long test) {
102 return mode & test;
103}
104
105static void set_precision(Calculator *calc, unsigned long mode, EvaluationOptions &eo, PrintOptions &po) {
106 int precision = PRECISION_DEFAULT;
107
108 if (mode_set(mode, MODE_EXACT)) {
109 eo.approximation = APPROXIMATION_EXACT;
110 po.number_fraction_format = FRACTION_DECIMAL_EXACT;
111
112 } else if (mode_set(mode, MODE_PRECISION)) {
113 precision = PRECISION_HIGH;
114 po.indicate_infinite_series = false;
115 }
116
117 calc->setPrecision(precision);
118}
119
120MathStructure evaluate_all(const vector<string> &expressions, const EvaluationOptions &eo, Calculator *calc) {
121 for (size_t i = 0; i < expressions.size() - 1; ++i)
122 evaluate_single(calc, eo, i + 1, expressions[i]);
123 return evaluate_single(calc, eo, expressions.size(), expressions.back());
124}
125
126void print_result(Calculator *calc, const MathStructure &result_struct, const PrintOptions &po, int mode,
127 bool approximate) {
128 string result = calc->print(result_struct, TIMEOUT_PRINT, po, false, mode_set(mode, MODE_NOCOLOR) ? 0 : 1,
129 TAG_TYPE_TERMINAL);
130
131 if (ends_with(result, calc->timedOutString())) {
132 throw timeout_exception();
133
134 } else {
135 putchar(TYPE_RESULT);
136 putchar(approximate ? RESULT_APPROXIMATION_YES : RESULT_APPROXIMATION_NO);
137 fputs(result.c_str(), stdout);
138 }
139 putchar(SEPARATOR);
140}
141
142static EvaluationOptions get_evaluationoptions() {
143 EvaluationOptions eo;
144 eo.approximation = APPROXIMATION_TRY_EXACT;
145 eo.parse_options.unknowns_enabled = false;
146 eo.sync_units = false;
147 return eo;
148}
149
150static PrintOptions get_printoptions(int base, bool &approximate) {
151 PrintOptions po;
152 po.base = base;
153 po.number_fraction_format = FRACTION_DECIMAL;
154 po.interval_display = INTERVAL_DISPLAY_PLUSMINUS;
155 po.use_unicode_signs = true;
156 //po.min_decimals = MIN_DECIMALS;
157 po.time_zone = TIME_ZONE_UTC;
158 po.abbreviate_names = true;
159 po.spell_out_logical_operators = true;
160 po.allow_non_usable = true;
161 po.show_ending_zeroes = false;
162 //po.preserve_precision = true;
163 //po.restrict_to_parent_precision = false;
164 po.is_approximate = &approximate;
165 return po;
166}
167
168static void evaluate(Calculator *calc, const vector<string> &expressions, unsigned int mode, int base) {
169 calc->setExchangeRatesWarningEnabled(false);
170 calc->loadExchangeRates();
171 calc->loadGlobalDefinitions();
172
173 bool approximate = false;
174
175 PrintOptions po = get_printoptions(base, approximate);
176 EvaluationOptions eo = get_evaluationoptions();
177 set_precision(calc, mode, eo, po);
178
179 calc->setMessagePrintOptions(po);
180
181 do_seccomp();
182
183 auto result_struct = evaluate_all(expressions, eo, calc);
184
185 print_result(calc, result_struct, po, mode, approximate);
186}
187
188static void update() {
189 if (!CALCULATOR->canFetch())
190 throw exchange_update_exception();
191
192 CALCULATOR->fetchExchangeRates(TIMEOUT_UPDATE);
193 // for some reason this returns false even when it's successful so I'm not going to check it
194}
195
196static vector<string> parseExpressions(stringstream input) {
197 vector<string> result;
198 string expression;
199 while (std::getline(input, expression, '\n'))
200 result.push_back(expression);
201
202 return result;
203}
204
205int main(int argc, char **argv) {
206 do_setuid();
207
208 if (argc < 2)
209 return 1;
210
211 auto *calc = new Calculator(true);
212 do_defang_calculator(calc);
213 try {
214 if (argc == 2) {
215 if (strcmp(argv[1], COMMAND_UPDATE) == 0)
216 update();
217 else
218 return 1;
219 } else {
220 evaluate(calc, parseExpressions(stringstream(argv[1])), std::strtoul(argv[2], nullptr, 10),
221 std::strtol(argv[3], nullptr, 10));
222 }
223
224 } catch (const qalculate_exception &e) {
225 return e.getCode();
226 }
227}
228
diff --git a/src/qalculate_exception.cpp b/src/qalculate_exception.cpp
new file mode 100644
index 0000000..db38fa3
--- /dev/null
+++ b/src/qalculate_exception.cpp
@@ -0,0 +1,12 @@
1//SPDX-License-Identifier: GPL-3.0
2
3#include <qalculate_exception.h>
4#include <string>
5
6qalculate_exception::qalculate_exception(int code) :
7 std::runtime_error(std::to_string(code).c_str()), code(code) {
8}
9
10int qalculate_exception::getCode() const {
11 return this->code;
12}
diff --git a/src/security_util.cpp b/src/security_util.cpp
new file mode 100644
index 0000000..33728fc
--- /dev/null
+++ b/src/security_util.cpp
@@ -0,0 +1,82 @@
1//SPDX-License-Identifier: GPL-3.0
2
3#include <libqalculate/Function.h>
4#include <libqalculate/Variable.h>
5#include <security_util.h>
6
7#ifdef UID
8#include <grp.h>
9#include <cap-ng.h>
10#else
11#warning "Not doing setuid/setgid, do not use in production!"
12#endif
13
14#ifdef SECCOMP
15#include <seccomp.h>
16#else
17#warning "Not doing seccomp, do not use in production!"
18#endif
19
20void do_setuid() {
21#ifdef UID
22if (setgroups(0, {})) {
23 perror("couldn't remove groups");
24 abort();
25}
26
27if (setresgid(UID, UID, UID)) {
28 perror("couldn't set gid");
29 abort();
30}
31
32if (setresuid(UID, UID, UID)) {
33 perror("couldn't set uid");
34 abort();
35}
36
37capng_clear(CAPNG_SELECT_BOTH);
38if (capng_update(CAPNG_DROP, (capng_type_t)(CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SETGID)) {
39 printf("couldn't drop caps: can't select\n");
40 abort();
41}
42int err = capng_apply(CAPNG_SELECT_BOTH);
43if (err) {
44 printf("couldn't drop caps: %d\n", err);
45 abort();
46}
47#endif
48}
49
50void do_defang_calculator(Calculator *calc) {
51 calc->getActiveFunction("command")->destroy(); // rce
52#ifdef HAS_PLOT
53 calc->getActiveFunction("plot")->destroy(); // wouldn't work
54#endif
55 calc->getActiveVariable("uptime")->destroy(); // information leakage
56}
57
58void do_seccomp() {
59#ifdef SECCOMP
60scmp_filter_ctx ctx;
61ctx = seccomp_init(SCMP_ACT_KILL);
62/* 0 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
63/* 1 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
64/* 9 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
65/* 10 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0);
66/* 11 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0);
67/* 13 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0);
68/* 14 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0);
69/* 24 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sched_yield), 0);
70/* 230 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clock_nanosleep), 0);
71/* 231 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
72/* 262 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat), 0);
73/* 273 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list), 0);
74/* 334 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rseq), 0);
75/* 435 */ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone3), 0);
76int err = seccomp_load(ctx);
77if (err) {
78 printf("couldn't seccomp: %d\n", err);
79 abort();
80}
81#endif
82}
diff --git a/src/timeout_exception.cpp b/src/timeout_exception.cpp
new file mode 100644
index 0000000..09d4bf3
--- /dev/null
+++ b/src/timeout_exception.cpp
@@ -0,0 +1,7 @@
1//SPDX-License-Identifier: GPL-3.0
2
3#include <timeout_exception.h>
4
5timeout_exception::timeout_exception() :
6 qalculate_exception(102) {
7}