1 From a4d7f5ee6f36decdcd18d70078e1f0a847fe9b24 Mon Sep 17 00:00:00 2001
2 From: Tobias Brunner <tobias@strongswan.org>
3 Date: Mon, 30 Nov 2015 16:04:35 +0100
4 Subject: [PATCH 1/2] connmark: Fix alignment when adding rules
6 The structs that make up a message sent to the kernel have all to be
7 aligned with XT_ALIGN. That was not necessarily the case when
8 initializing the complete message as struct.
12 src/libcharon/plugins/connmark/connmark_listener.c | 332 +++++++++++----------
13 1 file changed, 172 insertions(+), 160 deletions(-)
15 diff --git a/src/libcharon/plugins/connmark/connmark_listener.c b/src/libcharon/plugins/connmark/connmark_listener.c
16 index 23df690..cd53701 100644
17 --- a/src/libcharon/plugins/connmark/connmark_listener.c
18 +++ b/src/libcharon/plugins/connmark/connmark_listener.c
21 + * Copyright (C) 2015 Tobias Brunner
22 + * Hochschule fuer Technik Rapperswil
24 * Copyright (C) 2014 Martin Willi
25 * Copyright (C) 2014 revosec AG
28 #include <linux/netfilter/xt_policy.h>
29 #include <linux/netfilter/xt_CONNMARK.h>
32 + * Add a struct at the current position in the buffer
34 +#define ADD_STRUCT(pos, st, ...) ({\
35 + typeof(pos) _cur = pos; pos += XT_ALIGN(sizeof(st));\
36 + *(st*)_cur = (st){ __VA_ARGS__ };\
40 typedef struct private_connmark_listener_t private_connmark_listener_t;
42 @@ -108,54 +119,54 @@ static bool manage_pre_esp_in_udp(private_connmark_listener_t *this,
43 u_int mark, u_int32_t spi,
44 host_t *dst, host_t *src)
48 - struct ipt_entry_match m;
50 - struct ipt_entry_target t;
51 - struct xt_mark_tginfo2 tm;
54 - .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
56 - .next_offset = sizeof(ipt),
58 - .proto = IPPROTO_UDP,
60 + u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) +
61 + XT_ALIGN(sizeof(struct xt_udp));
62 + u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
63 + u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) +
64 + XT_ALIGN(sizeof(struct xt_mark_tginfo2));
65 + u_int16_t entry_size = target_offset + target_size;
66 + u_char ipt[entry_size], *pos = ipt;
67 + struct ipt_entry *e;
69 + memset(ipt, 0, sizeof(ipt));
70 + e = ADD_STRUCT(pos, struct ipt_entry,
71 + .target_offset = target_offset,
72 + .next_offset = entry_size,
74 + .proto = IPPROTO_UDP,
79 - .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.udp)),
83 + if (!host2in(dst, &e->ip.dst, &e->ip.dmsk) ||
84 + !host2in(src, &e->ip.src, &e->ip.smsk))
88 + ADD_STRUCT(pos, struct ipt_entry_match,
91 + .match_size = match_size,
96 - .spts = { src->get_port(src), src->get_port(src) },
97 - .dpts = { dst->get_port(dst), dst->get_port(dst) },
102 - .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)),
107 + ADD_STRUCT(pos, struct xt_udp,
108 + .spts = { src->get_port(src), src->get_port(src) },
109 + .dpts = { dst->get_port(dst), dst->get_port(dst) },
111 + ADD_STRUCT(pos, struct ipt_entry_target,
114 + .target_size = target_size,
125 - if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
126 - !host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
130 - return manage_rule(ipth, "PREROUTING", add, &ipt.e);
132 + ADD_STRUCT(pos, struct xt_mark_tginfo2,
136 + return manage_rule(ipth, "PREROUTING", add, e);
140 @@ -166,53 +177,53 @@ static bool manage_pre_esp(private_connmark_listener_t *this,
141 u_int mark, u_int32_t spi,
142 host_t *dst, host_t *src)
145 - struct ipt_entry e;
146 - struct ipt_entry_match m;
148 - struct ipt_entry_target t;
149 - struct xt_mark_tginfo2 tm;
152 - .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
154 - .next_offset = sizeof(ipt),
156 - .proto = IPPROTO_ESP,
158 + u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) +
159 + XT_ALIGN(sizeof(struct xt_esp));
160 + u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
161 + u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) +
162 + XT_ALIGN(sizeof(struct xt_mark_tginfo2));
163 + u_int16_t entry_size = target_offset + target_size;
164 + u_char ipt[entry_size], *pos = ipt;
165 + struct ipt_entry *e;
167 + memset(ipt, 0, sizeof(ipt));
168 + e = ADD_STRUCT(pos, struct ipt_entry,
169 + .target_offset = target_offset,
170 + .next_offset = entry_size,
172 + .proto = IPPROTO_ESP,
177 - .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.esp)),
181 + if (!host2in(dst, &e->ip.dst, &e->ip.dmsk) ||
182 + !host2in(src, &e->ip.src, &e->ip.smsk))
186 + ADD_STRUCT(pos, struct ipt_entry_match,
189 + .match_size = match_size,
194 - .spis = { htonl(spi), htonl(spi) },
199 - .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)),
204 + ADD_STRUCT(pos, struct xt_esp,
205 + .spis = { htonl(spi), htonl(spi) },
207 + ADD_STRUCT(pos, struct ipt_entry_target,
210 + .target_size = target_size,
221 - if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
222 - !host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
226 - return manage_rule(ipth, "PREROUTING", add, &ipt.e);
228 + ADD_STRUCT(pos, struct xt_mark_tginfo2,
232 + return manage_rule(ipth, "PREROUTING", add, e);
236 @@ -238,59 +249,59 @@ static bool manage_in(private_connmark_listener_t *this,
237 u_int mark, u_int32_t spi,
238 traffic_selector_t *dst, traffic_selector_t *src)
241 - struct ipt_entry e;
242 - struct ipt_entry_match m;
243 - struct xt_policy_info p;
244 - struct ipt_entry_target t;
245 - struct xt_connmark_tginfo1 cm;
248 - .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
250 - .next_offset = sizeof(ipt),
255 - .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.p)),
258 + u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) +
259 + XT_ALIGN(sizeof(struct xt_policy_info));
260 + u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
261 + u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) +
262 + XT_ALIGN(sizeof(struct xt_connmark_tginfo1));
263 + u_int16_t entry_size = target_offset + target_size;
264 + u_char ipt[entry_size], *pos = ipt;
265 + struct ipt_entry *e;
267 + memset(ipt, 0, sizeof(ipt));
268 + e = ADD_STRUCT(pos, struct ipt_entry,
269 + .target_offset = target_offset,
270 + .next_offset = entry_size,
272 + if (!ts2in(dst, &e->ip.dst, &e->ip.dmsk) ||
273 + !ts2in(src, &e->ip.src, &e->ip.smsk))
277 + ADD_STRUCT(pos, struct ipt_entry_match,
280 + .match_size = match_size,
291 + ADD_STRUCT(pos, struct xt_policy_info,
298 - .flags = XT_POLICY_MATCH_IN,
303 - .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)),
304 - .name = "CONNMARK",
308 + .flags = XT_POLICY_MATCH_IN,
310 + ADD_STRUCT(pos, struct ipt_entry_target,
313 + .target_size = target_size,
314 + .name = "CONNMARK",
322 - .mode = XT_CONNMARK_SET,
326 - if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
327 - !ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
331 - return manage_rule(ipth, "INPUT", add, &ipt.e);
333 + ADD_STRUCT(pos, struct xt_connmark_tginfo1,
337 + .mode = XT_CONNMARK_SET,
339 + return manage_rule(ipth, "INPUT", add, e);
343 @@ -300,37 +311,38 @@ static bool manage_out(private_connmark_listener_t *this,
344 struct iptc_handle *ipth, bool add,
345 traffic_selector_t *dst, traffic_selector_t *src)
348 - struct ipt_entry e;
349 - struct ipt_entry_target t;
350 - struct xt_connmark_tginfo1 cm;
353 - .target_offset = XT_ALIGN(sizeof(ipt.e)),
354 - .next_offset = sizeof(ipt),
359 - .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)),
360 - .name = "CONNMARK",
368 - .mode = XT_CONNMARK_RESTORE,
372 - if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
373 - !ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
374 + u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry));
375 + u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) +
376 + XT_ALIGN(sizeof(struct xt_connmark_tginfo1));
377 + u_int16_t entry_size = target_offset + target_size;
378 + u_char ipt[entry_size], *pos = ipt;
379 + struct ipt_entry *e;
381 + memset(ipt, 0, sizeof(ipt));
382 + e = ADD_STRUCT(pos, struct ipt_entry,
383 + .target_offset = target_offset,
384 + .next_offset = entry_size,
386 + if (!ts2in(dst, &e->ip.dst, &e->ip.dmsk) ||
387 + !ts2in(src, &e->ip.src, &e->ip.smsk))
391 - return manage_rule(ipth, "OUTPUT", add, &ipt.e);
392 + ADD_STRUCT(pos, struct ipt_entry_target,
395 + .target_size = target_size,
396 + .name = "CONNMARK",
401 + ADD_STRUCT(pos, struct xt_connmark_tginfo1,
404 + .mode = XT_CONNMARK_RESTORE,
406 + return manage_rule(ipth, "OUTPUT", add, e);