connmark: Fix alignment when adding rules
The structs that make up a message sent to the kernel have all to be aligned with XT_ALIGN. That was not necessarily the case when initializing the complete message as struct. Fixes #1212.
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2015 Tobias Brunner
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
* Copyright (C) 2014 Martin Willi
|
* Copyright (C) 2014 Martin Willi
|
||||||
* Copyright (C) 2014 revosec AG
|
* Copyright (C) 2014 revosec AG
|
||||||
*
|
*
|
||||||
@@ -25,6 +28,14 @@
|
|||||||
#include <linux/netfilter/xt_policy.h>
|
#include <linux/netfilter/xt_policy.h>
|
||||||
#include <linux/netfilter/xt_CONNMARK.h>
|
#include <linux/netfilter/xt_CONNMARK.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a struct at the current position in the buffer
|
||||||
|
*/
|
||||||
|
#define ADD_STRUCT(pos, st, ...) ({\
|
||||||
|
typeof(pos) _cur = pos; pos += XT_ALIGN(sizeof(st));\
|
||||||
|
*(st*)_cur = (st){ __VA_ARGS__ };\
|
||||||
|
(st*)_cur;\
|
||||||
|
})
|
||||||
|
|
||||||
typedef struct private_connmark_listener_t private_connmark_listener_t;
|
typedef struct private_connmark_listener_t private_connmark_listener_t;
|
||||||
|
|
||||||
@@ -108,54 +119,54 @@ static bool manage_pre_esp_in_udp(private_connmark_listener_t *this,
|
|||||||
u_int mark, u_int32_t spi,
|
u_int mark, u_int32_t spi,
|
||||||
host_t *dst, host_t *src)
|
host_t *dst, host_t *src)
|
||||||
{
|
{
|
||||||
struct {
|
u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) +
|
||||||
struct ipt_entry e;
|
XT_ALIGN(sizeof(struct xt_udp));
|
||||||
struct ipt_entry_match m;
|
u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
|
||||||
struct xt_udp udp;
|
u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) +
|
||||||
struct ipt_entry_target t;
|
XT_ALIGN(sizeof(struct xt_mark_tginfo2));
|
||||||
struct xt_mark_tginfo2 tm;
|
u_int16_t entry_size = target_offset + target_size;
|
||||||
} ipt = {
|
u_char ipt[entry_size], *pos = ipt;
|
||||||
.e = {
|
struct ipt_entry *e;
|
||||||
.target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
|
|
||||||
sizeof(ipt.udp)),
|
|
||||||
.next_offset = sizeof(ipt),
|
|
||||||
.ip = {
|
|
||||||
.proto = IPPROTO_UDP,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.m = {
|
|
||||||
.u = {
|
|
||||||
.user = {
|
|
||||||
.match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.udp)),
|
|
||||||
.name = "udp",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.udp = {
|
|
||||||
.spts = { src->get_port(src), src->get_port(src) },
|
|
||||||
.dpts = { dst->get_port(dst), dst->get_port(dst) },
|
|
||||||
},
|
|
||||||
.t = {
|
|
||||||
.u = {
|
|
||||||
.user = {
|
|
||||||
.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)),
|
|
||||||
.name = "MARK",
|
|
||||||
.revision = 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.tm = {
|
|
||||||
.mark = mark,
|
|
||||||
.mask = ~0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
|
memset(ipt, 0, sizeof(ipt));
|
||||||
!host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
|
e = ADD_STRUCT(pos, struct ipt_entry,
|
||||||
|
.target_offset = target_offset,
|
||||||
|
.next_offset = entry_size,
|
||||||
|
.ip = {
|
||||||
|
.proto = IPPROTO_UDP,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (!host2in(dst, &e->ip.dst, &e->ip.dmsk) ||
|
||||||
|
!host2in(src, &e->ip.src, &e->ip.smsk))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return manage_rule(ipth, "PREROUTING", add, &ipt.e);
|
ADD_STRUCT(pos, struct ipt_entry_match,
|
||||||
|
.u = {
|
||||||
|
.user = {
|
||||||
|
.match_size = match_size,
|
||||||
|
.name = "udp",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ADD_STRUCT(pos, struct xt_udp,
|
||||||
|
.spts = { src->get_port(src), src->get_port(src) },
|
||||||
|
.dpts = { dst->get_port(dst), dst->get_port(dst) },
|
||||||
|
);
|
||||||
|
ADD_STRUCT(pos, struct ipt_entry_target,
|
||||||
|
.u = {
|
||||||
|
.user = {
|
||||||
|
.target_size = target_size,
|
||||||
|
.name = "MARK",
|
||||||
|
.revision = 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ADD_STRUCT(pos, struct xt_mark_tginfo2,
|
||||||
|
.mark = mark,
|
||||||
|
.mask = ~0,
|
||||||
|
);
|
||||||
|
return manage_rule(ipth, "PREROUTING", add, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,53 +177,53 @@ static bool manage_pre_esp(private_connmark_listener_t *this,
|
|||||||
u_int mark, u_int32_t spi,
|
u_int mark, u_int32_t spi,
|
||||||
host_t *dst, host_t *src)
|
host_t *dst, host_t *src)
|
||||||
{
|
{
|
||||||
struct {
|
u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) +
|
||||||
struct ipt_entry e;
|
XT_ALIGN(sizeof(struct xt_esp));
|
||||||
struct ipt_entry_match m;
|
u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
|
||||||
struct xt_esp esp;
|
u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) +
|
||||||
struct ipt_entry_target t;
|
XT_ALIGN(sizeof(struct xt_mark_tginfo2));
|
||||||
struct xt_mark_tginfo2 tm;
|
u_int16_t entry_size = target_offset + target_size;
|
||||||
} ipt = {
|
u_char ipt[entry_size], *pos = ipt;
|
||||||
.e = {
|
struct ipt_entry *e;
|
||||||
.target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
|
|
||||||
sizeof(ipt.esp)),
|
|
||||||
.next_offset = sizeof(ipt),
|
|
||||||
.ip = {
|
|
||||||
.proto = IPPROTO_ESP,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.m = {
|
|
||||||
.u = {
|
|
||||||
.user = {
|
|
||||||
.match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.esp)),
|
|
||||||
.name = "esp",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.esp = {
|
|
||||||
.spis = { htonl(spi), htonl(spi) },
|
|
||||||
},
|
|
||||||
.t = {
|
|
||||||
.u = {
|
|
||||||
.user = {
|
|
||||||
.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)),
|
|
||||||
.name = "MARK",
|
|
||||||
.revision = 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.tm = {
|
|
||||||
.mark = mark,
|
|
||||||
.mask = ~0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
|
memset(ipt, 0, sizeof(ipt));
|
||||||
!host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
|
e = ADD_STRUCT(pos, struct ipt_entry,
|
||||||
|
.target_offset = target_offset,
|
||||||
|
.next_offset = entry_size,
|
||||||
|
.ip = {
|
||||||
|
.proto = IPPROTO_ESP,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (!host2in(dst, &e->ip.dst, &e->ip.dmsk) ||
|
||||||
|
!host2in(src, &e->ip.src, &e->ip.smsk))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return manage_rule(ipth, "PREROUTING", add, &ipt.e);
|
ADD_STRUCT(pos, struct ipt_entry_match,
|
||||||
|
.u = {
|
||||||
|
.user = {
|
||||||
|
.match_size = match_size,
|
||||||
|
.name = "esp",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ADD_STRUCT(pos, struct xt_esp,
|
||||||
|
.spis = { htonl(spi), htonl(spi) },
|
||||||
|
);
|
||||||
|
ADD_STRUCT(pos, struct ipt_entry_target,
|
||||||
|
.u = {
|
||||||
|
.user = {
|
||||||
|
.target_size = target_size,
|
||||||
|
.name = "MARK",
|
||||||
|
.revision = 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ADD_STRUCT(pos, struct xt_mark_tginfo2,
|
||||||
|
.mark = mark,
|
||||||
|
.mask = ~0,
|
||||||
|
);
|
||||||
|
return manage_rule(ipth, "PREROUTING", add, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -238,59 +249,59 @@ static bool manage_in(private_connmark_listener_t *this,
|
|||||||
u_int mark, u_int32_t spi,
|
u_int mark, u_int32_t spi,
|
||||||
traffic_selector_t *dst, traffic_selector_t *src)
|
traffic_selector_t *dst, traffic_selector_t *src)
|
||||||
{
|
{
|
||||||
struct {
|
u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) +
|
||||||
struct ipt_entry e;
|
XT_ALIGN(sizeof(struct xt_policy_info));
|
||||||
struct ipt_entry_match m;
|
u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
|
||||||
struct xt_policy_info p;
|
u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) +
|
||||||
struct ipt_entry_target t;
|
XT_ALIGN(sizeof(struct xt_connmark_tginfo1));
|
||||||
struct xt_connmark_tginfo1 cm;
|
u_int16_t entry_size = target_offset + target_size;
|
||||||
} ipt = {
|
u_char ipt[entry_size], *pos = ipt;
|
||||||
.e = {
|
struct ipt_entry *e;
|
||||||
.target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
|
|
||||||
sizeof(ipt.p)),
|
|
||||||
.next_offset = sizeof(ipt),
|
|
||||||
},
|
|
||||||
.m = {
|
|
||||||
.u = {
|
|
||||||
.user = {
|
|
||||||
.match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.p)),
|
|
||||||
.name = "policy",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.p = {
|
|
||||||
.pol = {
|
|
||||||
{
|
|
||||||
.spi = spi,
|
|
||||||
.match.spi = 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.len = 1,
|
|
||||||
.flags = XT_POLICY_MATCH_IN,
|
|
||||||
},
|
|
||||||
.t = {
|
|
||||||
.u = {
|
|
||||||
.user = {
|
|
||||||
.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)),
|
|
||||||
.name = "CONNMARK",
|
|
||||||
.revision = 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.cm = {
|
|
||||||
.ctmark = mark,
|
|
||||||
.ctmask = ~0,
|
|
||||||
.nfmask = ~0,
|
|
||||||
.mode = XT_CONNMARK_SET,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
|
memset(ipt, 0, sizeof(ipt));
|
||||||
!ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
|
e = ADD_STRUCT(pos, struct ipt_entry,
|
||||||
|
.target_offset = target_offset,
|
||||||
|
.next_offset = entry_size,
|
||||||
|
);
|
||||||
|
if (!ts2in(dst, &e->ip.dst, &e->ip.dmsk) ||
|
||||||
|
!ts2in(src, &e->ip.src, &e->ip.smsk))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return manage_rule(ipth, "INPUT", add, &ipt.e);
|
ADD_STRUCT(pos, struct ipt_entry_match,
|
||||||
|
.u = {
|
||||||
|
.user = {
|
||||||
|
.match_size = match_size,
|
||||||
|
.name = "policy",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ADD_STRUCT(pos, struct xt_policy_info,
|
||||||
|
.pol = {
|
||||||
|
{
|
||||||
|
.spi = spi,
|
||||||
|
.match.spi = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.len = 1,
|
||||||
|
.flags = XT_POLICY_MATCH_IN,
|
||||||
|
);
|
||||||
|
ADD_STRUCT(pos, struct ipt_entry_target,
|
||||||
|
.u = {
|
||||||
|
.user = {
|
||||||
|
.target_size = target_size,
|
||||||
|
.name = "CONNMARK",
|
||||||
|
.revision = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ADD_STRUCT(pos, struct xt_connmark_tginfo1,
|
||||||
|
.ctmark = mark,
|
||||||
|
.ctmask = ~0,
|
||||||
|
.nfmask = ~0,
|
||||||
|
.mode = XT_CONNMARK_SET,
|
||||||
|
);
|
||||||
|
return manage_rule(ipth, "INPUT", add, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -300,37 +311,38 @@ static bool manage_out(private_connmark_listener_t *this,
|
|||||||
struct iptc_handle *ipth, bool add,
|
struct iptc_handle *ipth, bool add,
|
||||||
traffic_selector_t *dst, traffic_selector_t *src)
|
traffic_selector_t *dst, traffic_selector_t *src)
|
||||||
{
|
{
|
||||||
struct {
|
u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry));
|
||||||
struct ipt_entry e;
|
u_int16_t target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) +
|
||||||
struct ipt_entry_target t;
|
XT_ALIGN(sizeof(struct xt_connmark_tginfo1));
|
||||||
struct xt_connmark_tginfo1 cm;
|
u_int16_t entry_size = target_offset + target_size;
|
||||||
} ipt = {
|
u_char ipt[entry_size], *pos = ipt;
|
||||||
.e = {
|
struct ipt_entry *e;
|
||||||
.target_offset = XT_ALIGN(sizeof(ipt.e)),
|
|
||||||
.next_offset = sizeof(ipt),
|
|
||||||
},
|
|
||||||
.t = {
|
|
||||||
.u = {
|
|
||||||
.user = {
|
|
||||||
.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)),
|
|
||||||
.name = "CONNMARK",
|
|
||||||
.revision = 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.cm = {
|
|
||||||
.ctmask = ~0,
|
|
||||||
.nfmask = ~0,
|
|
||||||
.mode = XT_CONNMARK_RESTORE,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
|
memset(ipt, 0, sizeof(ipt));
|
||||||
!ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
|
e = ADD_STRUCT(pos, struct ipt_entry,
|
||||||
|
.target_offset = target_offset,
|
||||||
|
.next_offset = entry_size,
|
||||||
|
);
|
||||||
|
if (!ts2in(dst, &e->ip.dst, &e->ip.dmsk) ||
|
||||||
|
!ts2in(src, &e->ip.src, &e->ip.smsk))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return manage_rule(ipth, "OUTPUT", add, &ipt.e);
|
ADD_STRUCT(pos, struct ipt_entry_target,
|
||||||
|
.u = {
|
||||||
|
.user = {
|
||||||
|
.target_size = target_size,
|
||||||
|
.name = "CONNMARK",
|
||||||
|
.revision = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ADD_STRUCT(pos, struct xt_connmark_tginfo1,
|
||||||
|
.ctmask = ~0,
|
||||||
|
.nfmask = ~0,
|
||||||
|
.mode = XT_CONNMARK_RESTORE,
|
||||||
|
);
|
||||||
|
return manage_rule(ipth, "OUTPUT", add, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user