* [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-20 19:15 ` Richard Haines
0 siblings, 0 replies; 32+ messages in thread
From: Richard Haines via Selinux @ 2018-02-20 19:15 UTC (permalink / raw)
To: selinux-+05T5uksL2qpZYMLLGbcSA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-sctp-u79uwXL29TY76Z2rM5mHXA,
linux-security-module-u79uwXL29TY76Z2rM5mHXA
Cc: marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w,
nhorman-2XuSBdqkA4R54TAoqtyWWQ, vyasevich-Re5JQEeQqe8AvxtiuMwx3w,
sds-+05T5uksL2qpZYMLLGbcSA
Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
and CALIPSO/IPv6 services.
Signed-off-by: Richard Haines <richard_c_haines-FhtRXb7CoQBt1OO0OYaSVA@public.gmane.org>
---
All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
pass.
V7 Changes:
1) Log when copy ip options fail for IPv4 and IPv6
2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
func_tests do not test with struct sctp_assoc_value. Just used simple test
and okay.
3) Move calculation of overheads to sctp_packet_config().
NOTE: Initially in sctp_packet_reset() I set packet->size and
packet->overhead to zero (as it is a reset). This was okay for all the
lksctp-tools function tests, however when running "sctp-tests" ndatshched
tests it causes these to fail with an st_s.log entry of:
sid: 3, expected: 3
sid: 3, expected: 3
unexpected sid packet !!!
sid: 1, expected: 3
I then found sctp_packet_transmit() relies on setting
"packet->size = packet->overhead;" to reset size to the current overhead
after sending packets, hence the comment in sctp_packet_reset()
include/net/sctp/sctp.h | 4 +++-
include/net/sctp/structs.h | 2 ++
net/sctp/chunk.c | 10 +++++++---
net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
net/sctp/output.c | 34 +++++++++++++++++++++-------------
net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
net/sctp/socket.c | 11 ++++++++---
7 files changed, 117 insertions(+), 27 deletions(-)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index f7ae6b0..25c5c87 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
{
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
int frag = pmtu;
- frag -= sp->pf->af->net_header_len;
+ frag -= af->ip_options_len(asoc->base.sk);
+ frag -= af->net_header_len;
frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
if (asoc->user_frag)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 03e92dd..ead5fce 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -491,6 +491,7 @@ struct sctp_af {
void (*ecn_capable)(struct sock *sk);
__u16 net_header_len;
int sockaddr_len;
+ int (*ip_options_len)(struct sock *sk);
sa_family_t sa_family;
struct list_head list;
};
@@ -515,6 +516,7 @@ struct sctp_pf {
int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
+ void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
struct sctp_af *af;
};
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 991a530..d726d21 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
struct list_head *pos, *temp;
struct sctp_chunk *chunk;
struct sctp_datamsg *msg;
+ struct sctp_sock *sp;
+ struct sctp_af *af;
int err;
msg = sctp_datamsg_new(GFP_KERNEL);
@@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
/* This is the biggest possible DATA chunk that can fit into
* the packet
*/
- max_data = asoc->pathmtu -
- sctp_sk(asoc->base.sk)->pf->af->net_header_len -
- sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
+ sp = sctp_sk(asoc->base.sk);
+ af = sp->pf->af;
+ max_data = asoc->pathmtu - af->net_header_len -
+ sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
+ af->ip_options_len(asoc->base.sk);
max_data = SCTP_TRUNC4(max_data);
/* If the the peer requested that we authenticate DATA chunks
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index e35d4f7..30a05a8 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
rcu_read_unlock();
}
+/* Copy over any ip options */
+static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
+{
+ struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
+ struct ipv6_txoptions *opt;
+
+ newnp = inet6_sk(newsk);
+
+ rcu_read_lock();
+ opt = rcu_dereference(np->opt);
+ if (opt) {
+ opt = ipv6_dup_options(newsk, opt);
+ if (!opt)
+ pr_err("%s: Failed to copy ip options\n", __func__);
+ }
+ RCU_INIT_POINTER(newnp->opt, opt);
+ rcu_read_unlock();
+}
+
+/* Account for the IP options */
+static int sctp_v6_ip_options_len(struct sock *sk)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_txoptions *opt;
+ int len = 0;
+
+ rcu_read_lock();
+ opt = rcu_dereference(np->opt);
+ if (opt)
+ len = opt->opt_flen + opt->opt_nflen;
+
+ rcu_read_unlock();
+ return len;
+}
+
/* Initialize a sockaddr_storage from in incoming skb. */
static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
int is_saddr)
@@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
struct sock *newsk;
struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct sctp6_sock *newsctp6sk;
- struct ipv6_txoptions *opt;
newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
if (!newsk)
@@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
newnp->ipv6_ac_list = NULL;
newnp->ipv6_fl_list = NULL;
- rcu_read_lock();
- opt = rcu_dereference(np->opt);
- if (opt)
- opt = ipv6_dup_options(newsk, opt);
- RCU_INIT_POINTER(newnp->opt, opt);
- rcu_read_unlock();
+ sctp_v6_copy_ip_options(sk, newsk);
/* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
* and getpeername().
@@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
.ecn_capable = sctp_v6_ecn_capable,
.net_header_len = sizeof(struct ipv6hdr),
.sockaddr_len = sizeof(struct sockaddr_in6),
+ .ip_options_len = sctp_v6_ip_options_len,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
@@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
.addr_to_user = sctp_v6_addr_to_user,
.to_sk_saddr = sctp_v6_to_sk_saddr,
.to_sk_daddr = sctp_v6_to_sk_daddr,
+ .copy_ip_options = sctp_v6_copy_ip_options,
.af = &sctp_af_inet6,
};
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 01a26ee..a58d13c 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
static void sctp_packet_reset(struct sctp_packet *packet)
{
+ /* sctp_packet_transmit() relies on this to reset size to the
+ * current overhead after sending packets.
+ */
packet->size = packet->overhead;
+
packet->has_cookie_echo = 0;
packet->has_sack = 0;
packet->has_data = 0;
@@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
struct sctp_transport *tp = packet->transport;
struct sctp_association *asoc = tp->asoc;
struct sock *sk;
+ size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
packet->vtag = vtag;
@@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
if (!sctp_packet_empty(packet))
return;
- /* set packet max_size with pathmtu */
+ /* set packet max_size with pathmtu, then calculate overhead */
packet->max_size = tp->pathmtu;
- if (!asoc)
+ if (asoc) {
+ struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
+
+ overhead = af->net_header_len +
+ af->ip_options_len(asoc->base.sk);
+ overhead += sizeof(struct sctphdr);
+ packet->overhead = overhead;
+ packet->size = overhead;
+ } else {
+ packet->overhead = overhead;
+ packet->size = overhead;
return;
+ }
/* update dst or transport pathmtu if in need */
sk = asoc->base.sk;
@@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
struct sctp_transport *transport,
__u16 sport, __u16 dport)
{
- struct sctp_association *asoc = transport->asoc;
- size_t overhead;
-
pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
packet->transport = transport;
packet->source_port = sport;
packet->destination_port = dport;
INIT_LIST_HEAD(&packet->chunk_list);
- if (asoc) {
- struct sctp_sock *sp = sctp_sk(asoc->base.sk);
- overhead = sp->pf->af->net_header_len;
- } else {
- overhead = sizeof(struct ipv6hdr);
- }
- overhead += sizeof(struct sctphdr);
- packet->overhead = overhead;
+ /* The overhead will be calculated by sctp_packet_config() */
+ packet->overhead = 0;
sctp_packet_reset(packet);
packet->vtag = 0;
}
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 91813e6..01c4d77 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
return error;
}
+/* Copy over any ip options */
+static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
+{
+ struct inet_sock *newinet, *inet = inet_sk(sk);
+ struct ip_options_rcu *inet_opt, *newopt = NULL;
+
+ newinet = inet_sk(newsk);
+
+ rcu_read_lock();
+ inet_opt = rcu_dereference(inet->inet_opt);
+ if (inet_opt) {
+ newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
+ inet_opt->opt.optlen, GFP_ATOMIC);
+ if (newopt)
+ memcpy(newopt, inet_opt, sizeof(*inet_opt) +
+ inet_opt->opt.optlen);
+ else
+ pr_err("%s: Failed to copy ip options\n", __func__);
+ }
+ RCU_INIT_POINTER(newinet->inet_opt, newopt);
+ rcu_read_unlock();
+}
+
+/* Account for the IP options */
+static int sctp_v4_ip_options_len(struct sock *sk)
+{
+ struct inet_sock *inet = inet_sk(sk);
+
+ if (inet->inet_opt)
+ return inet->inet_opt->opt.optlen;
+ else
+ return 0;
+}
+
/* Initialize a sctp_addr from in incoming skb. */
static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
int is_saddr)
@@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
sctp_copy_sock(newsk, sk, asoc);
sock_reset_flag(newsk, SOCK_ZAPPED);
+ sctp_v4_copy_ip_options(sk, newsk);
+
newinet = inet_sk(newsk);
newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
@@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
.addr_to_user = sctp_v4_addr_to_user,
.to_sk_saddr = sctp_v4_to_sk_saddr,
.to_sk_daddr = sctp_v4_to_sk_daddr,
+ .copy_ip_options = sctp_v4_copy_ip_options,
.af = &sctp_af_inet
};
@@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
.ecn_capable = sctp_v4_ecn_capable,
.net_header_len = sizeof(struct iphdr),
.sockaddr_len = sizeof(struct sockaddr_in),
+ .ip_options_len = sctp_v4_ip_options_len,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ip_setsockopt,
.compat_getsockopt = compat_ip_getsockopt,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index bf271f8..eb55c63 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
{
struct sctp_sock *sp = sctp_sk(sk);
+ struct sctp_af *af = sp->pf->af;
struct sctp_assoc_value params;
struct sctp_association *asoc;
int val;
@@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
if (val) {
int min_len, max_len;
- min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
+ min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
+ min_len -= af->ip_options_len(sk);
min_len -= sizeof(struct sctphdr) +
sizeof(struct sctp_data_chunk);
@@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
asoc = sctp_id2assoc(sk, params.assoc_id);
if (asoc) {
if (val == 0) {
- val = asoc->pathmtu - sp->pf->af->net_header_len;
+ val = asoc->pathmtu - af->net_header_len;
+ val -= af->ip_options_len(sk);
val -= sizeof(struct sctphdr) +
sctp_datachk_len(&asoc->stream);
}
@@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
sctp_copy_sock(sock->sk, sk, asoc);
/* Make peeled-off sockets more like 1-1 accepted sockets.
- * Set the daddr and initialize id to something more random
+ * Set the daddr and initialize id to something more random and also
+ * copy over any ip options.
*/
sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
+ sp->pf->copy_ip_options(sk, sock->sk);
/* Populate the fields of the newsk from the oldsk and migrate the
* asoc to the newsk.
--
2.14.3
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-20 19:15 ` Richard Haines
0 siblings, 0 replies; 32+ messages in thread
From: Richard Haines @ 2018-02-20 19:15 UTC (permalink / raw)
To: linux-security-module
Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
and CALIPSO/IPv6 services.
Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
---
All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
pass.
V7 Changes:
1) Log when copy ip options fail for IPv4 and IPv6
2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
func_tests do not test with struct sctp_assoc_value. Just used simple test
and okay.
3) Move calculation of overheads to sctp_packet_config().
NOTE: Initially in sctp_packet_reset() I set packet->size and
packet->overhead to zero (as it is a reset). This was okay for all the
lksctp-tools function tests, however when running "sctp-tests" ndatshched
tests it causes these to fail with an st_s.log entry of:
sid: 3, expected: 3
sid: 3, expected: 3
unexpected sid packet !!!
sid: 1, expected: 3
I then found sctp_packet_transmit() relies on setting
"packet->size = packet->overhead;" to reset size to the current overhead
after sending packets, hence the comment in sctp_packet_reset()
include/net/sctp/sctp.h | 4 +++-
include/net/sctp/structs.h | 2 ++
net/sctp/chunk.c | 10 +++++++---
net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
net/sctp/output.c | 34 +++++++++++++++++++++-------------
net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
net/sctp/socket.c | 11 ++++++++---
7 files changed, 117 insertions(+), 27 deletions(-)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index f7ae6b0..25c5c87 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
{
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
int frag = pmtu;
- frag -= sp->pf->af->net_header_len;
+ frag -= af->ip_options_len(asoc->base.sk);
+ frag -= af->net_header_len;
frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
if (asoc->user_frag)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 03e92dd..ead5fce 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -491,6 +491,7 @@ struct sctp_af {
void (*ecn_capable)(struct sock *sk);
__u16 net_header_len;
int sockaddr_len;
+ int (*ip_options_len)(struct sock *sk);
sa_family_t sa_family;
struct list_head list;
};
@@ -515,6 +516,7 @@ struct sctp_pf {
int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
+ void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
struct sctp_af *af;
};
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 991a530..d726d21 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
struct list_head *pos, *temp;
struct sctp_chunk *chunk;
struct sctp_datamsg *msg;
+ struct sctp_sock *sp;
+ struct sctp_af *af;
int err;
msg = sctp_datamsg_new(GFP_KERNEL);
@@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
/* This is the biggest possible DATA chunk that can fit into
* the packet
*/
- max_data = asoc->pathmtu -
- sctp_sk(asoc->base.sk)->pf->af->net_header_len -
- sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
+ sp = sctp_sk(asoc->base.sk);
+ af = sp->pf->af;
+ max_data = asoc->pathmtu - af->net_header_len -
+ sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
+ af->ip_options_len(asoc->base.sk);
max_data = SCTP_TRUNC4(max_data);
/* If the the peer requested that we authenticate DATA chunks
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index e35d4f7..30a05a8 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
rcu_read_unlock();
}
+/* Copy over any ip options */
+static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
+{
+ struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
+ struct ipv6_txoptions *opt;
+
+ newnp = inet6_sk(newsk);
+
+ rcu_read_lock();
+ opt = rcu_dereference(np->opt);
+ if (opt) {
+ opt = ipv6_dup_options(newsk, opt);
+ if (!opt)
+ pr_err("%s: Failed to copy ip options\n", __func__);
+ }
+ RCU_INIT_POINTER(newnp->opt, opt);
+ rcu_read_unlock();
+}
+
+/* Account for the IP options */
+static int sctp_v6_ip_options_len(struct sock *sk)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_txoptions *opt;
+ int len = 0;
+
+ rcu_read_lock();
+ opt = rcu_dereference(np->opt);
+ if (opt)
+ len = opt->opt_flen + opt->opt_nflen;
+
+ rcu_read_unlock();
+ return len;
+}
+
/* Initialize a sockaddr_storage from in incoming skb. */
static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
int is_saddr)
@@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
struct sock *newsk;
struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct sctp6_sock *newsctp6sk;
- struct ipv6_txoptions *opt;
newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
if (!newsk)
@@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
newnp->ipv6_ac_list = NULL;
newnp->ipv6_fl_list = NULL;
- rcu_read_lock();
- opt = rcu_dereference(np->opt);
- if (opt)
- opt = ipv6_dup_options(newsk, opt);
- RCU_INIT_POINTER(newnp->opt, opt);
- rcu_read_unlock();
+ sctp_v6_copy_ip_options(sk, newsk);
/* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
* and getpeername().
@@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
.ecn_capable = sctp_v6_ecn_capable,
.net_header_len = sizeof(struct ipv6hdr),
.sockaddr_len = sizeof(struct sockaddr_in6),
+ .ip_options_len = sctp_v6_ip_options_len,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
@@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
.addr_to_user = sctp_v6_addr_to_user,
.to_sk_saddr = sctp_v6_to_sk_saddr,
.to_sk_daddr = sctp_v6_to_sk_daddr,
+ .copy_ip_options = sctp_v6_copy_ip_options,
.af = &sctp_af_inet6,
};
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 01a26ee..a58d13c 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
static void sctp_packet_reset(struct sctp_packet *packet)
{
+ /* sctp_packet_transmit() relies on this to reset size to the
+ * current overhead after sending packets.
+ */
packet->size = packet->overhead;
+
packet->has_cookie_echo = 0;
packet->has_sack = 0;
packet->has_data = 0;
@@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
struct sctp_transport *tp = packet->transport;
struct sctp_association *asoc = tp->asoc;
struct sock *sk;
+ size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
packet->vtag = vtag;
@@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
if (!sctp_packet_empty(packet))
return;
- /* set packet max_size with pathmtu */
+ /* set packet max_size with pathmtu, then calculate overhead */
packet->max_size = tp->pathmtu;
- if (!asoc)
+ if (asoc) {
+ struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
+
+ overhead = af->net_header_len +
+ af->ip_options_len(asoc->base.sk);
+ overhead += sizeof(struct sctphdr);
+ packet->overhead = overhead;
+ packet->size = overhead;
+ } else {
+ packet->overhead = overhead;
+ packet->size = overhead;
return;
+ }
/* update dst or transport pathmtu if in need */
sk = asoc->base.sk;
@@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
struct sctp_transport *transport,
__u16 sport, __u16 dport)
{
- struct sctp_association *asoc = transport->asoc;
- size_t overhead;
-
pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
packet->transport = transport;
packet->source_port = sport;
packet->destination_port = dport;
INIT_LIST_HEAD(&packet->chunk_list);
- if (asoc) {
- struct sctp_sock *sp = sctp_sk(asoc->base.sk);
- overhead = sp->pf->af->net_header_len;
- } else {
- overhead = sizeof(struct ipv6hdr);
- }
- overhead += sizeof(struct sctphdr);
- packet->overhead = overhead;
+ /* The overhead will be calculated by sctp_packet_config() */
+ packet->overhead = 0;
sctp_packet_reset(packet);
packet->vtag = 0;
}
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 91813e6..01c4d77 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
return error;
}
+/* Copy over any ip options */
+static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
+{
+ struct inet_sock *newinet, *inet = inet_sk(sk);
+ struct ip_options_rcu *inet_opt, *newopt = NULL;
+
+ newinet = inet_sk(newsk);
+
+ rcu_read_lock();
+ inet_opt = rcu_dereference(inet->inet_opt);
+ if (inet_opt) {
+ newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
+ inet_opt->opt.optlen, GFP_ATOMIC);
+ if (newopt)
+ memcpy(newopt, inet_opt, sizeof(*inet_opt) +
+ inet_opt->opt.optlen);
+ else
+ pr_err("%s: Failed to copy ip options\n", __func__);
+ }
+ RCU_INIT_POINTER(newinet->inet_opt, newopt);
+ rcu_read_unlock();
+}
+
+/* Account for the IP options */
+static int sctp_v4_ip_options_len(struct sock *sk)
+{
+ struct inet_sock *inet = inet_sk(sk);
+
+ if (inet->inet_opt)
+ return inet->inet_opt->opt.optlen;
+ else
+ return 0;
+}
+
/* Initialize a sctp_addr from in incoming skb. */
static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
int is_saddr)
@@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
sctp_copy_sock(newsk, sk, asoc);
sock_reset_flag(newsk, SOCK_ZAPPED);
+ sctp_v4_copy_ip_options(sk, newsk);
+
newinet = inet_sk(newsk);
newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
@@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
.addr_to_user = sctp_v4_addr_to_user,
.to_sk_saddr = sctp_v4_to_sk_saddr,
.to_sk_daddr = sctp_v4_to_sk_daddr,
+ .copy_ip_options = sctp_v4_copy_ip_options,
.af = &sctp_af_inet
};
@@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
.ecn_capable = sctp_v4_ecn_capable,
.net_header_len = sizeof(struct iphdr),
.sockaddr_len = sizeof(struct sockaddr_in),
+ .ip_options_len = sctp_v4_ip_options_len,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ip_setsockopt,
.compat_getsockopt = compat_ip_getsockopt,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index bf271f8..eb55c63 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
{
struct sctp_sock *sp = sctp_sk(sk);
+ struct sctp_af *af = sp->pf->af;
struct sctp_assoc_value params;
struct sctp_association *asoc;
int val;
@@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
if (val) {
int min_len, max_len;
- min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
+ min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
+ min_len -= af->ip_options_len(sk);
min_len -= sizeof(struct sctphdr) +
sizeof(struct sctp_data_chunk);
@@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
asoc = sctp_id2assoc(sk, params.assoc_id);
if (asoc) {
if (val = 0) {
- val = asoc->pathmtu - sp->pf->af->net_header_len;
+ val = asoc->pathmtu - af->net_header_len;
+ val -= af->ip_options_len(sk);
val -= sizeof(struct sctphdr) +
sctp_datachk_len(&asoc->stream);
}
@@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
sctp_copy_sock(sock->sk, sk, asoc);
/* Make peeled-off sockets more like 1-1 accepted sockets.
- * Set the daddr and initialize id to something more random
+ * Set the daddr and initialize id to something more random and also
+ * copy over any ip options.
*/
sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
+ sp->pf->copy_ip_options(sk, sock->sk);
/* Populate the fields of the newsk from the oldsk and migrate the
* asoc to the newsk.
--
2.14.3
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-20 19:15 ` Richard Haines
0 siblings, 0 replies; 32+ messages in thread
From: Richard Haines @ 2018-02-20 19:15 UTC (permalink / raw)
To: selinux, netdev, linux-sctp, linux-security-module
Cc: paul, vyasevich, nhorman, sds, eparis, marcelo.leitner, casey,
jmorris, Richard Haines
Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
and CALIPSO/IPv6 services.
Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
---
All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
pass.
V7 Changes:
1) Log when copy ip options fail for IPv4 and IPv6
2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
func_tests do not test with struct sctp_assoc_value. Just used simple test
and okay.
3) Move calculation of overheads to sctp_packet_config().
NOTE: Initially in sctp_packet_reset() I set packet->size and
packet->overhead to zero (as it is a reset). This was okay for all the
lksctp-tools function tests, however when running "sctp-tests" ndatshched
tests it causes these to fail with an st_s.log entry of:
sid: 3, expected: 3
sid: 3, expected: 3
unexpected sid packet !!!
sid: 1, expected: 3
I then found sctp_packet_transmit() relies on setting
"packet->size = packet->overhead;" to reset size to the current overhead
after sending packets, hence the comment in sctp_packet_reset()
include/net/sctp/sctp.h | 4 +++-
include/net/sctp/structs.h | 2 ++
net/sctp/chunk.c | 10 +++++++---
net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
net/sctp/output.c | 34 +++++++++++++++++++++-------------
net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
net/sctp/socket.c | 11 ++++++++---
7 files changed, 117 insertions(+), 27 deletions(-)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index f7ae6b0..25c5c87 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
{
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
int frag = pmtu;
- frag -= sp->pf->af->net_header_len;
+ frag -= af->ip_options_len(asoc->base.sk);
+ frag -= af->net_header_len;
frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
if (asoc->user_frag)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 03e92dd..ead5fce 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -491,6 +491,7 @@ struct sctp_af {
void (*ecn_capable)(struct sock *sk);
__u16 net_header_len;
int sockaddr_len;
+ int (*ip_options_len)(struct sock *sk);
sa_family_t sa_family;
struct list_head list;
};
@@ -515,6 +516,7 @@ struct sctp_pf {
int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
+ void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
struct sctp_af *af;
};
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 991a530..d726d21 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
struct list_head *pos, *temp;
struct sctp_chunk *chunk;
struct sctp_datamsg *msg;
+ struct sctp_sock *sp;
+ struct sctp_af *af;
int err;
msg = sctp_datamsg_new(GFP_KERNEL);
@@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
/* This is the biggest possible DATA chunk that can fit into
* the packet
*/
- max_data = asoc->pathmtu -
- sctp_sk(asoc->base.sk)->pf->af->net_header_len -
- sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
+ sp = sctp_sk(asoc->base.sk);
+ af = sp->pf->af;
+ max_data = asoc->pathmtu - af->net_header_len -
+ sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
+ af->ip_options_len(asoc->base.sk);
max_data = SCTP_TRUNC4(max_data);
/* If the the peer requested that we authenticate DATA chunks
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index e35d4f7..30a05a8 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
rcu_read_unlock();
}
+/* Copy over any ip options */
+static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
+{
+ struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
+ struct ipv6_txoptions *opt;
+
+ newnp = inet6_sk(newsk);
+
+ rcu_read_lock();
+ opt = rcu_dereference(np->opt);
+ if (opt) {
+ opt = ipv6_dup_options(newsk, opt);
+ if (!opt)
+ pr_err("%s: Failed to copy ip options\n", __func__);
+ }
+ RCU_INIT_POINTER(newnp->opt, opt);
+ rcu_read_unlock();
+}
+
+/* Account for the IP options */
+static int sctp_v6_ip_options_len(struct sock *sk)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_txoptions *opt;
+ int len = 0;
+
+ rcu_read_lock();
+ opt = rcu_dereference(np->opt);
+ if (opt)
+ len = opt->opt_flen + opt->opt_nflen;
+
+ rcu_read_unlock();
+ return len;
+}
+
/* Initialize a sockaddr_storage from in incoming skb. */
static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
int is_saddr)
@@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
struct sock *newsk;
struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct sctp6_sock *newsctp6sk;
- struct ipv6_txoptions *opt;
newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
if (!newsk)
@@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
newnp->ipv6_ac_list = NULL;
newnp->ipv6_fl_list = NULL;
- rcu_read_lock();
- opt = rcu_dereference(np->opt);
- if (opt)
- opt = ipv6_dup_options(newsk, opt);
- RCU_INIT_POINTER(newnp->opt, opt);
- rcu_read_unlock();
+ sctp_v6_copy_ip_options(sk, newsk);
/* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
* and getpeername().
@@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
.ecn_capable = sctp_v6_ecn_capable,
.net_header_len = sizeof(struct ipv6hdr),
.sockaddr_len = sizeof(struct sockaddr_in6),
+ .ip_options_len = sctp_v6_ip_options_len,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
@@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
.addr_to_user = sctp_v6_addr_to_user,
.to_sk_saddr = sctp_v6_to_sk_saddr,
.to_sk_daddr = sctp_v6_to_sk_daddr,
+ .copy_ip_options = sctp_v6_copy_ip_options,
.af = &sctp_af_inet6,
};
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 01a26ee..a58d13c 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
static void sctp_packet_reset(struct sctp_packet *packet)
{
+ /* sctp_packet_transmit() relies on this to reset size to the
+ * current overhead after sending packets.
+ */
packet->size = packet->overhead;
+
packet->has_cookie_echo = 0;
packet->has_sack = 0;
packet->has_data = 0;
@@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
struct sctp_transport *tp = packet->transport;
struct sctp_association *asoc = tp->asoc;
struct sock *sk;
+ size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
packet->vtag = vtag;
@@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
if (!sctp_packet_empty(packet))
return;
- /* set packet max_size with pathmtu */
+ /* set packet max_size with pathmtu, then calculate overhead */
packet->max_size = tp->pathmtu;
- if (!asoc)
+ if (asoc) {
+ struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
+
+ overhead = af->net_header_len +
+ af->ip_options_len(asoc->base.sk);
+ overhead += sizeof(struct sctphdr);
+ packet->overhead = overhead;
+ packet->size = overhead;
+ } else {
+ packet->overhead = overhead;
+ packet->size = overhead;
return;
+ }
/* update dst or transport pathmtu if in need */
sk = asoc->base.sk;
@@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
struct sctp_transport *transport,
__u16 sport, __u16 dport)
{
- struct sctp_association *asoc = transport->asoc;
- size_t overhead;
-
pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
packet->transport = transport;
packet->source_port = sport;
packet->destination_port = dport;
INIT_LIST_HEAD(&packet->chunk_list);
- if (asoc) {
- struct sctp_sock *sp = sctp_sk(asoc->base.sk);
- overhead = sp->pf->af->net_header_len;
- } else {
- overhead = sizeof(struct ipv6hdr);
- }
- overhead += sizeof(struct sctphdr);
- packet->overhead = overhead;
+ /* The overhead will be calculated by sctp_packet_config() */
+ packet->overhead = 0;
sctp_packet_reset(packet);
packet->vtag = 0;
}
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 91813e6..01c4d77 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
return error;
}
+/* Copy over any ip options */
+static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
+{
+ struct inet_sock *newinet, *inet = inet_sk(sk);
+ struct ip_options_rcu *inet_opt, *newopt = NULL;
+
+ newinet = inet_sk(newsk);
+
+ rcu_read_lock();
+ inet_opt = rcu_dereference(inet->inet_opt);
+ if (inet_opt) {
+ newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
+ inet_opt->opt.optlen, GFP_ATOMIC);
+ if (newopt)
+ memcpy(newopt, inet_opt, sizeof(*inet_opt) +
+ inet_opt->opt.optlen);
+ else
+ pr_err("%s: Failed to copy ip options\n", __func__);
+ }
+ RCU_INIT_POINTER(newinet->inet_opt, newopt);
+ rcu_read_unlock();
+}
+
+/* Account for the IP options */
+static int sctp_v4_ip_options_len(struct sock *sk)
+{
+ struct inet_sock *inet = inet_sk(sk);
+
+ if (inet->inet_opt)
+ return inet->inet_opt->opt.optlen;
+ else
+ return 0;
+}
+
/* Initialize a sctp_addr from in incoming skb. */
static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
int is_saddr)
@@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
sctp_copy_sock(newsk, sk, asoc);
sock_reset_flag(newsk, SOCK_ZAPPED);
+ sctp_v4_copy_ip_options(sk, newsk);
+
newinet = inet_sk(newsk);
newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
@@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
.addr_to_user = sctp_v4_addr_to_user,
.to_sk_saddr = sctp_v4_to_sk_saddr,
.to_sk_daddr = sctp_v4_to_sk_daddr,
+ .copy_ip_options = sctp_v4_copy_ip_options,
.af = &sctp_af_inet
};
@@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
.ecn_capable = sctp_v4_ecn_capable,
.net_header_len = sizeof(struct iphdr),
.sockaddr_len = sizeof(struct sockaddr_in),
+ .ip_options_len = sctp_v4_ip_options_len,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ip_setsockopt,
.compat_getsockopt = compat_ip_getsockopt,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index bf271f8..eb55c63 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
{
struct sctp_sock *sp = sctp_sk(sk);
+ struct sctp_af *af = sp->pf->af;
struct sctp_assoc_value params;
struct sctp_association *asoc;
int val;
@@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
if (val) {
int min_len, max_len;
- min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
+ min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
+ min_len -= af->ip_options_len(sk);
min_len -= sizeof(struct sctphdr) +
sizeof(struct sctp_data_chunk);
@@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
asoc = sctp_id2assoc(sk, params.assoc_id);
if (asoc) {
if (val == 0) {
- val = asoc->pathmtu - sp->pf->af->net_header_len;
+ val = asoc->pathmtu - af->net_header_len;
+ val -= af->ip_options_len(sk);
val -= sizeof(struct sctphdr) +
sctp_datachk_len(&asoc->stream);
}
@@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
sctp_copy_sock(sock->sk, sk, asoc);
/* Make peeled-off sockets more like 1-1 accepted sockets.
- * Set the daddr and initialize id to something more random
+ * Set the daddr and initialize id to something more random and also
+ * copy over any ip options.
*/
sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
+ sp->pf->copy_ip_options(sk, sock->sk);
/* Populate the fields of the newsk from the oldsk and migrate the
* asoc to the newsk.
--
2.14.3
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-20 19:15 ` Richard Haines
0 siblings, 0 replies; 32+ messages in thread
From: Richard Haines @ 2018-02-20 19:15 UTC (permalink / raw)
To: linux-security-module
Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
and CALIPSO/IPv6 services.
Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
---
All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
pass.
V7 Changes:
1) Log when copy ip options fail for IPv4 and IPv6
2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
func_tests do not test with struct sctp_assoc_value. Just used simple test
and okay.
3) Move calculation of overheads to sctp_packet_config().
NOTE: Initially in sctp_packet_reset() I set packet->size and
packet->overhead to zero (as it is a reset). This was okay for all the
lksctp-tools function tests, however when running "sctp-tests" ndatshched
tests it causes these to fail with an st_s.log entry of:
sid: 3, expected: 3
sid: 3, expected: 3
unexpected sid packet !!!
sid: 1, expected: 3
I then found sctp_packet_transmit() relies on setting
"packet->size = packet->overhead;" to reset size to the current overhead
after sending packets, hence the comment in sctp_packet_reset()
include/net/sctp/sctp.h | 4 +++-
include/net/sctp/structs.h | 2 ++
net/sctp/chunk.c | 10 +++++++---
net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
net/sctp/output.c | 34 +++++++++++++++++++++-------------
net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
net/sctp/socket.c | 11 ++++++++---
7 files changed, 117 insertions(+), 27 deletions(-)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index f7ae6b0..25c5c87 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
{
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
int frag = pmtu;
- frag -= sp->pf->af->net_header_len;
+ frag -= af->ip_options_len(asoc->base.sk);
+ frag -= af->net_header_len;
frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
if (asoc->user_frag)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 03e92dd..ead5fce 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -491,6 +491,7 @@ struct sctp_af {
void (*ecn_capable)(struct sock *sk);
__u16 net_header_len;
int sockaddr_len;
+ int (*ip_options_len)(struct sock *sk);
sa_family_t sa_family;
struct list_head list;
};
@@ -515,6 +516,7 @@ struct sctp_pf {
int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
+ void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
struct sctp_af *af;
};
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 991a530..d726d21 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
struct list_head *pos, *temp;
struct sctp_chunk *chunk;
struct sctp_datamsg *msg;
+ struct sctp_sock *sp;
+ struct sctp_af *af;
int err;
msg = sctp_datamsg_new(GFP_KERNEL);
@@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
/* This is the biggest possible DATA chunk that can fit into
* the packet
*/
- max_data = asoc->pathmtu -
- sctp_sk(asoc->base.sk)->pf->af->net_header_len -
- sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
+ sp = sctp_sk(asoc->base.sk);
+ af = sp->pf->af;
+ max_data = asoc->pathmtu - af->net_header_len -
+ sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
+ af->ip_options_len(asoc->base.sk);
max_data = SCTP_TRUNC4(max_data);
/* If the the peer requested that we authenticate DATA chunks
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index e35d4f7..30a05a8 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
rcu_read_unlock();
}
+/* Copy over any ip options */
+static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
+{
+ struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
+ struct ipv6_txoptions *opt;
+
+ newnp = inet6_sk(newsk);
+
+ rcu_read_lock();
+ opt = rcu_dereference(np->opt);
+ if (opt) {
+ opt = ipv6_dup_options(newsk, opt);
+ if (!opt)
+ pr_err("%s: Failed to copy ip options\n", __func__);
+ }
+ RCU_INIT_POINTER(newnp->opt, opt);
+ rcu_read_unlock();
+}
+
+/* Account for the IP options */
+static int sctp_v6_ip_options_len(struct sock *sk)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_txoptions *opt;
+ int len = 0;
+
+ rcu_read_lock();
+ opt = rcu_dereference(np->opt);
+ if (opt)
+ len = opt->opt_flen + opt->opt_nflen;
+
+ rcu_read_unlock();
+ return len;
+}
+
/* Initialize a sockaddr_storage from in incoming skb. */
static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
int is_saddr)
@@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
struct sock *newsk;
struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct sctp6_sock *newsctp6sk;
- struct ipv6_txoptions *opt;
newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
if (!newsk)
@@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
newnp->ipv6_ac_list = NULL;
newnp->ipv6_fl_list = NULL;
- rcu_read_lock();
- opt = rcu_dereference(np->opt);
- if (opt)
- opt = ipv6_dup_options(newsk, opt);
- RCU_INIT_POINTER(newnp->opt, opt);
- rcu_read_unlock();
+ sctp_v6_copy_ip_options(sk, newsk);
/* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
* and getpeername().
@@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
.ecn_capable = sctp_v6_ecn_capable,
.net_header_len = sizeof(struct ipv6hdr),
.sockaddr_len = sizeof(struct sockaddr_in6),
+ .ip_options_len = sctp_v6_ip_options_len,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
@@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
.addr_to_user = sctp_v6_addr_to_user,
.to_sk_saddr = sctp_v6_to_sk_saddr,
.to_sk_daddr = sctp_v6_to_sk_daddr,
+ .copy_ip_options = sctp_v6_copy_ip_options,
.af = &sctp_af_inet6,
};
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 01a26ee..a58d13c 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
static void sctp_packet_reset(struct sctp_packet *packet)
{
+ /* sctp_packet_transmit() relies on this to reset size to the
+ * current overhead after sending packets.
+ */
packet->size = packet->overhead;
+
packet->has_cookie_echo = 0;
packet->has_sack = 0;
packet->has_data = 0;
@@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
struct sctp_transport *tp = packet->transport;
struct sctp_association *asoc = tp->asoc;
struct sock *sk;
+ size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
packet->vtag = vtag;
@@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
if (!sctp_packet_empty(packet))
return;
- /* set packet max_size with pathmtu */
+ /* set packet max_size with pathmtu, then calculate overhead */
packet->max_size = tp->pathmtu;
- if (!asoc)
+ if (asoc) {
+ struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
+
+ overhead = af->net_header_len +
+ af->ip_options_len(asoc->base.sk);
+ overhead += sizeof(struct sctphdr);
+ packet->overhead = overhead;
+ packet->size = overhead;
+ } else {
+ packet->overhead = overhead;
+ packet->size = overhead;
return;
+ }
/* update dst or transport pathmtu if in need */
sk = asoc->base.sk;
@@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
struct sctp_transport *transport,
__u16 sport, __u16 dport)
{
- struct sctp_association *asoc = transport->asoc;
- size_t overhead;
-
pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
packet->transport = transport;
packet->source_port = sport;
packet->destination_port = dport;
INIT_LIST_HEAD(&packet->chunk_list);
- if (asoc) {
- struct sctp_sock *sp = sctp_sk(asoc->base.sk);
- overhead = sp->pf->af->net_header_len;
- } else {
- overhead = sizeof(struct ipv6hdr);
- }
- overhead += sizeof(struct sctphdr);
- packet->overhead = overhead;
+ /* The overhead will be calculated by sctp_packet_config() */
+ packet->overhead = 0;
sctp_packet_reset(packet);
packet->vtag = 0;
}
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 91813e6..01c4d77 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
return error;
}
+/* Copy over any ip options */
+static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
+{
+ struct inet_sock *newinet, *inet = inet_sk(sk);
+ struct ip_options_rcu *inet_opt, *newopt = NULL;
+
+ newinet = inet_sk(newsk);
+
+ rcu_read_lock();
+ inet_opt = rcu_dereference(inet->inet_opt);
+ if (inet_opt) {
+ newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
+ inet_opt->opt.optlen, GFP_ATOMIC);
+ if (newopt)
+ memcpy(newopt, inet_opt, sizeof(*inet_opt) +
+ inet_opt->opt.optlen);
+ else
+ pr_err("%s: Failed to copy ip options\n", __func__);
+ }
+ RCU_INIT_POINTER(newinet->inet_opt, newopt);
+ rcu_read_unlock();
+}
+
+/* Account for the IP options */
+static int sctp_v4_ip_options_len(struct sock *sk)
+{
+ struct inet_sock *inet = inet_sk(sk);
+
+ if (inet->inet_opt)
+ return inet->inet_opt->opt.optlen;
+ else
+ return 0;
+}
+
/* Initialize a sctp_addr from in incoming skb. */
static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
int is_saddr)
@@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
sctp_copy_sock(newsk, sk, asoc);
sock_reset_flag(newsk, SOCK_ZAPPED);
+ sctp_v4_copy_ip_options(sk, newsk);
+
newinet = inet_sk(newsk);
newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
@@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
.addr_to_user = sctp_v4_addr_to_user,
.to_sk_saddr = sctp_v4_to_sk_saddr,
.to_sk_daddr = sctp_v4_to_sk_daddr,
+ .copy_ip_options = sctp_v4_copy_ip_options,
.af = &sctp_af_inet
};
@@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
.ecn_capable = sctp_v4_ecn_capable,
.net_header_len = sizeof(struct iphdr),
.sockaddr_len = sizeof(struct sockaddr_in),
+ .ip_options_len = sctp_v4_ip_options_len,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ip_setsockopt,
.compat_getsockopt = compat_ip_getsockopt,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index bf271f8..eb55c63 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
{
struct sctp_sock *sp = sctp_sk(sk);
+ struct sctp_af *af = sp->pf->af;
struct sctp_assoc_value params;
struct sctp_association *asoc;
int val;
@@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
if (val) {
int min_len, max_len;
- min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
+ min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
+ min_len -= af->ip_options_len(sk);
min_len -= sizeof(struct sctphdr) +
sizeof(struct sctp_data_chunk);
@@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
asoc = sctp_id2assoc(sk, params.assoc_id);
if (asoc) {
if (val == 0) {
- val = asoc->pathmtu - sp->pf->af->net_header_len;
+ val = asoc->pathmtu - af->net_header_len;
+ val -= af->ip_options_len(sk);
val -= sizeof(struct sctphdr) +
sctp_datachk_len(&asoc->stream);
}
@@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
sctp_copy_sock(sock->sk, sk, asoc);
/* Make peeled-off sockets more like 1-1 accepted sockets.
- * Set the daddr and initialize id to something more random
+ * Set the daddr and initialize id to something more random and also
+ * copy over any ip options.
*/
sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
+ sp->pf->copy_ip_options(sk, sock->sk);
/* Populate the fields of the newsk from the oldsk and migrate the
* asoc to the newsk.
--
2.14.3
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
2018-02-20 19:15 ` Richard Haines
(?)
(?)
@ 2018-02-21 3:44 ` Neil Horman
-1 siblings, 0 replies; 32+ messages in thread
From: Neil Horman @ 2018-02-21 3:44 UTC (permalink / raw)
To: Richard Haines
Cc: marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA, vyasevich-Re5JQEeQqe8AvxtiuMwx3w,
linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-sctp-u79uwXL29TY76Z2rM5mHXA,
selinux-+05T5uksL2qpZYMLLGbcSA, sds-+05T5uksL2qpZYMLLGbcSA
On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> and CALIPSO/IPv6 services.
>
> Signed-off-by: Richard Haines <richard_c_haines-FhtRXb7CoQBt1OO0OYaSVA@public.gmane.org>
> ---
> All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
> All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
> pass.
>
> V7 Changes:
> 1) Log when copy ip options fail for IPv4 and IPv6
> 2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
> func_tests do not test with struct sctp_assoc_value. Just used simple test
> and okay.
> 3) Move calculation of overheads to sctp_packet_config().
> NOTE: Initially in sctp_packet_reset() I set packet->size and
> packet->overhead to zero (as it is a reset). This was okay for all the
> lksctp-tools function tests, however when running "sctp-tests" ndatshched
> tests it causes these to fail with an st_s.log entry of:
> sid: 3, expected: 3
> sid: 3, expected: 3
> unexpected sid packet !!!
> sid: 1, expected: 3
>
> I then found sctp_packet_transmit() relies on setting
> "packet->size = packet->overhead;" to reset size to the current overhead
> after sending packets, hence the comment in sctp_packet_reset()
>
> include/net/sctp/sctp.h | 4 +++-
> include/net/sctp/structs.h | 2 ++
> net/sctp/chunk.c | 10 +++++++---
> net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
> net/sctp/output.c | 34 +++++++++++++++++++++-------------
> net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
> net/sctp/socket.c | 11 ++++++++---
> 7 files changed, 117 insertions(+), 27 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index f7ae6b0..25c5c87 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
> static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
> {
> struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> int frag = pmtu;
>
> - frag -= sp->pf->af->net_header_len;
> + frag -= af->ip_options_len(asoc->base.sk);
> + frag -= af->net_header_len;
> frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
>
> if (asoc->user_frag)
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 03e92dd..ead5fce 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -491,6 +491,7 @@ struct sctp_af {
> void (*ecn_capable)(struct sock *sk);
> __u16 net_header_len;
> int sockaddr_len;
> + int (*ip_options_len)(struct sock *sk);
> sa_family_t sa_family;
> struct list_head list;
> };
> @@ -515,6 +516,7 @@ struct sctp_pf {
> int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
> void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
> void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
> + void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
> struct sctp_af *af;
> };
>
> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
> index 991a530..d726d21 100644
> --- a/net/sctp/chunk.c
> +++ b/net/sctp/chunk.c
> @@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> struct list_head *pos, *temp;
> struct sctp_chunk *chunk;
> struct sctp_datamsg *msg;
> + struct sctp_sock *sp;
> + struct sctp_af *af;
> int err;
>
> msg = sctp_datamsg_new(GFP_KERNEL);
> @@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> /* This is the biggest possible DATA chunk that can fit into
> * the packet
> */
> - max_data = asoc->pathmtu -
> - sctp_sk(asoc->base.sk)->pf->af->net_header_len -
> - sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
> + sp = sctp_sk(asoc->base.sk);
> + af = sp->pf->af;
> + max_data = asoc->pathmtu - af->net_header_len -
> + sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
> + af->ip_options_len(asoc->base.sk);
> max_data = SCTP_TRUNC4(max_data);
>
> /* If the the peer requested that we authenticate DATA chunks
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index e35d4f7..30a05a8 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
> rcu_read_unlock();
> }
>
> +/* Copy over any ip options */
> +static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> +
> + newnp = inet6_sk(newsk);
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt) {
> + opt = ipv6_dup_options(newsk, opt);
> + if (!opt)
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newnp->opt, opt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v6_ip_options_len(struct sock *sk)
> +{
> + struct ipv6_pinfo *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> + int len = 0;
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt)
> + len = opt->opt_flen + opt->opt_nflen;
> +
> + rcu_read_unlock();
> + return len;
> +}
> +
> /* Initialize a sockaddr_storage from in incoming skb. */
> static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> struct sock *newsk;
> struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> struct sctp6_sock *newsctp6sk;
> - struct ipv6_txoptions *opt;
>
> newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
> if (!newsk)
> @@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> newnp->ipv6_ac_list = NULL;
> newnp->ipv6_fl_list = NULL;
>
> - rcu_read_lock();
> - opt = rcu_dereference(np->opt);
> - if (opt)
> - opt = ipv6_dup_options(newsk, opt);
> - RCU_INIT_POINTER(newnp->opt, opt);
> - rcu_read_unlock();
> + sctp_v6_copy_ip_options(sk, newsk);
>
> /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
> * and getpeername().
> @@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
> .ecn_capable = sctp_v6_ecn_capable,
> .net_header_len = sizeof(struct ipv6hdr),
> .sockaddr_len = sizeof(struct sockaddr_in6),
> + .ip_options_len = sctp_v6_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ipv6_setsockopt,
> .compat_getsockopt = compat_ipv6_getsockopt,
> @@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
> .addr_to_user = sctp_v6_addr_to_user,
> .to_sk_saddr = sctp_v6_to_sk_saddr,
> .to_sk_daddr = sctp_v6_to_sk_daddr,
> + .copy_ip_options = sctp_v6_copy_ip_options,
> .af = &sctp_af_inet6,
> };
>
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 01a26ee..a58d13c 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
>
> static void sctp_packet_reset(struct sctp_packet *packet)
> {
> + /* sctp_packet_transmit() relies on this to reset size to the
> + * current overhead after sending packets.
> + */
> packet->size = packet->overhead;
> +
> packet->has_cookie_echo = 0;
> packet->has_sack = 0;
> packet->has_data = 0;
> @@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> struct sctp_transport *tp = packet->transport;
> struct sctp_association *asoc = tp->asoc;
> struct sock *sk;
> + size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
>
> pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
> packet->vtag = vtag;
> @@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> if (!sctp_packet_empty(packet))
> return;
>
> - /* set packet max_size with pathmtu */
> + /* set packet max_size with pathmtu, then calculate overhead */
> packet->max_size = tp->pathmtu;
> - if (!asoc)
> + if (asoc) {
> + struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> +
> + overhead = af->net_header_len +
> + af->ip_options_len(asoc->base.sk);
> + overhead += sizeof(struct sctphdr);
> + packet->overhead = overhead;
> + packet->size = overhead;
> + } else {
> + packet->overhead = overhead;
> + packet->size = overhead;
> return;
> + }
>
> /* update dst or transport pathmtu if in need */
> sk = asoc->base.sk;
> @@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
> struct sctp_transport *transport,
> __u16 sport, __u16 dport)
> {
> - struct sctp_association *asoc = transport->asoc;
> - size_t overhead;
> -
> pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
>
> packet->transport = transport;
> packet->source_port = sport;
> packet->destination_port = dport;
> INIT_LIST_HEAD(&packet->chunk_list);
> - if (asoc) {
> - struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> - overhead = sp->pf->af->net_header_len;
> - } else {
> - overhead = sizeof(struct ipv6hdr);
> - }
> - overhead += sizeof(struct sctphdr);
> - packet->overhead = overhead;
> + /* The overhead will be calculated by sctp_packet_config() */
> + packet->overhead = 0;
> sctp_packet_reset(packet);
> packet->vtag = 0;
> }
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 91813e6..01c4d77 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
> return error;
> }
>
> +/* Copy over any ip options */
> +static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct inet_sock *newinet, *inet = inet_sk(sk);
> + struct ip_options_rcu *inet_opt, *newopt = NULL;
> +
> + newinet = inet_sk(newsk);
> +
> + rcu_read_lock();
> + inet_opt = rcu_dereference(inet->inet_opt);
> + if (inet_opt) {
> + newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
> + inet_opt->opt.optlen, GFP_ATOMIC);
> + if (newopt)
> + memcpy(newopt, inet_opt, sizeof(*inet_opt) +
> + inet_opt->opt.optlen);
> + else
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newinet->inet_opt, newopt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v4_ip_options_len(struct sock *sk)
> +{
> + struct inet_sock *inet = inet_sk(sk);
> +
> + if (inet->inet_opt)
> + return inet->inet_opt->opt.optlen;
> + else
> + return 0;
> +}
> +
> /* Initialize a sctp_addr from in incoming skb. */
> static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
> sctp_copy_sock(newsk, sk, asoc);
> sock_reset_flag(newsk, SOCK_ZAPPED);
>
> + sctp_v4_copy_ip_options(sk, newsk);
> +
> newinet = inet_sk(newsk);
>
> newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
> @@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
> .addr_to_user = sctp_v4_addr_to_user,
> .to_sk_saddr = sctp_v4_to_sk_saddr,
> .to_sk_daddr = sctp_v4_to_sk_daddr,
> + .copy_ip_options = sctp_v4_copy_ip_options,
> .af = &sctp_af_inet
> };
>
> @@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
> .ecn_capable = sctp_v4_ecn_capable,
> .net_header_len = sizeof(struct iphdr),
> .sockaddr_len = sizeof(struct sockaddr_in),
> + .ip_options_len = sctp_v4_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ip_setsockopt,
> .compat_getsockopt = compat_ip_getsockopt,
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index bf271f8..eb55c63 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
> static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
> {
> struct sctp_sock *sp = sctp_sk(sk);
> + struct sctp_af *af = sp->pf->af;
> struct sctp_assoc_value params;
> struct sctp_association *asoc;
> int val;
> @@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> if (val) {
> int min_len, max_len;
>
> - min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
> + min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
> + min_len -= af->ip_options_len(sk);
> min_len -= sizeof(struct sctphdr) +
> sizeof(struct sctp_data_chunk);
>
> @@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> asoc = sctp_id2assoc(sk, params.assoc_id);
> if (asoc) {
> if (val == 0) {
> - val = asoc->pathmtu - sp->pf->af->net_header_len;
> + val = asoc->pathmtu - af->net_header_len;
> + val -= af->ip_options_len(sk);
> val -= sizeof(struct sctphdr) +
> sctp_datachk_len(&asoc->stream);
> }
> @@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
> sctp_copy_sock(sock->sk, sk, asoc);
>
> /* Make peeled-off sockets more like 1-1 accepted sockets.
> - * Set the daddr and initialize id to something more random
> + * Set the daddr and initialize id to something more random and also
> + * copy over any ip options.
> */
> sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
> + sp->pf->copy_ip_options(sk, sock->sk);
>
> /* Populate the fields of the newsk from the oldsk and migrate the
> * asoc to the newsk.
> --
> 2.14.3
>
>
I think this makes a good bit more sense, thanks for the extra pass
Acked-by: Neil Horman <nhorman-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-21 3:44 ` Neil Horman
0 siblings, 0 replies; 32+ messages in thread
From: Neil Horman @ 2018-02-21 3:44 UTC (permalink / raw)
To: linux-security-module
On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> and CALIPSO/IPv6 services.
>
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> ---
> All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
> All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
> pass.
>
> V7 Changes:
> 1) Log when copy ip options fail for IPv4 and IPv6
> 2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
> func_tests do not test with struct sctp_assoc_value. Just used simple test
> and okay.
> 3) Move calculation of overheads to sctp_packet_config().
> NOTE: Initially in sctp_packet_reset() I set packet->size and
> packet->overhead to zero (as it is a reset). This was okay for all the
> lksctp-tools function tests, however when running "sctp-tests" ndatshched
> tests it causes these to fail with an st_s.log entry of:
> sid: 3, expected: 3
> sid: 3, expected: 3
> unexpected sid packet !!!
> sid: 1, expected: 3
>
> I then found sctp_packet_transmit() relies on setting
> "packet->size = packet->overhead;" to reset size to the current overhead
> after sending packets, hence the comment in sctp_packet_reset()
>
> include/net/sctp/sctp.h | 4 +++-
> include/net/sctp/structs.h | 2 ++
> net/sctp/chunk.c | 10 +++++++---
> net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
> net/sctp/output.c | 34 +++++++++++++++++++++-------------
> net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
> net/sctp/socket.c | 11 ++++++++---
> 7 files changed, 117 insertions(+), 27 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index f7ae6b0..25c5c87 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
> static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
> {
> struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> int frag = pmtu;
>
> - frag -= sp->pf->af->net_header_len;
> + frag -= af->ip_options_len(asoc->base.sk);
> + frag -= af->net_header_len;
> frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
>
> if (asoc->user_frag)
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 03e92dd..ead5fce 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -491,6 +491,7 @@ struct sctp_af {
> void (*ecn_capable)(struct sock *sk);
> __u16 net_header_len;
> int sockaddr_len;
> + int (*ip_options_len)(struct sock *sk);
> sa_family_t sa_family;
> struct list_head list;
> };
> @@ -515,6 +516,7 @@ struct sctp_pf {
> int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
> void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
> void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
> + void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
> struct sctp_af *af;
> };
>
> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
> index 991a530..d726d21 100644
> --- a/net/sctp/chunk.c
> +++ b/net/sctp/chunk.c
> @@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> struct list_head *pos, *temp;
> struct sctp_chunk *chunk;
> struct sctp_datamsg *msg;
> + struct sctp_sock *sp;
> + struct sctp_af *af;
> int err;
>
> msg = sctp_datamsg_new(GFP_KERNEL);
> @@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> /* This is the biggest possible DATA chunk that can fit into
> * the packet
> */
> - max_data = asoc->pathmtu -
> - sctp_sk(asoc->base.sk)->pf->af->net_header_len -
> - sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
> + sp = sctp_sk(asoc->base.sk);
> + af = sp->pf->af;
> + max_data = asoc->pathmtu - af->net_header_len -
> + sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
> + af->ip_options_len(asoc->base.sk);
> max_data = SCTP_TRUNC4(max_data);
>
> /* If the the peer requested that we authenticate DATA chunks
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index e35d4f7..30a05a8 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
> rcu_read_unlock();
> }
>
> +/* Copy over any ip options */
> +static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> +
> + newnp = inet6_sk(newsk);
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt) {
> + opt = ipv6_dup_options(newsk, opt);
> + if (!opt)
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newnp->opt, opt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v6_ip_options_len(struct sock *sk)
> +{
> + struct ipv6_pinfo *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> + int len = 0;
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt)
> + len = opt->opt_flen + opt->opt_nflen;
> +
> + rcu_read_unlock();
> + return len;
> +}
> +
> /* Initialize a sockaddr_storage from in incoming skb. */
> static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> struct sock *newsk;
> struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> struct sctp6_sock *newsctp6sk;
> - struct ipv6_txoptions *opt;
>
> newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
> if (!newsk)
> @@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> newnp->ipv6_ac_list = NULL;
> newnp->ipv6_fl_list = NULL;
>
> - rcu_read_lock();
> - opt = rcu_dereference(np->opt);
> - if (opt)
> - opt = ipv6_dup_options(newsk, opt);
> - RCU_INIT_POINTER(newnp->opt, opt);
> - rcu_read_unlock();
> + sctp_v6_copy_ip_options(sk, newsk);
>
> /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
> * and getpeername().
> @@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
> .ecn_capable = sctp_v6_ecn_capable,
> .net_header_len = sizeof(struct ipv6hdr),
> .sockaddr_len = sizeof(struct sockaddr_in6),
> + .ip_options_len = sctp_v6_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ipv6_setsockopt,
> .compat_getsockopt = compat_ipv6_getsockopt,
> @@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
> .addr_to_user = sctp_v6_addr_to_user,
> .to_sk_saddr = sctp_v6_to_sk_saddr,
> .to_sk_daddr = sctp_v6_to_sk_daddr,
> + .copy_ip_options = sctp_v6_copy_ip_options,
> .af = &sctp_af_inet6,
> };
>
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 01a26ee..a58d13c 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
>
> static void sctp_packet_reset(struct sctp_packet *packet)
> {
> + /* sctp_packet_transmit() relies on this to reset size to the
> + * current overhead after sending packets.
> + */
> packet->size = packet->overhead;
> +
> packet->has_cookie_echo = 0;
> packet->has_sack = 0;
> packet->has_data = 0;
> @@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> struct sctp_transport *tp = packet->transport;
> struct sctp_association *asoc = tp->asoc;
> struct sock *sk;
> + size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
>
> pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
> packet->vtag = vtag;
> @@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> if (!sctp_packet_empty(packet))
> return;
>
> - /* set packet max_size with pathmtu */
> + /* set packet max_size with pathmtu, then calculate overhead */
> packet->max_size = tp->pathmtu;
> - if (!asoc)
> + if (asoc) {
> + struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> +
> + overhead = af->net_header_len +
> + af->ip_options_len(asoc->base.sk);
> + overhead += sizeof(struct sctphdr);
> + packet->overhead = overhead;
> + packet->size = overhead;
> + } else {
> + packet->overhead = overhead;
> + packet->size = overhead;
> return;
> + }
>
> /* update dst or transport pathmtu if in need */
> sk = asoc->base.sk;
> @@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
> struct sctp_transport *transport,
> __u16 sport, __u16 dport)
> {
> - struct sctp_association *asoc = transport->asoc;
> - size_t overhead;
> -
> pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
>
> packet->transport = transport;
> packet->source_port = sport;
> packet->destination_port = dport;
> INIT_LIST_HEAD(&packet->chunk_list);
> - if (asoc) {
> - struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> - overhead = sp->pf->af->net_header_len;
> - } else {
> - overhead = sizeof(struct ipv6hdr);
> - }
> - overhead += sizeof(struct sctphdr);
> - packet->overhead = overhead;
> + /* The overhead will be calculated by sctp_packet_config() */
> + packet->overhead = 0;
> sctp_packet_reset(packet);
> packet->vtag = 0;
> }
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 91813e6..01c4d77 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
> return error;
> }
>
> +/* Copy over any ip options */
> +static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct inet_sock *newinet, *inet = inet_sk(sk);
> + struct ip_options_rcu *inet_opt, *newopt = NULL;
> +
> + newinet = inet_sk(newsk);
> +
> + rcu_read_lock();
> + inet_opt = rcu_dereference(inet->inet_opt);
> + if (inet_opt) {
> + newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
> + inet_opt->opt.optlen, GFP_ATOMIC);
> + if (newopt)
> + memcpy(newopt, inet_opt, sizeof(*inet_opt) +
> + inet_opt->opt.optlen);
> + else
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newinet->inet_opt, newopt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v4_ip_options_len(struct sock *sk)
> +{
> + struct inet_sock *inet = inet_sk(sk);
> +
> + if (inet->inet_opt)
> + return inet->inet_opt->opt.optlen;
> + else
> + return 0;
> +}
> +
> /* Initialize a sctp_addr from in incoming skb. */
> static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
> sctp_copy_sock(newsk, sk, asoc);
> sock_reset_flag(newsk, SOCK_ZAPPED);
>
> + sctp_v4_copy_ip_options(sk, newsk);
> +
> newinet = inet_sk(newsk);
>
> newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
> @@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
> .addr_to_user = sctp_v4_addr_to_user,
> .to_sk_saddr = sctp_v4_to_sk_saddr,
> .to_sk_daddr = sctp_v4_to_sk_daddr,
> + .copy_ip_options = sctp_v4_copy_ip_options,
> .af = &sctp_af_inet
> };
>
> @@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
> .ecn_capable = sctp_v4_ecn_capable,
> .net_header_len = sizeof(struct iphdr),
> .sockaddr_len = sizeof(struct sockaddr_in),
> + .ip_options_len = sctp_v4_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ip_setsockopt,
> .compat_getsockopt = compat_ip_getsockopt,
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index bf271f8..eb55c63 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
> static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
> {
> struct sctp_sock *sp = sctp_sk(sk);
> + struct sctp_af *af = sp->pf->af;
> struct sctp_assoc_value params;
> struct sctp_association *asoc;
> int val;
> @@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> if (val) {
> int min_len, max_len;
>
> - min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
> + min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
> + min_len -= af->ip_options_len(sk);
> min_len -= sizeof(struct sctphdr) +
> sizeof(struct sctp_data_chunk);
>
> @@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> asoc = sctp_id2assoc(sk, params.assoc_id);
> if (asoc) {
> if (val = 0) {
> - val = asoc->pathmtu - sp->pf->af->net_header_len;
> + val = asoc->pathmtu - af->net_header_len;
> + val -= af->ip_options_len(sk);
> val -= sizeof(struct sctphdr) +
> sctp_datachk_len(&asoc->stream);
> }
> @@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
> sctp_copy_sock(sock->sk, sk, asoc);
>
> /* Make peeled-off sockets more like 1-1 accepted sockets.
> - * Set the daddr and initialize id to something more random
> + * Set the daddr and initialize id to something more random and also
> + * copy over any ip options.
> */
> sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
> + sp->pf->copy_ip_options(sk, sock->sk);
>
> /* Populate the fields of the newsk from the oldsk and migrate the
> * asoc to the newsk.
> --
> 2.14.3
>
>
I think this makes a good bit more sense, thanks for the extra pass
Acked-by: Neil Horman <nhorman@tuxdriver.com>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-21 3:44 ` Neil Horman
0 siblings, 0 replies; 32+ messages in thread
From: Neil Horman @ 2018-02-21 3:44 UTC (permalink / raw)
To: Richard Haines
Cc: selinux, netdev, linux-sctp, linux-security-module, paul,
vyasevich, sds, eparis, marcelo.leitner, casey, jmorris
On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> and CALIPSO/IPv6 services.
>
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> ---
> All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
> All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
> pass.
>
> V7 Changes:
> 1) Log when copy ip options fail for IPv4 and IPv6
> 2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
> func_tests do not test with struct sctp_assoc_value. Just used simple test
> and okay.
> 3) Move calculation of overheads to sctp_packet_config().
> NOTE: Initially in sctp_packet_reset() I set packet->size and
> packet->overhead to zero (as it is a reset). This was okay for all the
> lksctp-tools function tests, however when running "sctp-tests" ndatshched
> tests it causes these to fail with an st_s.log entry of:
> sid: 3, expected: 3
> sid: 3, expected: 3
> unexpected sid packet !!!
> sid: 1, expected: 3
>
> I then found sctp_packet_transmit() relies on setting
> "packet->size = packet->overhead;" to reset size to the current overhead
> after sending packets, hence the comment in sctp_packet_reset()
>
> include/net/sctp/sctp.h | 4 +++-
> include/net/sctp/structs.h | 2 ++
> net/sctp/chunk.c | 10 +++++++---
> net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
> net/sctp/output.c | 34 +++++++++++++++++++++-------------
> net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
> net/sctp/socket.c | 11 ++++++++---
> 7 files changed, 117 insertions(+), 27 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index f7ae6b0..25c5c87 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
> static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
> {
> struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> int frag = pmtu;
>
> - frag -= sp->pf->af->net_header_len;
> + frag -= af->ip_options_len(asoc->base.sk);
> + frag -= af->net_header_len;
> frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
>
> if (asoc->user_frag)
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 03e92dd..ead5fce 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -491,6 +491,7 @@ struct sctp_af {
> void (*ecn_capable)(struct sock *sk);
> __u16 net_header_len;
> int sockaddr_len;
> + int (*ip_options_len)(struct sock *sk);
> sa_family_t sa_family;
> struct list_head list;
> };
> @@ -515,6 +516,7 @@ struct sctp_pf {
> int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
> void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
> void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
> + void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
> struct sctp_af *af;
> };
>
> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
> index 991a530..d726d21 100644
> --- a/net/sctp/chunk.c
> +++ b/net/sctp/chunk.c
> @@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> struct list_head *pos, *temp;
> struct sctp_chunk *chunk;
> struct sctp_datamsg *msg;
> + struct sctp_sock *sp;
> + struct sctp_af *af;
> int err;
>
> msg = sctp_datamsg_new(GFP_KERNEL);
> @@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> /* This is the biggest possible DATA chunk that can fit into
> * the packet
> */
> - max_data = asoc->pathmtu -
> - sctp_sk(asoc->base.sk)->pf->af->net_header_len -
> - sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
> + sp = sctp_sk(asoc->base.sk);
> + af = sp->pf->af;
> + max_data = asoc->pathmtu - af->net_header_len -
> + sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
> + af->ip_options_len(asoc->base.sk);
> max_data = SCTP_TRUNC4(max_data);
>
> /* If the the peer requested that we authenticate DATA chunks
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index e35d4f7..30a05a8 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
> rcu_read_unlock();
> }
>
> +/* Copy over any ip options */
> +static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> +
> + newnp = inet6_sk(newsk);
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt) {
> + opt = ipv6_dup_options(newsk, opt);
> + if (!opt)
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newnp->opt, opt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v6_ip_options_len(struct sock *sk)
> +{
> + struct ipv6_pinfo *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> + int len = 0;
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt)
> + len = opt->opt_flen + opt->opt_nflen;
> +
> + rcu_read_unlock();
> + return len;
> +}
> +
> /* Initialize a sockaddr_storage from in incoming skb. */
> static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> struct sock *newsk;
> struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> struct sctp6_sock *newsctp6sk;
> - struct ipv6_txoptions *opt;
>
> newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
> if (!newsk)
> @@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> newnp->ipv6_ac_list = NULL;
> newnp->ipv6_fl_list = NULL;
>
> - rcu_read_lock();
> - opt = rcu_dereference(np->opt);
> - if (opt)
> - opt = ipv6_dup_options(newsk, opt);
> - RCU_INIT_POINTER(newnp->opt, opt);
> - rcu_read_unlock();
> + sctp_v6_copy_ip_options(sk, newsk);
>
> /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
> * and getpeername().
> @@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
> .ecn_capable = sctp_v6_ecn_capable,
> .net_header_len = sizeof(struct ipv6hdr),
> .sockaddr_len = sizeof(struct sockaddr_in6),
> + .ip_options_len = sctp_v6_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ipv6_setsockopt,
> .compat_getsockopt = compat_ipv6_getsockopt,
> @@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
> .addr_to_user = sctp_v6_addr_to_user,
> .to_sk_saddr = sctp_v6_to_sk_saddr,
> .to_sk_daddr = sctp_v6_to_sk_daddr,
> + .copy_ip_options = sctp_v6_copy_ip_options,
> .af = &sctp_af_inet6,
> };
>
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 01a26ee..a58d13c 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
>
> static void sctp_packet_reset(struct sctp_packet *packet)
> {
> + /* sctp_packet_transmit() relies on this to reset size to the
> + * current overhead after sending packets.
> + */
> packet->size = packet->overhead;
> +
> packet->has_cookie_echo = 0;
> packet->has_sack = 0;
> packet->has_data = 0;
> @@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> struct sctp_transport *tp = packet->transport;
> struct sctp_association *asoc = tp->asoc;
> struct sock *sk;
> + size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
>
> pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
> packet->vtag = vtag;
> @@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> if (!sctp_packet_empty(packet))
> return;
>
> - /* set packet max_size with pathmtu */
> + /* set packet max_size with pathmtu, then calculate overhead */
> packet->max_size = tp->pathmtu;
> - if (!asoc)
> + if (asoc) {
> + struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> +
> + overhead = af->net_header_len +
> + af->ip_options_len(asoc->base.sk);
> + overhead += sizeof(struct sctphdr);
> + packet->overhead = overhead;
> + packet->size = overhead;
> + } else {
> + packet->overhead = overhead;
> + packet->size = overhead;
> return;
> + }
>
> /* update dst or transport pathmtu if in need */
> sk = asoc->base.sk;
> @@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
> struct sctp_transport *transport,
> __u16 sport, __u16 dport)
> {
> - struct sctp_association *asoc = transport->asoc;
> - size_t overhead;
> -
> pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
>
> packet->transport = transport;
> packet->source_port = sport;
> packet->destination_port = dport;
> INIT_LIST_HEAD(&packet->chunk_list);
> - if (asoc) {
> - struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> - overhead = sp->pf->af->net_header_len;
> - } else {
> - overhead = sizeof(struct ipv6hdr);
> - }
> - overhead += sizeof(struct sctphdr);
> - packet->overhead = overhead;
> + /* The overhead will be calculated by sctp_packet_config() */
> + packet->overhead = 0;
> sctp_packet_reset(packet);
> packet->vtag = 0;
> }
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 91813e6..01c4d77 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
> return error;
> }
>
> +/* Copy over any ip options */
> +static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct inet_sock *newinet, *inet = inet_sk(sk);
> + struct ip_options_rcu *inet_opt, *newopt = NULL;
> +
> + newinet = inet_sk(newsk);
> +
> + rcu_read_lock();
> + inet_opt = rcu_dereference(inet->inet_opt);
> + if (inet_opt) {
> + newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
> + inet_opt->opt.optlen, GFP_ATOMIC);
> + if (newopt)
> + memcpy(newopt, inet_opt, sizeof(*inet_opt) +
> + inet_opt->opt.optlen);
> + else
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newinet->inet_opt, newopt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v4_ip_options_len(struct sock *sk)
> +{
> + struct inet_sock *inet = inet_sk(sk);
> +
> + if (inet->inet_opt)
> + return inet->inet_opt->opt.optlen;
> + else
> + return 0;
> +}
> +
> /* Initialize a sctp_addr from in incoming skb. */
> static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
> sctp_copy_sock(newsk, sk, asoc);
> sock_reset_flag(newsk, SOCK_ZAPPED);
>
> + sctp_v4_copy_ip_options(sk, newsk);
> +
> newinet = inet_sk(newsk);
>
> newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
> @@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
> .addr_to_user = sctp_v4_addr_to_user,
> .to_sk_saddr = sctp_v4_to_sk_saddr,
> .to_sk_daddr = sctp_v4_to_sk_daddr,
> + .copy_ip_options = sctp_v4_copy_ip_options,
> .af = &sctp_af_inet
> };
>
> @@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
> .ecn_capable = sctp_v4_ecn_capable,
> .net_header_len = sizeof(struct iphdr),
> .sockaddr_len = sizeof(struct sockaddr_in),
> + .ip_options_len = sctp_v4_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ip_setsockopt,
> .compat_getsockopt = compat_ip_getsockopt,
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index bf271f8..eb55c63 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
> static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
> {
> struct sctp_sock *sp = sctp_sk(sk);
> + struct sctp_af *af = sp->pf->af;
> struct sctp_assoc_value params;
> struct sctp_association *asoc;
> int val;
> @@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> if (val) {
> int min_len, max_len;
>
> - min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
> + min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
> + min_len -= af->ip_options_len(sk);
> min_len -= sizeof(struct sctphdr) +
> sizeof(struct sctp_data_chunk);
>
> @@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> asoc = sctp_id2assoc(sk, params.assoc_id);
> if (asoc) {
> if (val == 0) {
> - val = asoc->pathmtu - sp->pf->af->net_header_len;
> + val = asoc->pathmtu - af->net_header_len;
> + val -= af->ip_options_len(sk);
> val -= sizeof(struct sctphdr) +
> sctp_datachk_len(&asoc->stream);
> }
> @@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
> sctp_copy_sock(sock->sk, sk, asoc);
>
> /* Make peeled-off sockets more like 1-1 accepted sockets.
> - * Set the daddr and initialize id to something more random
> + * Set the daddr and initialize id to something more random and also
> + * copy over any ip options.
> */
> sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
> + sp->pf->copy_ip_options(sk, sock->sk);
>
> /* Populate the fields of the newsk from the oldsk and migrate the
> * asoc to the newsk.
> --
> 2.14.3
>
>
I think this makes a good bit more sense, thanks for the extra pass
Acked-by: Neil Horman <nhorman@tuxdriver.com>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-21 3:44 ` Neil Horman
0 siblings, 0 replies; 32+ messages in thread
From: Neil Horman @ 2018-02-21 3:44 UTC (permalink / raw)
To: linux-security-module
On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> and CALIPSO/IPv6 services.
>
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> ---
> All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
> All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
> pass.
>
> V7 Changes:
> 1) Log when copy ip options fail for IPv4 and IPv6
> 2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
> func_tests do not test with struct sctp_assoc_value. Just used simple test
> and okay.
> 3) Move calculation of overheads to sctp_packet_config().
> NOTE: Initially in sctp_packet_reset() I set packet->size and
> packet->overhead to zero (as it is a reset). This was okay for all the
> lksctp-tools function tests, however when running "sctp-tests" ndatshched
> tests it causes these to fail with an st_s.log entry of:
> sid: 3, expected: 3
> sid: 3, expected: 3
> unexpected sid packet !!!
> sid: 1, expected: 3
>
> I then found sctp_packet_transmit() relies on setting
> "packet->size = packet->overhead;" to reset size to the current overhead
> after sending packets, hence the comment in sctp_packet_reset()
>
> include/net/sctp/sctp.h | 4 +++-
> include/net/sctp/structs.h | 2 ++
> net/sctp/chunk.c | 10 +++++++---
> net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
> net/sctp/output.c | 34 +++++++++++++++++++++-------------
> net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
> net/sctp/socket.c | 11 ++++++++---
> 7 files changed, 117 insertions(+), 27 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index f7ae6b0..25c5c87 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
> static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
> {
> struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> int frag = pmtu;
>
> - frag -= sp->pf->af->net_header_len;
> + frag -= af->ip_options_len(asoc->base.sk);
> + frag -= af->net_header_len;
> frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
>
> if (asoc->user_frag)
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 03e92dd..ead5fce 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -491,6 +491,7 @@ struct sctp_af {
> void (*ecn_capable)(struct sock *sk);
> __u16 net_header_len;
> int sockaddr_len;
> + int (*ip_options_len)(struct sock *sk);
> sa_family_t sa_family;
> struct list_head list;
> };
> @@ -515,6 +516,7 @@ struct sctp_pf {
> int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
> void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
> void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
> + void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
> struct sctp_af *af;
> };
>
> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
> index 991a530..d726d21 100644
> --- a/net/sctp/chunk.c
> +++ b/net/sctp/chunk.c
> @@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> struct list_head *pos, *temp;
> struct sctp_chunk *chunk;
> struct sctp_datamsg *msg;
> + struct sctp_sock *sp;
> + struct sctp_af *af;
> int err;
>
> msg = sctp_datamsg_new(GFP_KERNEL);
> @@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> /* This is the biggest possible DATA chunk that can fit into
> * the packet
> */
> - max_data = asoc->pathmtu -
> - sctp_sk(asoc->base.sk)->pf->af->net_header_len -
> - sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
> + sp = sctp_sk(asoc->base.sk);
> + af = sp->pf->af;
> + max_data = asoc->pathmtu - af->net_header_len -
> + sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
> + af->ip_options_len(asoc->base.sk);
> max_data = SCTP_TRUNC4(max_data);
>
> /* If the the peer requested that we authenticate DATA chunks
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index e35d4f7..30a05a8 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
> rcu_read_unlock();
> }
>
> +/* Copy over any ip options */
> +static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> +
> + newnp = inet6_sk(newsk);
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt) {
> + opt = ipv6_dup_options(newsk, opt);
> + if (!opt)
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newnp->opt, opt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v6_ip_options_len(struct sock *sk)
> +{
> + struct ipv6_pinfo *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> + int len = 0;
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt)
> + len = opt->opt_flen + opt->opt_nflen;
> +
> + rcu_read_unlock();
> + return len;
> +}
> +
> /* Initialize a sockaddr_storage from in incoming skb. */
> static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> struct sock *newsk;
> struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> struct sctp6_sock *newsctp6sk;
> - struct ipv6_txoptions *opt;
>
> newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
> if (!newsk)
> @@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> newnp->ipv6_ac_list = NULL;
> newnp->ipv6_fl_list = NULL;
>
> - rcu_read_lock();
> - opt = rcu_dereference(np->opt);
> - if (opt)
> - opt = ipv6_dup_options(newsk, opt);
> - RCU_INIT_POINTER(newnp->opt, opt);
> - rcu_read_unlock();
> + sctp_v6_copy_ip_options(sk, newsk);
>
> /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
> * and getpeername().
> @@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
> .ecn_capable = sctp_v6_ecn_capable,
> .net_header_len = sizeof(struct ipv6hdr),
> .sockaddr_len = sizeof(struct sockaddr_in6),
> + .ip_options_len = sctp_v6_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ipv6_setsockopt,
> .compat_getsockopt = compat_ipv6_getsockopt,
> @@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
> .addr_to_user = sctp_v6_addr_to_user,
> .to_sk_saddr = sctp_v6_to_sk_saddr,
> .to_sk_daddr = sctp_v6_to_sk_daddr,
> + .copy_ip_options = sctp_v6_copy_ip_options,
> .af = &sctp_af_inet6,
> };
>
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 01a26ee..a58d13c 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
>
> static void sctp_packet_reset(struct sctp_packet *packet)
> {
> + /* sctp_packet_transmit() relies on this to reset size to the
> + * current overhead after sending packets.
> + */
> packet->size = packet->overhead;
> +
> packet->has_cookie_echo = 0;
> packet->has_sack = 0;
> packet->has_data = 0;
> @@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> struct sctp_transport *tp = packet->transport;
> struct sctp_association *asoc = tp->asoc;
> struct sock *sk;
> + size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
>
> pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
> packet->vtag = vtag;
> @@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> if (!sctp_packet_empty(packet))
> return;
>
> - /* set packet max_size with pathmtu */
> + /* set packet max_size with pathmtu, then calculate overhead */
> packet->max_size = tp->pathmtu;
> - if (!asoc)
> + if (asoc) {
> + struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> +
> + overhead = af->net_header_len +
> + af->ip_options_len(asoc->base.sk);
> + overhead += sizeof(struct sctphdr);
> + packet->overhead = overhead;
> + packet->size = overhead;
> + } else {
> + packet->overhead = overhead;
> + packet->size = overhead;
> return;
> + }
>
> /* update dst or transport pathmtu if in need */
> sk = asoc->base.sk;
> @@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
> struct sctp_transport *transport,
> __u16 sport, __u16 dport)
> {
> - struct sctp_association *asoc = transport->asoc;
> - size_t overhead;
> -
> pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
>
> packet->transport = transport;
> packet->source_port = sport;
> packet->destination_port = dport;
> INIT_LIST_HEAD(&packet->chunk_list);
> - if (asoc) {
> - struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> - overhead = sp->pf->af->net_header_len;
> - } else {
> - overhead = sizeof(struct ipv6hdr);
> - }
> - overhead += sizeof(struct sctphdr);
> - packet->overhead = overhead;
> + /* The overhead will be calculated by sctp_packet_config() */
> + packet->overhead = 0;
> sctp_packet_reset(packet);
> packet->vtag = 0;
> }
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 91813e6..01c4d77 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
> return error;
> }
>
> +/* Copy over any ip options */
> +static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct inet_sock *newinet, *inet = inet_sk(sk);
> + struct ip_options_rcu *inet_opt, *newopt = NULL;
> +
> + newinet = inet_sk(newsk);
> +
> + rcu_read_lock();
> + inet_opt = rcu_dereference(inet->inet_opt);
> + if (inet_opt) {
> + newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
> + inet_opt->opt.optlen, GFP_ATOMIC);
> + if (newopt)
> + memcpy(newopt, inet_opt, sizeof(*inet_opt) +
> + inet_opt->opt.optlen);
> + else
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newinet->inet_opt, newopt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v4_ip_options_len(struct sock *sk)
> +{
> + struct inet_sock *inet = inet_sk(sk);
> +
> + if (inet->inet_opt)
> + return inet->inet_opt->opt.optlen;
> + else
> + return 0;
> +}
> +
> /* Initialize a sctp_addr from in incoming skb. */
> static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
> sctp_copy_sock(newsk, sk, asoc);
> sock_reset_flag(newsk, SOCK_ZAPPED);
>
> + sctp_v4_copy_ip_options(sk, newsk);
> +
> newinet = inet_sk(newsk);
>
> newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
> @@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
> .addr_to_user = sctp_v4_addr_to_user,
> .to_sk_saddr = sctp_v4_to_sk_saddr,
> .to_sk_daddr = sctp_v4_to_sk_daddr,
> + .copy_ip_options = sctp_v4_copy_ip_options,
> .af = &sctp_af_inet
> };
>
> @@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
> .ecn_capable = sctp_v4_ecn_capable,
> .net_header_len = sizeof(struct iphdr),
> .sockaddr_len = sizeof(struct sockaddr_in),
> + .ip_options_len = sctp_v4_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ip_setsockopt,
> .compat_getsockopt = compat_ip_getsockopt,
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index bf271f8..eb55c63 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
> static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
> {
> struct sctp_sock *sp = sctp_sk(sk);
> + struct sctp_af *af = sp->pf->af;
> struct sctp_assoc_value params;
> struct sctp_association *asoc;
> int val;
> @@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> if (val) {
> int min_len, max_len;
>
> - min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
> + min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
> + min_len -= af->ip_options_len(sk);
> min_len -= sizeof(struct sctphdr) +
> sizeof(struct sctp_data_chunk);
>
> @@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> asoc = sctp_id2assoc(sk, params.assoc_id);
> if (asoc) {
> if (val == 0) {
> - val = asoc->pathmtu - sp->pf->af->net_header_len;
> + val = asoc->pathmtu - af->net_header_len;
> + val -= af->ip_options_len(sk);
> val -= sizeof(struct sctphdr) +
> sctp_datachk_len(&asoc->stream);
> }
> @@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
> sctp_copy_sock(sock->sk, sk, asoc);
>
> /* Make peeled-off sockets more like 1-1 accepted sockets.
> - * Set the daddr and initialize id to something more random
> + * Set the daddr and initialize id to something more random and also
> + * copy over any ip options.
> */
> sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
> + sp->pf->copy_ip_options(sk, sock->sk);
>
> /* Populate the fields of the newsk from the oldsk and migrate the
> * asoc to the newsk.
> --
> 2.14.3
>
>
I think this makes a good bit more sense, thanks for the extra pass
Acked-by: Neil Horman <nhorman@tuxdriver.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
2018-02-20 19:15 ` Richard Haines
(?)
(?)
@ 2018-02-21 14:33 ` Marcelo Ricardo Leitner
-1 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-21 14:33 UTC (permalink / raw)
To: Richard Haines
Cc: nhorman-2XuSBdqkA4R54TAoqtyWWQ, netdev-u79uwXL29TY76Z2rM5mHXA,
vyasevich-Re5JQEeQqe8AvxtiuMwx3w,
linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-sctp-u79uwXL29TY76Z2rM5mHXA,
selinux-+05T5uksL2qpZYMLLGbcSA, sds-+05T5uksL2qpZYMLLGbcSA
On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> and CALIPSO/IPv6 services.
>
> Signed-off-by: Richard Haines <richard_c_haines-FhtRXb7CoQBt1OO0OYaSVA@public.gmane.org>
LGTM too, thanks!
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
> All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
> pass.
>
> V7 Changes:
> 1) Log when copy ip options fail for IPv4 and IPv6
> 2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
> func_tests do not test with struct sctp_assoc_value. Just used simple test
> and okay.
> 3) Move calculation of overheads to sctp_packet_config().
> NOTE: Initially in sctp_packet_reset() I set packet->size and
> packet->overhead to zero (as it is a reset). This was okay for all the
> lksctp-tools function tests, however when running "sctp-tests" ndatshched
> tests it causes these to fail with an st_s.log entry of:
> sid: 3, expected: 3
> sid: 3, expected: 3
> unexpected sid packet !!!
> sid: 1, expected: 3
>
> I then found sctp_packet_transmit() relies on setting
> "packet->size = packet->overhead;" to reset size to the current overhead
> after sending packets, hence the comment in sctp_packet_reset()
>
> include/net/sctp/sctp.h | 4 +++-
> include/net/sctp/structs.h | 2 ++
> net/sctp/chunk.c | 10 +++++++---
> net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
> net/sctp/output.c | 34 +++++++++++++++++++++-------------
> net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
> net/sctp/socket.c | 11 ++++++++---
> 7 files changed, 117 insertions(+), 27 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index f7ae6b0..25c5c87 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
> static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
> {
> struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> int frag = pmtu;
>
> - frag -= sp->pf->af->net_header_len;
> + frag -= af->ip_options_len(asoc->base.sk);
> + frag -= af->net_header_len;
> frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
>
> if (asoc->user_frag)
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 03e92dd..ead5fce 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -491,6 +491,7 @@ struct sctp_af {
> void (*ecn_capable)(struct sock *sk);
> __u16 net_header_len;
> int sockaddr_len;
> + int (*ip_options_len)(struct sock *sk);
> sa_family_t sa_family;
> struct list_head list;
> };
> @@ -515,6 +516,7 @@ struct sctp_pf {
> int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
> void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
> void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
> + void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
> struct sctp_af *af;
> };
>
> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
> index 991a530..d726d21 100644
> --- a/net/sctp/chunk.c
> +++ b/net/sctp/chunk.c
> @@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> struct list_head *pos, *temp;
> struct sctp_chunk *chunk;
> struct sctp_datamsg *msg;
> + struct sctp_sock *sp;
> + struct sctp_af *af;
> int err;
>
> msg = sctp_datamsg_new(GFP_KERNEL);
> @@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> /* This is the biggest possible DATA chunk that can fit into
> * the packet
> */
> - max_data = asoc->pathmtu -
> - sctp_sk(asoc->base.sk)->pf->af->net_header_len -
> - sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
> + sp = sctp_sk(asoc->base.sk);
> + af = sp->pf->af;
> + max_data = asoc->pathmtu - af->net_header_len -
> + sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
> + af->ip_options_len(asoc->base.sk);
> max_data = SCTP_TRUNC4(max_data);
>
> /* If the the peer requested that we authenticate DATA chunks
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index e35d4f7..30a05a8 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
> rcu_read_unlock();
> }
>
> +/* Copy over any ip options */
> +static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> +
> + newnp = inet6_sk(newsk);
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt) {
> + opt = ipv6_dup_options(newsk, opt);
> + if (!opt)
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newnp->opt, opt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v6_ip_options_len(struct sock *sk)
> +{
> + struct ipv6_pinfo *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> + int len = 0;
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt)
> + len = opt->opt_flen + opt->opt_nflen;
> +
> + rcu_read_unlock();
> + return len;
> +}
> +
> /* Initialize a sockaddr_storage from in incoming skb. */
> static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> struct sock *newsk;
> struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> struct sctp6_sock *newsctp6sk;
> - struct ipv6_txoptions *opt;
>
> newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
> if (!newsk)
> @@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> newnp->ipv6_ac_list = NULL;
> newnp->ipv6_fl_list = NULL;
>
> - rcu_read_lock();
> - opt = rcu_dereference(np->opt);
> - if (opt)
> - opt = ipv6_dup_options(newsk, opt);
> - RCU_INIT_POINTER(newnp->opt, opt);
> - rcu_read_unlock();
> + sctp_v6_copy_ip_options(sk, newsk);
>
> /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
> * and getpeername().
> @@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
> .ecn_capable = sctp_v6_ecn_capable,
> .net_header_len = sizeof(struct ipv6hdr),
> .sockaddr_len = sizeof(struct sockaddr_in6),
> + .ip_options_len = sctp_v6_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ipv6_setsockopt,
> .compat_getsockopt = compat_ipv6_getsockopt,
> @@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
> .addr_to_user = sctp_v6_addr_to_user,
> .to_sk_saddr = sctp_v6_to_sk_saddr,
> .to_sk_daddr = sctp_v6_to_sk_daddr,
> + .copy_ip_options = sctp_v6_copy_ip_options,
> .af = &sctp_af_inet6,
> };
>
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 01a26ee..a58d13c 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
>
> static void sctp_packet_reset(struct sctp_packet *packet)
> {
> + /* sctp_packet_transmit() relies on this to reset size to the
> + * current overhead after sending packets.
> + */
> packet->size = packet->overhead;
> +
> packet->has_cookie_echo = 0;
> packet->has_sack = 0;
> packet->has_data = 0;
> @@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> struct sctp_transport *tp = packet->transport;
> struct sctp_association *asoc = tp->asoc;
> struct sock *sk;
> + size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
>
> pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
> packet->vtag = vtag;
> @@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> if (!sctp_packet_empty(packet))
> return;
>
> - /* set packet max_size with pathmtu */
> + /* set packet max_size with pathmtu, then calculate overhead */
> packet->max_size = tp->pathmtu;
> - if (!asoc)
> + if (asoc) {
> + struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> +
> + overhead = af->net_header_len +
> + af->ip_options_len(asoc->base.sk);
> + overhead += sizeof(struct sctphdr);
> + packet->overhead = overhead;
> + packet->size = overhead;
> + } else {
> + packet->overhead = overhead;
> + packet->size = overhead;
> return;
> + }
>
> /* update dst or transport pathmtu if in need */
> sk = asoc->base.sk;
> @@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
> struct sctp_transport *transport,
> __u16 sport, __u16 dport)
> {
> - struct sctp_association *asoc = transport->asoc;
> - size_t overhead;
> -
> pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
>
> packet->transport = transport;
> packet->source_port = sport;
> packet->destination_port = dport;
> INIT_LIST_HEAD(&packet->chunk_list);
> - if (asoc) {
> - struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> - overhead = sp->pf->af->net_header_len;
> - } else {
> - overhead = sizeof(struct ipv6hdr);
> - }
> - overhead += sizeof(struct sctphdr);
> - packet->overhead = overhead;
> + /* The overhead will be calculated by sctp_packet_config() */
> + packet->overhead = 0;
> sctp_packet_reset(packet);
> packet->vtag = 0;
> }
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 91813e6..01c4d77 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
> return error;
> }
>
> +/* Copy over any ip options */
> +static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct inet_sock *newinet, *inet = inet_sk(sk);
> + struct ip_options_rcu *inet_opt, *newopt = NULL;
> +
> + newinet = inet_sk(newsk);
> +
> + rcu_read_lock();
> + inet_opt = rcu_dereference(inet->inet_opt);
> + if (inet_opt) {
> + newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
> + inet_opt->opt.optlen, GFP_ATOMIC);
> + if (newopt)
> + memcpy(newopt, inet_opt, sizeof(*inet_opt) +
> + inet_opt->opt.optlen);
> + else
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newinet->inet_opt, newopt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v4_ip_options_len(struct sock *sk)
> +{
> + struct inet_sock *inet = inet_sk(sk);
> +
> + if (inet->inet_opt)
> + return inet->inet_opt->opt.optlen;
> + else
> + return 0;
> +}
> +
> /* Initialize a sctp_addr from in incoming skb. */
> static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
> sctp_copy_sock(newsk, sk, asoc);
> sock_reset_flag(newsk, SOCK_ZAPPED);
>
> + sctp_v4_copy_ip_options(sk, newsk);
> +
> newinet = inet_sk(newsk);
>
> newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
> @@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
> .addr_to_user = sctp_v4_addr_to_user,
> .to_sk_saddr = sctp_v4_to_sk_saddr,
> .to_sk_daddr = sctp_v4_to_sk_daddr,
> + .copy_ip_options = sctp_v4_copy_ip_options,
> .af = &sctp_af_inet
> };
>
> @@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
> .ecn_capable = sctp_v4_ecn_capable,
> .net_header_len = sizeof(struct iphdr),
> .sockaddr_len = sizeof(struct sockaddr_in),
> + .ip_options_len = sctp_v4_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ip_setsockopt,
> .compat_getsockopt = compat_ip_getsockopt,
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index bf271f8..eb55c63 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
> static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
> {
> struct sctp_sock *sp = sctp_sk(sk);
> + struct sctp_af *af = sp->pf->af;
> struct sctp_assoc_value params;
> struct sctp_association *asoc;
> int val;
> @@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> if (val) {
> int min_len, max_len;
>
> - min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
> + min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
> + min_len -= af->ip_options_len(sk);
> min_len -= sizeof(struct sctphdr) +
> sizeof(struct sctp_data_chunk);
>
> @@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> asoc = sctp_id2assoc(sk, params.assoc_id);
> if (asoc) {
> if (val == 0) {
> - val = asoc->pathmtu - sp->pf->af->net_header_len;
> + val = asoc->pathmtu - af->net_header_len;
> + val -= af->ip_options_len(sk);
> val -= sizeof(struct sctphdr) +
> sctp_datachk_len(&asoc->stream);
> }
> @@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
> sctp_copy_sock(sock->sk, sk, asoc);
>
> /* Make peeled-off sockets more like 1-1 accepted sockets.
> - * Set the daddr and initialize id to something more random
> + * Set the daddr and initialize id to something more random and also
> + * copy over any ip options.
> */
> sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
> + sp->pf->copy_ip_options(sk, sock->sk);
>
> /* Populate the fields of the newsk from the oldsk and migrate the
> * asoc to the newsk.
> --
> 2.14.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-21 14:33 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-21 14:33 UTC (permalink / raw)
To: linux-security-module
On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> and CALIPSO/IPv6 services.
>
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
LGTM too, thanks!
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> ---
> All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
> All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
> pass.
>
> V7 Changes:
> 1) Log when copy ip options fail for IPv4 and IPv6
> 2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
> func_tests do not test with struct sctp_assoc_value. Just used simple test
> and okay.
> 3) Move calculation of overheads to sctp_packet_config().
> NOTE: Initially in sctp_packet_reset() I set packet->size and
> packet->overhead to zero (as it is a reset). This was okay for all the
> lksctp-tools function tests, however when running "sctp-tests" ndatshched
> tests it causes these to fail with an st_s.log entry of:
> sid: 3, expected: 3
> sid: 3, expected: 3
> unexpected sid packet !!!
> sid: 1, expected: 3
>
> I then found sctp_packet_transmit() relies on setting
> "packet->size = packet->overhead;" to reset size to the current overhead
> after sending packets, hence the comment in sctp_packet_reset()
>
> include/net/sctp/sctp.h | 4 +++-
> include/net/sctp/structs.h | 2 ++
> net/sctp/chunk.c | 10 +++++++---
> net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
> net/sctp/output.c | 34 +++++++++++++++++++++-------------
> net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
> net/sctp/socket.c | 11 ++++++++---
> 7 files changed, 117 insertions(+), 27 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index f7ae6b0..25c5c87 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
> static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
> {
> struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> int frag = pmtu;
>
> - frag -= sp->pf->af->net_header_len;
> + frag -= af->ip_options_len(asoc->base.sk);
> + frag -= af->net_header_len;
> frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
>
> if (asoc->user_frag)
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 03e92dd..ead5fce 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -491,6 +491,7 @@ struct sctp_af {
> void (*ecn_capable)(struct sock *sk);
> __u16 net_header_len;
> int sockaddr_len;
> + int (*ip_options_len)(struct sock *sk);
> sa_family_t sa_family;
> struct list_head list;
> };
> @@ -515,6 +516,7 @@ struct sctp_pf {
> int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
> void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
> void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
> + void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
> struct sctp_af *af;
> };
>
> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
> index 991a530..d726d21 100644
> --- a/net/sctp/chunk.c
> +++ b/net/sctp/chunk.c
> @@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> struct list_head *pos, *temp;
> struct sctp_chunk *chunk;
> struct sctp_datamsg *msg;
> + struct sctp_sock *sp;
> + struct sctp_af *af;
> int err;
>
> msg = sctp_datamsg_new(GFP_KERNEL);
> @@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> /* This is the biggest possible DATA chunk that can fit into
> * the packet
> */
> - max_data = asoc->pathmtu -
> - sctp_sk(asoc->base.sk)->pf->af->net_header_len -
> - sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
> + sp = sctp_sk(asoc->base.sk);
> + af = sp->pf->af;
> + max_data = asoc->pathmtu - af->net_header_len -
> + sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
> + af->ip_options_len(asoc->base.sk);
> max_data = SCTP_TRUNC4(max_data);
>
> /* If the the peer requested that we authenticate DATA chunks
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index e35d4f7..30a05a8 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
> rcu_read_unlock();
> }
>
> +/* Copy over any ip options */
> +static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> +
> + newnp = inet6_sk(newsk);
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt) {
> + opt = ipv6_dup_options(newsk, opt);
> + if (!opt)
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newnp->opt, opt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v6_ip_options_len(struct sock *sk)
> +{
> + struct ipv6_pinfo *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> + int len = 0;
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt)
> + len = opt->opt_flen + opt->opt_nflen;
> +
> + rcu_read_unlock();
> + return len;
> +}
> +
> /* Initialize a sockaddr_storage from in incoming skb. */
> static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> struct sock *newsk;
> struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> struct sctp6_sock *newsctp6sk;
> - struct ipv6_txoptions *opt;
>
> newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
> if (!newsk)
> @@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> newnp->ipv6_ac_list = NULL;
> newnp->ipv6_fl_list = NULL;
>
> - rcu_read_lock();
> - opt = rcu_dereference(np->opt);
> - if (opt)
> - opt = ipv6_dup_options(newsk, opt);
> - RCU_INIT_POINTER(newnp->opt, opt);
> - rcu_read_unlock();
> + sctp_v6_copy_ip_options(sk, newsk);
>
> /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
> * and getpeername().
> @@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
> .ecn_capable = sctp_v6_ecn_capable,
> .net_header_len = sizeof(struct ipv6hdr),
> .sockaddr_len = sizeof(struct sockaddr_in6),
> + .ip_options_len = sctp_v6_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ipv6_setsockopt,
> .compat_getsockopt = compat_ipv6_getsockopt,
> @@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
> .addr_to_user = sctp_v6_addr_to_user,
> .to_sk_saddr = sctp_v6_to_sk_saddr,
> .to_sk_daddr = sctp_v6_to_sk_daddr,
> + .copy_ip_options = sctp_v6_copy_ip_options,
> .af = &sctp_af_inet6,
> };
>
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 01a26ee..a58d13c 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
>
> static void sctp_packet_reset(struct sctp_packet *packet)
> {
> + /* sctp_packet_transmit() relies on this to reset size to the
> + * current overhead after sending packets.
> + */
> packet->size = packet->overhead;
> +
> packet->has_cookie_echo = 0;
> packet->has_sack = 0;
> packet->has_data = 0;
> @@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> struct sctp_transport *tp = packet->transport;
> struct sctp_association *asoc = tp->asoc;
> struct sock *sk;
> + size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
>
> pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
> packet->vtag = vtag;
> @@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> if (!sctp_packet_empty(packet))
> return;
>
> - /* set packet max_size with pathmtu */
> + /* set packet max_size with pathmtu, then calculate overhead */
> packet->max_size = tp->pathmtu;
> - if (!asoc)
> + if (asoc) {
> + struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> +
> + overhead = af->net_header_len +
> + af->ip_options_len(asoc->base.sk);
> + overhead += sizeof(struct sctphdr);
> + packet->overhead = overhead;
> + packet->size = overhead;
> + } else {
> + packet->overhead = overhead;
> + packet->size = overhead;
> return;
> + }
>
> /* update dst or transport pathmtu if in need */
> sk = asoc->base.sk;
> @@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
> struct sctp_transport *transport,
> __u16 sport, __u16 dport)
> {
> - struct sctp_association *asoc = transport->asoc;
> - size_t overhead;
> -
> pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
>
> packet->transport = transport;
> packet->source_port = sport;
> packet->destination_port = dport;
> INIT_LIST_HEAD(&packet->chunk_list);
> - if (asoc) {
> - struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> - overhead = sp->pf->af->net_header_len;
> - } else {
> - overhead = sizeof(struct ipv6hdr);
> - }
> - overhead += sizeof(struct sctphdr);
> - packet->overhead = overhead;
> + /* The overhead will be calculated by sctp_packet_config() */
> + packet->overhead = 0;
> sctp_packet_reset(packet);
> packet->vtag = 0;
> }
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 91813e6..01c4d77 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
> return error;
> }
>
> +/* Copy over any ip options */
> +static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct inet_sock *newinet, *inet = inet_sk(sk);
> + struct ip_options_rcu *inet_opt, *newopt = NULL;
> +
> + newinet = inet_sk(newsk);
> +
> + rcu_read_lock();
> + inet_opt = rcu_dereference(inet->inet_opt);
> + if (inet_opt) {
> + newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
> + inet_opt->opt.optlen, GFP_ATOMIC);
> + if (newopt)
> + memcpy(newopt, inet_opt, sizeof(*inet_opt) +
> + inet_opt->opt.optlen);
> + else
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newinet->inet_opt, newopt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v4_ip_options_len(struct sock *sk)
> +{
> + struct inet_sock *inet = inet_sk(sk);
> +
> + if (inet->inet_opt)
> + return inet->inet_opt->opt.optlen;
> + else
> + return 0;
> +}
> +
> /* Initialize a sctp_addr from in incoming skb. */
> static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
> sctp_copy_sock(newsk, sk, asoc);
> sock_reset_flag(newsk, SOCK_ZAPPED);
>
> + sctp_v4_copy_ip_options(sk, newsk);
> +
> newinet = inet_sk(newsk);
>
> newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
> @@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
> .addr_to_user = sctp_v4_addr_to_user,
> .to_sk_saddr = sctp_v4_to_sk_saddr,
> .to_sk_daddr = sctp_v4_to_sk_daddr,
> + .copy_ip_options = sctp_v4_copy_ip_options,
> .af = &sctp_af_inet
> };
>
> @@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
> .ecn_capable = sctp_v4_ecn_capable,
> .net_header_len = sizeof(struct iphdr),
> .sockaddr_len = sizeof(struct sockaddr_in),
> + .ip_options_len = sctp_v4_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ip_setsockopt,
> .compat_getsockopt = compat_ip_getsockopt,
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index bf271f8..eb55c63 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
> static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
> {
> struct sctp_sock *sp = sctp_sk(sk);
> + struct sctp_af *af = sp->pf->af;
> struct sctp_assoc_value params;
> struct sctp_association *asoc;
> int val;
> @@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> if (val) {
> int min_len, max_len;
>
> - min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
> + min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
> + min_len -= af->ip_options_len(sk);
> min_len -= sizeof(struct sctphdr) +
> sizeof(struct sctp_data_chunk);
>
> @@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> asoc = sctp_id2assoc(sk, params.assoc_id);
> if (asoc) {
> if (val = 0) {
> - val = asoc->pathmtu - sp->pf->af->net_header_len;
> + val = asoc->pathmtu - af->net_header_len;
> + val -= af->ip_options_len(sk);
> val -= sizeof(struct sctphdr) +
> sctp_datachk_len(&asoc->stream);
> }
> @@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
> sctp_copy_sock(sock->sk, sk, asoc);
>
> /* Make peeled-off sockets more like 1-1 accepted sockets.
> - * Set the daddr and initialize id to something more random
> + * Set the daddr and initialize id to something more random and also
> + * copy over any ip options.
> */
> sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
> + sp->pf->copy_ip_options(sk, sock->sk);
>
> /* Populate the fields of the newsk from the oldsk and migrate the
> * asoc to the newsk.
> --
> 2.14.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-21 14:33 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-21 14:33 UTC (permalink / raw)
To: Richard Haines
Cc: selinux, netdev, linux-sctp, linux-security-module, paul,
vyasevich, nhorman, sds, eparis, casey, jmorris
On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> and CALIPSO/IPv6 services.
>
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
LGTM too, thanks!
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> ---
> All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
> All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
> pass.
>
> V7 Changes:
> 1) Log when copy ip options fail for IPv4 and IPv6
> 2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
> func_tests do not test with struct sctp_assoc_value. Just used simple test
> and okay.
> 3) Move calculation of overheads to sctp_packet_config().
> NOTE: Initially in sctp_packet_reset() I set packet->size and
> packet->overhead to zero (as it is a reset). This was okay for all the
> lksctp-tools function tests, however when running "sctp-tests" ndatshched
> tests it causes these to fail with an st_s.log entry of:
> sid: 3, expected: 3
> sid: 3, expected: 3
> unexpected sid packet !!!
> sid: 1, expected: 3
>
> I then found sctp_packet_transmit() relies on setting
> "packet->size = packet->overhead;" to reset size to the current overhead
> after sending packets, hence the comment in sctp_packet_reset()
>
> include/net/sctp/sctp.h | 4 +++-
> include/net/sctp/structs.h | 2 ++
> net/sctp/chunk.c | 10 +++++++---
> net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
> net/sctp/output.c | 34 +++++++++++++++++++++-------------
> net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
> net/sctp/socket.c | 11 ++++++++---
> 7 files changed, 117 insertions(+), 27 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index f7ae6b0..25c5c87 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
> static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
> {
> struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> int frag = pmtu;
>
> - frag -= sp->pf->af->net_header_len;
> + frag -= af->ip_options_len(asoc->base.sk);
> + frag -= af->net_header_len;
> frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
>
> if (asoc->user_frag)
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 03e92dd..ead5fce 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -491,6 +491,7 @@ struct sctp_af {
> void (*ecn_capable)(struct sock *sk);
> __u16 net_header_len;
> int sockaddr_len;
> + int (*ip_options_len)(struct sock *sk);
> sa_family_t sa_family;
> struct list_head list;
> };
> @@ -515,6 +516,7 @@ struct sctp_pf {
> int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
> void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
> void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
> + void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
> struct sctp_af *af;
> };
>
> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
> index 991a530..d726d21 100644
> --- a/net/sctp/chunk.c
> +++ b/net/sctp/chunk.c
> @@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> struct list_head *pos, *temp;
> struct sctp_chunk *chunk;
> struct sctp_datamsg *msg;
> + struct sctp_sock *sp;
> + struct sctp_af *af;
> int err;
>
> msg = sctp_datamsg_new(GFP_KERNEL);
> @@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> /* This is the biggest possible DATA chunk that can fit into
> * the packet
> */
> - max_data = asoc->pathmtu -
> - sctp_sk(asoc->base.sk)->pf->af->net_header_len -
> - sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
> + sp = sctp_sk(asoc->base.sk);
> + af = sp->pf->af;
> + max_data = asoc->pathmtu - af->net_header_len -
> + sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
> + af->ip_options_len(asoc->base.sk);
> max_data = SCTP_TRUNC4(max_data);
>
> /* If the the peer requested that we authenticate DATA chunks
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index e35d4f7..30a05a8 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
> rcu_read_unlock();
> }
>
> +/* Copy over any ip options */
> +static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> +
> + newnp = inet6_sk(newsk);
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt) {
> + opt = ipv6_dup_options(newsk, opt);
> + if (!opt)
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newnp->opt, opt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v6_ip_options_len(struct sock *sk)
> +{
> + struct ipv6_pinfo *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> + int len = 0;
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt)
> + len = opt->opt_flen + opt->opt_nflen;
> +
> + rcu_read_unlock();
> + return len;
> +}
> +
> /* Initialize a sockaddr_storage from in incoming skb. */
> static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> struct sock *newsk;
> struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> struct sctp6_sock *newsctp6sk;
> - struct ipv6_txoptions *opt;
>
> newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
> if (!newsk)
> @@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> newnp->ipv6_ac_list = NULL;
> newnp->ipv6_fl_list = NULL;
>
> - rcu_read_lock();
> - opt = rcu_dereference(np->opt);
> - if (opt)
> - opt = ipv6_dup_options(newsk, opt);
> - RCU_INIT_POINTER(newnp->opt, opt);
> - rcu_read_unlock();
> + sctp_v6_copy_ip_options(sk, newsk);
>
> /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
> * and getpeername().
> @@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
> .ecn_capable = sctp_v6_ecn_capable,
> .net_header_len = sizeof(struct ipv6hdr),
> .sockaddr_len = sizeof(struct sockaddr_in6),
> + .ip_options_len = sctp_v6_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ipv6_setsockopt,
> .compat_getsockopt = compat_ipv6_getsockopt,
> @@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
> .addr_to_user = sctp_v6_addr_to_user,
> .to_sk_saddr = sctp_v6_to_sk_saddr,
> .to_sk_daddr = sctp_v6_to_sk_daddr,
> + .copy_ip_options = sctp_v6_copy_ip_options,
> .af = &sctp_af_inet6,
> };
>
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 01a26ee..a58d13c 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
>
> static void sctp_packet_reset(struct sctp_packet *packet)
> {
> + /* sctp_packet_transmit() relies on this to reset size to the
> + * current overhead after sending packets.
> + */
> packet->size = packet->overhead;
> +
> packet->has_cookie_echo = 0;
> packet->has_sack = 0;
> packet->has_data = 0;
> @@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> struct sctp_transport *tp = packet->transport;
> struct sctp_association *asoc = tp->asoc;
> struct sock *sk;
> + size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
>
> pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
> packet->vtag = vtag;
> @@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> if (!sctp_packet_empty(packet))
> return;
>
> - /* set packet max_size with pathmtu */
> + /* set packet max_size with pathmtu, then calculate overhead */
> packet->max_size = tp->pathmtu;
> - if (!asoc)
> + if (asoc) {
> + struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> +
> + overhead = af->net_header_len +
> + af->ip_options_len(asoc->base.sk);
> + overhead += sizeof(struct sctphdr);
> + packet->overhead = overhead;
> + packet->size = overhead;
> + } else {
> + packet->overhead = overhead;
> + packet->size = overhead;
> return;
> + }
>
> /* update dst or transport pathmtu if in need */
> sk = asoc->base.sk;
> @@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
> struct sctp_transport *transport,
> __u16 sport, __u16 dport)
> {
> - struct sctp_association *asoc = transport->asoc;
> - size_t overhead;
> -
> pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
>
> packet->transport = transport;
> packet->source_port = sport;
> packet->destination_port = dport;
> INIT_LIST_HEAD(&packet->chunk_list);
> - if (asoc) {
> - struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> - overhead = sp->pf->af->net_header_len;
> - } else {
> - overhead = sizeof(struct ipv6hdr);
> - }
> - overhead += sizeof(struct sctphdr);
> - packet->overhead = overhead;
> + /* The overhead will be calculated by sctp_packet_config() */
> + packet->overhead = 0;
> sctp_packet_reset(packet);
> packet->vtag = 0;
> }
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 91813e6..01c4d77 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
> return error;
> }
>
> +/* Copy over any ip options */
> +static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct inet_sock *newinet, *inet = inet_sk(sk);
> + struct ip_options_rcu *inet_opt, *newopt = NULL;
> +
> + newinet = inet_sk(newsk);
> +
> + rcu_read_lock();
> + inet_opt = rcu_dereference(inet->inet_opt);
> + if (inet_opt) {
> + newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
> + inet_opt->opt.optlen, GFP_ATOMIC);
> + if (newopt)
> + memcpy(newopt, inet_opt, sizeof(*inet_opt) +
> + inet_opt->opt.optlen);
> + else
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newinet->inet_opt, newopt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v4_ip_options_len(struct sock *sk)
> +{
> + struct inet_sock *inet = inet_sk(sk);
> +
> + if (inet->inet_opt)
> + return inet->inet_opt->opt.optlen;
> + else
> + return 0;
> +}
> +
> /* Initialize a sctp_addr from in incoming skb. */
> static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
> sctp_copy_sock(newsk, sk, asoc);
> sock_reset_flag(newsk, SOCK_ZAPPED);
>
> + sctp_v4_copy_ip_options(sk, newsk);
> +
> newinet = inet_sk(newsk);
>
> newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
> @@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
> .addr_to_user = sctp_v4_addr_to_user,
> .to_sk_saddr = sctp_v4_to_sk_saddr,
> .to_sk_daddr = sctp_v4_to_sk_daddr,
> + .copy_ip_options = sctp_v4_copy_ip_options,
> .af = &sctp_af_inet
> };
>
> @@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
> .ecn_capable = sctp_v4_ecn_capable,
> .net_header_len = sizeof(struct iphdr),
> .sockaddr_len = sizeof(struct sockaddr_in),
> + .ip_options_len = sctp_v4_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ip_setsockopt,
> .compat_getsockopt = compat_ip_getsockopt,
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index bf271f8..eb55c63 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
> static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
> {
> struct sctp_sock *sp = sctp_sk(sk);
> + struct sctp_af *af = sp->pf->af;
> struct sctp_assoc_value params;
> struct sctp_association *asoc;
> int val;
> @@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> if (val) {
> int min_len, max_len;
>
> - min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
> + min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
> + min_len -= af->ip_options_len(sk);
> min_len -= sizeof(struct sctphdr) +
> sizeof(struct sctp_data_chunk);
>
> @@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> asoc = sctp_id2assoc(sk, params.assoc_id);
> if (asoc) {
> if (val == 0) {
> - val = asoc->pathmtu - sp->pf->af->net_header_len;
> + val = asoc->pathmtu - af->net_header_len;
> + val -= af->ip_options_len(sk);
> val -= sizeof(struct sctphdr) +
> sctp_datachk_len(&asoc->stream);
> }
> @@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
> sctp_copy_sock(sock->sk, sk, asoc);
>
> /* Make peeled-off sockets more like 1-1 accepted sockets.
> - * Set the daddr and initialize id to something more random
> + * Set the daddr and initialize id to something more random and also
> + * copy over any ip options.
> */
> sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
> + sp->pf->copy_ip_options(sk, sock->sk);
>
> /* Populate the fields of the newsk from the oldsk and migrate the
> * asoc to the newsk.
> --
> 2.14.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-21 14:33 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-21 14:33 UTC (permalink / raw)
To: linux-security-module
On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> and CALIPSO/IPv6 services.
>
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
LGTM too, thanks!
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> ---
> All SCTP lksctp-tools/src/func_tests run correctly in enforcing mode.
> All "./sctp-tests run" obtained from: https://github.com/sctp/sctp-tests
> pass.
>
> V7 Changes:
> 1) Log when copy ip options fail for IPv4 and IPv6
> 2) Correct sctp_setsockopt_maxseg() function. Note that the lksctp-tools
> func_tests do not test with struct sctp_assoc_value. Just used simple test
> and okay.
> 3) Move calculation of overheads to sctp_packet_config().
> NOTE: Initially in sctp_packet_reset() I set packet->size and
> packet->overhead to zero (as it is a reset). This was okay for all the
> lksctp-tools function tests, however when running "sctp-tests" ndatshched
> tests it causes these to fail with an st_s.log entry of:
> sid: 3, expected: 3
> sid: 3, expected: 3
> unexpected sid packet !!!
> sid: 1, expected: 3
>
> I then found sctp_packet_transmit() relies on setting
> "packet->size = packet->overhead;" to reset size to the current overhead
> after sending packets, hence the comment in sctp_packet_reset()
>
> include/net/sctp/sctp.h | 4 +++-
> include/net/sctp/structs.h | 2 ++
> net/sctp/chunk.c | 10 +++++++---
> net/sctp/ipv6.c | 45 ++++++++++++++++++++++++++++++++++++++-------
> net/sctp/output.c | 34 +++++++++++++++++++++-------------
> net/sctp/protocol.c | 38 ++++++++++++++++++++++++++++++++++++++
> net/sctp/socket.c | 11 ++++++++---
> 7 files changed, 117 insertions(+), 27 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index f7ae6b0..25c5c87 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
> static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
> {
> struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> int frag = pmtu;
>
> - frag -= sp->pf->af->net_header_len;
> + frag -= af->ip_options_len(asoc->base.sk);
> + frag -= af->net_header_len;
> frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
>
> if (asoc->user_frag)
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 03e92dd..ead5fce 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -491,6 +491,7 @@ struct sctp_af {
> void (*ecn_capable)(struct sock *sk);
> __u16 net_header_len;
> int sockaddr_len;
> + int (*ip_options_len)(struct sock *sk);
> sa_family_t sa_family;
> struct list_head list;
> };
> @@ -515,6 +516,7 @@ struct sctp_pf {
> int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
> void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
> void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
> + void (*copy_ip_options)(struct sock *sk, struct sock *newsk);
> struct sctp_af *af;
> };
>
> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
> index 991a530..d726d21 100644
> --- a/net/sctp/chunk.c
> +++ b/net/sctp/chunk.c
> @@ -171,6 +171,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> struct list_head *pos, *temp;
> struct sctp_chunk *chunk;
> struct sctp_datamsg *msg;
> + struct sctp_sock *sp;
> + struct sctp_af *af;
> int err;
>
> msg = sctp_datamsg_new(GFP_KERNEL);
> @@ -189,9 +191,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
> /* This is the biggest possible DATA chunk that can fit into
> * the packet
> */
> - max_data = asoc->pathmtu -
> - sctp_sk(asoc->base.sk)->pf->af->net_header_len -
> - sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
> + sp = sctp_sk(asoc->base.sk);
> + af = sp->pf->af;
> + max_data = asoc->pathmtu - af->net_header_len -
> + sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
> + af->ip_options_len(asoc->base.sk);
> max_data = SCTP_TRUNC4(max_data);
>
> /* If the the peer requested that we authenticate DATA chunks
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index e35d4f7..30a05a8 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -427,6 +427,41 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
> rcu_read_unlock();
> }
>
> +/* Copy over any ip options */
> +static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> +
> + newnp = inet6_sk(newsk);
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt) {
> + opt = ipv6_dup_options(newsk, opt);
> + if (!opt)
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newnp->opt, opt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v6_ip_options_len(struct sock *sk)
> +{
> + struct ipv6_pinfo *np = inet6_sk(sk);
> + struct ipv6_txoptions *opt;
> + int len = 0;
> +
> + rcu_read_lock();
> + opt = rcu_dereference(np->opt);
> + if (opt)
> + len = opt->opt_flen + opt->opt_nflen;
> +
> + rcu_read_unlock();
> + return len;
> +}
> +
> /* Initialize a sockaddr_storage from in incoming skb. */
> static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -666,7 +701,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> struct sock *newsk;
> struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
> struct sctp6_sock *newsctp6sk;
> - struct ipv6_txoptions *opt;
>
> newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
> if (!newsk)
> @@ -689,12 +723,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> newnp->ipv6_ac_list = NULL;
> newnp->ipv6_fl_list = NULL;
>
> - rcu_read_lock();
> - opt = rcu_dereference(np->opt);
> - if (opt)
> - opt = ipv6_dup_options(newsk, opt);
> - RCU_INIT_POINTER(newnp->opt, opt);
> - rcu_read_unlock();
> + sctp_v6_copy_ip_options(sk, newsk);
>
> /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
> * and getpeername().
> @@ -1041,6 +1070,7 @@ static struct sctp_af sctp_af_inet6 = {
> .ecn_capable = sctp_v6_ecn_capable,
> .net_header_len = sizeof(struct ipv6hdr),
> .sockaddr_len = sizeof(struct sockaddr_in6),
> + .ip_options_len = sctp_v6_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ipv6_setsockopt,
> .compat_getsockopt = compat_ipv6_getsockopt,
> @@ -1059,6 +1089,7 @@ static struct sctp_pf sctp_pf_inet6 = {
> .addr_to_user = sctp_v6_addr_to_user,
> .to_sk_saddr = sctp_v6_to_sk_saddr,
> .to_sk_daddr = sctp_v6_to_sk_daddr,
> + .copy_ip_options = sctp_v6_copy_ip_options,
> .af = &sctp_af_inet6,
> };
>
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 01a26ee..a58d13c 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -69,7 +69,11 @@ static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
>
> static void sctp_packet_reset(struct sctp_packet *packet)
> {
> + /* sctp_packet_transmit() relies on this to reset size to the
> + * current overhead after sending packets.
> + */
> packet->size = packet->overhead;
> +
> packet->has_cookie_echo = 0;
> packet->has_sack = 0;
> packet->has_data = 0;
> @@ -87,6 +91,7 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> struct sctp_transport *tp = packet->transport;
> struct sctp_association *asoc = tp->asoc;
> struct sock *sk;
> + size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
>
> pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
> packet->vtag = vtag;
> @@ -95,10 +100,22 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> if (!sctp_packet_empty(packet))
> return;
>
> - /* set packet max_size with pathmtu */
> + /* set packet max_size with pathmtu, then calculate overhead */
> packet->max_size = tp->pathmtu;
> - if (!asoc)
> + if (asoc) {
> + struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> + struct sctp_af *af = sp->pf->af;
> +
> + overhead = af->net_header_len +
> + af->ip_options_len(asoc->base.sk);
> + overhead += sizeof(struct sctphdr);
> + packet->overhead = overhead;
> + packet->size = overhead;
> + } else {
> + packet->overhead = overhead;
> + packet->size = overhead;
> return;
> + }
>
> /* update dst or transport pathmtu if in need */
> sk = asoc->base.sk;
> @@ -140,23 +157,14 @@ void sctp_packet_init(struct sctp_packet *packet,
> struct sctp_transport *transport,
> __u16 sport, __u16 dport)
> {
> - struct sctp_association *asoc = transport->asoc;
> - size_t overhead;
> -
> pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport);
>
> packet->transport = transport;
> packet->source_port = sport;
> packet->destination_port = dport;
> INIT_LIST_HEAD(&packet->chunk_list);
> - if (asoc) {
> - struct sctp_sock *sp = sctp_sk(asoc->base.sk);
> - overhead = sp->pf->af->net_header_len;
> - } else {
> - overhead = sizeof(struct ipv6hdr);
> - }
> - overhead += sizeof(struct sctphdr);
> - packet->overhead = overhead;
> + /* The overhead will be calculated by sctp_packet_config() */
> + packet->overhead = 0;
> sctp_packet_reset(packet);
> packet->vtag = 0;
> }
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 91813e6..01c4d77 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -237,6 +237,40 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
> return error;
> }
>
> +/* Copy over any ip options */
> +static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
> +{
> + struct inet_sock *newinet, *inet = inet_sk(sk);
> + struct ip_options_rcu *inet_opt, *newopt = NULL;
> +
> + newinet = inet_sk(newsk);
> +
> + rcu_read_lock();
> + inet_opt = rcu_dereference(inet->inet_opt);
> + if (inet_opt) {
> + newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
> + inet_opt->opt.optlen, GFP_ATOMIC);
> + if (newopt)
> + memcpy(newopt, inet_opt, sizeof(*inet_opt) +
> + inet_opt->opt.optlen);
> + else
> + pr_err("%s: Failed to copy ip options\n", __func__);
> + }
> + RCU_INIT_POINTER(newinet->inet_opt, newopt);
> + rcu_read_unlock();
> +}
> +
> +/* Account for the IP options */
> +static int sctp_v4_ip_options_len(struct sock *sk)
> +{
> + struct inet_sock *inet = inet_sk(sk);
> +
> + if (inet->inet_opt)
> + return inet->inet_opt->opt.optlen;
> + else
> + return 0;
> +}
> +
> /* Initialize a sctp_addr from in incoming skb. */
> static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
> int is_saddr)
> @@ -588,6 +622,8 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
> sctp_copy_sock(newsk, sk, asoc);
> sock_reset_flag(newsk, SOCK_ZAPPED);
>
> + sctp_v4_copy_ip_options(sk, newsk);
> +
> newinet = inet_sk(newsk);
>
> newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
> @@ -1006,6 +1042,7 @@ static struct sctp_pf sctp_pf_inet = {
> .addr_to_user = sctp_v4_addr_to_user,
> .to_sk_saddr = sctp_v4_to_sk_saddr,
> .to_sk_daddr = sctp_v4_to_sk_daddr,
> + .copy_ip_options = sctp_v4_copy_ip_options,
> .af = &sctp_af_inet
> };
>
> @@ -1090,6 +1127,7 @@ static struct sctp_af sctp_af_inet = {
> .ecn_capable = sctp_v4_ecn_capable,
> .net_header_len = sizeof(struct iphdr),
> .sockaddr_len = sizeof(struct sockaddr_in),
> + .ip_options_len = sctp_v4_ip_options_len,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_ip_setsockopt,
> .compat_getsockopt = compat_ip_getsockopt,
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index bf271f8..eb55c63 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3138,6 +3138,7 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
> static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
> {
> struct sctp_sock *sp = sctp_sk(sk);
> + struct sctp_af *af = sp->pf->af;
> struct sctp_assoc_value params;
> struct sctp_association *asoc;
> int val;
> @@ -3162,7 +3163,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> if (val) {
> int min_len, max_len;
>
> - min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
> + min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
> + min_len -= af->ip_options_len(sk);
> min_len -= sizeof(struct sctphdr) +
> sizeof(struct sctp_data_chunk);
>
> @@ -3175,7 +3177,8 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
> asoc = sctp_id2assoc(sk, params.assoc_id);
> if (asoc) {
> if (val == 0) {
> - val = asoc->pathmtu - sp->pf->af->net_header_len;
> + val = asoc->pathmtu - af->net_header_len;
> + val -= af->ip_options_len(sk);
> val -= sizeof(struct sctphdr) +
> sctp_datachk_len(&asoc->stream);
> }
> @@ -5087,9 +5090,11 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
> sctp_copy_sock(sock->sk, sk, asoc);
>
> /* Make peeled-off sockets more like 1-1 accepted sockets.
> - * Set the daddr and initialize id to something more random
> + * Set the daddr and initialize id to something more random and also
> + * copy over any ip options.
> */
> sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
> + sp->pf->copy_ip_options(sk, sock->sk);
>
> /* Populate the fields of the newsk from the oldsk and migrate the
> * asoc to the newsk.
> --
> 2.14.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
2018-02-21 14:33 ` Marcelo Ricardo Leitner
(?)
(?)
@ 2018-02-21 20:45 ` Paul Moore
-1 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-21 20:45 UTC (permalink / raw)
To: Marcelo Ricardo Leitner, Richard Haines
Cc: nhorman-2XuSBdqkA4R54TAoqtyWWQ, netdev-u79uwXL29TY76Z2rM5mHXA,
vyasevich-Re5JQEeQqe8AvxtiuMwx3w,
linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-sctp-u79uwXL29TY76Z2rM5mHXA,
selinux-+05T5uksL2qpZYMLLGbcSA, sds-+05T5uksL2qpZYMLLGbcSA
On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>> and CALIPSO/IPv6 services.
>>
>> Signed-off-by: Richard Haines <richard_c_haines-FhtRXb7CoQBt1OO0OYaSVA@public.gmane.org>
>
> LGTM too, thanks!
>
> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-21 20:45 ` Paul Moore
0 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-21 20:45 UTC (permalink / raw)
To: linux-security-module
On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>> and CALIPSO/IPv6 services.
>>
>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
>
> LGTM too, thanks!
>
> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
--
paul moore
www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-21 20:45 ` Paul Moore
0 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-21 20:45 UTC (permalink / raw)
To: Marcelo Ricardo Leitner, Richard Haines
Cc: selinux, netdev, linux-sctp, linux-security-module, vyasevich,
nhorman, sds, eparis, casey, jmorris
On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>> and CALIPSO/IPv6 services.
>>
>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
>
> LGTM too, thanks!
>
> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
--
paul moore
www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-21 20:45 ` Paul Moore
0 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-21 20:45 UTC (permalink / raw)
To: linux-security-module
On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>> and CALIPSO/IPv6 services.
>>
>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
>
> LGTM too, thanks!
>
> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
--
paul moore
www.paul-moore.com
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
2018-02-21 20:45 ` Paul Moore
(?)
(?)
@ 2018-02-22 23:08 ` Paul Moore
-1 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-22 23:08 UTC (permalink / raw)
To: Richard Haines
Cc: Marcelo Ricardo Leitner, nhorman-2XuSBdqkA4R54TAoqtyWWQ,
netdev-u79uwXL29TY76Z2rM5mHXA, Vlad Yasevich,
linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-sctp-u79uwXL29TY76Z2rM5mHXA,
selinux-+05T5uksL2qpZYMLLGbcSA, Stephen Smalley
On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul-r2n+y4ga6xFZroRs9YW3xA@public.gmane.org> wrote:
> On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>>> and CALIPSO/IPv6 services.
>>>
>>> Signed-off-by: Richard Haines <richard_c_haines-FhtRXb7CoQBt1OO0OYaSVA@public.gmane.org>
>>
>> LGTM too, thanks!
>>
>> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>
> I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
v7 patchset) in selinux/next and did a quick sanity test on the kernel
(booted, no basic SELinux regressions). Additional testing help is
always appreciated ...
* git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
* https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
--
paul moore
www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-22 23:08 ` Paul Moore
0 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-22 23:08 UTC (permalink / raw)
To: linux-security-module
On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
> On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
>> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>>> and CALIPSO/IPv6 services.
>>>
>>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
>>
>> LGTM too, thanks!
>>
>> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
>
> I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
v7 patchset) in selinux/next and did a quick sanity test on the kernel
(booted, no basic SELinux regressions). Additional testing help is
always appreciated ...
* git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
* https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
--
paul moore
www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-22 23:08 ` Paul Moore
0 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-22 23:08 UTC (permalink / raw)
To: Richard Haines
Cc: selinux, netdev, linux-sctp, linux-security-module,
Vlad Yasevich, nhorman, Stephen Smalley, Eric Paris, casey,
James Morris, Marcelo Ricardo Leitner
On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
> On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
>> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>>> and CALIPSO/IPv6 services.
>>>
>>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
>>
>> LGTM too, thanks!
>>
>> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
>
> I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
v7 patchset) in selinux/next and did a quick sanity test on the kernel
(booted, no basic SELinux regressions). Additional testing help is
always appreciated ...
* git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
* https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
--
paul moore
www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-22 23:08 ` Paul Moore
0 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-22 23:08 UTC (permalink / raw)
To: linux-security-module
On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
> On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
>> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>>> and CALIPSO/IPv6 services.
>>>
>>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
>>
>> LGTM too, thanks!
>>
>> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
>
> I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
v7 patchset) in selinux/next and did a quick sanity test on the kernel
(booted, no basic SELinux regressions). Additional testing help is
always appreciated ...
* git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
* https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
--
paul moore
www.paul-moore.com
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
2018-02-22 23:08 ` Paul Moore
(?)
(?)
@ 2018-02-23 2:40 ` Marcelo Ricardo Leitner
-1 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-23 2:40 UTC (permalink / raw)
To: Paul Moore
Cc: nhorman-2XuSBdqkA4R54TAoqtyWWQ, netdev-u79uwXL29TY76Z2rM5mHXA,
Vlad Yasevich, linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-sctp-u79uwXL29TY76Z2rM5mHXA,
selinux-+05T5uksL2qpZYMLLGbcSA, Stephen Smalley
On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul-r2n+y4ga6xFZroRs9YW3xA@public.gmane.org> wrote:
> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> >>> and CALIPSO/IPv6 services.
> >>>
> >>> Signed-off-by: Richard Haines <richard_c_haines-FhtRXb7CoQBt1OO0OYaSVA@public.gmane.org>
> >>
> >> LGTM too, thanks!
> >>
> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >
> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
>
> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
> v7 patchset) in selinux/next and did a quick sanity test on the kernel
> (booted, no basic SELinux regressions). Additional testing help is
> always appreciated ...
I'll try it early next week.
Any ideas on when this is going to appear on Dave's net-next tree?
We have a lot of SCTP changes to be posted on this cycle and would be
nice if we could avoid merge conflicts.
>
> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>
> --
> paul moore
> www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-23 2:40 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-23 2:40 UTC (permalink / raw)
To: linux-security-module
On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> >>> and CALIPSO/IPv6 services.
> >>>
> >>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> >>
> >> LGTM too, thanks!
> >>
> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> >
> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
>
> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
> v7 patchset) in selinux/next and did a quick sanity test on the kernel
> (booted, no basic SELinux regressions). Additional testing help is
> always appreciated ...
I'll try it early next week.
Any ideas on when this is going to appear on Dave's net-next tree?
We have a lot of SCTP changes to be posted on this cycle and would be
nice if we could avoid merge conflicts.
>
> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>
> --
> paul moore
> www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-23 2:40 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-23 2:40 UTC (permalink / raw)
To: Paul Moore
Cc: Richard Haines, selinux, netdev, linux-sctp,
linux-security-module, Vlad Yasevich, nhorman, Stephen Smalley,
Eric Paris, casey, James Morris
On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> >>> and CALIPSO/IPv6 services.
> >>>
> >>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> >>
> >> LGTM too, thanks!
> >>
> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> >
> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
>
> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
> v7 patchset) in selinux/next and did a quick sanity test on the kernel
> (booted, no basic SELinux regressions). Additional testing help is
> always appreciated ...
I'll try it early next week.
Any ideas on when this is going to appear on Dave's net-next tree?
We have a lot of SCTP changes to be posted on this cycle and would be
nice if we could avoid merge conflicts.
>
> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>
> --
> paul moore
> www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-23 2:40 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-23 2:40 UTC (permalink / raw)
To: linux-security-module
On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> >>> and CALIPSO/IPv6 services.
> >>>
> >>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> >>
> >> LGTM too, thanks!
> >>
> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> >
> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
>
> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
> v7 patchset) in selinux/next and did a quick sanity test on the kernel
> (booted, no basic SELinux regressions). Additional testing help is
> always appreciated ...
I'll try it early next week.
Any ideas on when this is going to appear on Dave's net-next tree?
We have a lot of SCTP changes to be posted on this cycle and would be
nice if we could avoid merge conflicts.
>
> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>
> --
> paul moore
> www.paul-moore.com
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
2018-02-23 2:40 ` Marcelo Ricardo Leitner
(?)
(?)
@ 2018-02-23 16:11 ` Paul Moore
-1 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-23 16:11 UTC (permalink / raw)
To: Marcelo Ricardo Leitner
Cc: nhorman-2XuSBdqkA4R54TAoqtyWWQ, netdev-u79uwXL29TY76Z2rM5mHXA,
Vlad Yasevich, linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-sctp-u79uwXL29TY76Z2rM5mHXA,
selinux-+05T5uksL2qpZYMLLGbcSA, Stephen Smalley
On Thu, Feb 22, 2018 at 9:40 PM, Marcelo Ricardo Leitner
<marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
>> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul-r2n+y4ga6xFZroRs9YW3xA@public.gmane.org> wrote:
>> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>> >>> and CALIPSO/IPv6 services.
>> >>>
>> >>> Signed-off-by: Richard Haines <richard_c_haines-FhtRXb7CoQBt1OO0OYaSVA@public.gmane.org>
>> >>
>> >> LGTM too, thanks!
>> >>
>> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> >
>> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
>>
>> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
>> v7 patchset) in selinux/next and did a quick sanity test on the kernel
>> (booted, no basic SELinux regressions). Additional testing help is
>> always appreciated ...
>
> I'll try it early next week.
>
> Any ideas on when this is going to appear on Dave's net-next tree?
> We have a lot of SCTP changes to be posted on this cycle and would be
> nice if we could avoid merge conflicts.
It's merged into the SELinux tree, next branch; see the links below.
Last I checked DaveM doesn't pull the selinux/next into his net-next
tree (that would be a little funny for historical reasons).
Any idea on how bad the merge conflicts are?
>> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
--
paul moore
www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-23 16:11 ` Paul Moore
0 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-23 16:11 UTC (permalink / raw)
To: linux-security-module
On Thu, Feb 22, 2018 at 9:40 PM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
>> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
>> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
>> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>> >>> and CALIPSO/IPv6 services.
>> >>>
>> >>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
>> >>
>> >> LGTM too, thanks!
>> >>
>> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
>> >
>> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
>>
>> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
>> v7 patchset) in selinux/next and did a quick sanity test on the kernel
>> (booted, no basic SELinux regressions). Additional testing help is
>> always appreciated ...
>
> I'll try it early next week.
>
> Any ideas on when this is going to appear on Dave's net-next tree?
> We have a lot of SCTP changes to be posted on this cycle and would be
> nice if we could avoid merge conflicts.
It's merged into the SELinux tree, next branch; see the links below.
Last I checked DaveM doesn't pull the selinux/next into his net-next
tree (that would be a little funny for historical reasons).
Any idea on how bad the merge conflicts are?
>> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
--
paul moore
www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-23 16:11 ` Paul Moore
0 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-23 16:11 UTC (permalink / raw)
To: Marcelo Ricardo Leitner
Cc: Richard Haines, selinux, netdev, linux-sctp,
linux-security-module, Vlad Yasevich, nhorman, Stephen Smalley,
Eric Paris, casey, James Morris
On Thu, Feb 22, 2018 at 9:40 PM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
>> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
>> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
>> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>> >>> and CALIPSO/IPv6 services.
>> >>>
>> >>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
>> >>
>> >> LGTM too, thanks!
>> >>
>> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
>> >
>> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
>>
>> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
>> v7 patchset) in selinux/next and did a quick sanity test on the kernel
>> (booted, no basic SELinux regressions). Additional testing help is
>> always appreciated ...
>
> I'll try it early next week.
>
> Any ideas on when this is going to appear on Dave's net-next tree?
> We have a lot of SCTP changes to be posted on this cycle and would be
> nice if we could avoid merge conflicts.
It's merged into the SELinux tree, next branch; see the links below.
Last I checked DaveM doesn't pull the selinux/next into his net-next
tree (that would be a little funny for historical reasons).
Any idea on how bad the merge conflicts are?
>> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
--
paul moore
www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-23 16:11 ` Paul Moore
0 siblings, 0 replies; 32+ messages in thread
From: Paul Moore @ 2018-02-23 16:11 UTC (permalink / raw)
To: linux-security-module
On Thu, Feb 22, 2018 at 9:40 PM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
>> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
>> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
>> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
>> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
>> >>> and CALIPSO/IPv6 services.
>> >>>
>> >>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
>> >>
>> >> LGTM too, thanks!
>> >>
>> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
>> >
>> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
>>
>> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
>> v7 patchset) in selinux/next and did a quick sanity test on the kernel
>> (booted, no basic SELinux regressions). Additional testing help is
>> always appreciated ...
>
> I'll try it early next week.
>
> Any ideas on when this is going to appear on Dave's net-next tree?
> We have a lot of SCTP changes to be posted on this cycle and would be
> nice if we could avoid merge conflicts.
It's merged into the SELinux tree, next branch; see the links below.
Last I checked DaveM doesn't pull the selinux/next into his net-next
tree (that would be a little funny for historical reasons).
Any idea on how bad the merge conflicts are?
>> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
--
paul moore
www.paul-moore.com
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
2018-02-23 16:11 ` Paul Moore
(?)
(?)
@ 2018-02-24 0:56 ` Marcelo Ricardo Leitner
-1 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-24 0:56 UTC (permalink / raw)
To: Paul Moore
Cc: nhorman-2XuSBdqkA4R54TAoqtyWWQ, netdev-u79uwXL29TY76Z2rM5mHXA,
Vlad Yasevich, linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-sctp-u79uwXL29TY76Z2rM5mHXA,
selinux-+05T5uksL2qpZYMLLGbcSA, Stephen Smalley
On Fri, Feb 23, 2018 at 11:11:50AM -0500, Paul Moore wrote:
> On Thu, Feb 22, 2018 at 9:40 PM, Marcelo Ricardo Leitner
> <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> > On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
> >> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul-r2n+y4ga6xFZroRs9YW3xA@public.gmane.org> wrote:
> >> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> >> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> >> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> >> >>> and CALIPSO/IPv6 services.
> >> >>>
> >> >>> Signed-off-by: Richard Haines <richard_c_haines-FhtRXb7CoQBt1OO0OYaSVA@public.gmane.org>
> >> >>
> >> >> LGTM too, thanks!
> >> >>
> >> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >> >
> >> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
> >>
> >> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
> >> v7 patchset) in selinux/next and did a quick sanity test on the kernel
> >> (booted, no basic SELinux regressions). Additional testing help is
> >> always appreciated ...
> >
> > I'll try it early next week.
> >
> > Any ideas on when this is going to appear on Dave's net-next tree?
> > We have a lot of SCTP changes to be posted on this cycle and would be
> > nice if we could avoid merge conflicts.
>
> It's merged into the SELinux tree, next branch; see the links below.
> Last I checked DaveM doesn't pull the selinux/next into his net-next
> tree (that would be a little funny for historical reasons).
>
> Any idea on how bad the merge conflicts are?
I know about 5 patchsets that we are cooking. For 4 of them I think it
would be mostly fine, perhaps one conflict here and there. But the
other one is a refactoring on MTU handling and it touches lots of
places that 92c49e12646e4 ("sctp: Add ip option support") also
touched, like in the chunk below:
+++ b/include/net/sctp/sctp.h
@@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
{
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
int frag = pmtu;
- frag -= sp->pf->af->net_header_len;
+ frag -= af->ip_options_len(asoc->base.sk);
+ frag -= af->net_header_len;
In the refactor I'm removing this function from here and adding a
similar, not quite the same but similar, in a .c file.
I post the mtu patchset as RFC next week so we can know better.
Marcelo
>
> >> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
> >> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>
> --
> paul moore
> www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-24 0:56 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-24 0:56 UTC (permalink / raw)
To: linux-security-module
On Fri, Feb 23, 2018 at 11:11:50AM -0500, Paul Moore wrote:
> On Thu, Feb 22, 2018 at 9:40 PM, Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> > On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
> >> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
> >> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
> >> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> >> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> >> >>> and CALIPSO/IPv6 services.
> >> >>>
> >> >>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> >> >>
> >> >> LGTM too, thanks!
> >> >>
> >> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> >> >
> >> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
> >>
> >> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
> >> v7 patchset) in selinux/next and did a quick sanity test on the kernel
> >> (booted, no basic SELinux regressions). Additional testing help is
> >> always appreciated ...
> >
> > I'll try it early next week.
> >
> > Any ideas on when this is going to appear on Dave's net-next tree?
> > We have a lot of SCTP changes to be posted on this cycle and would be
> > nice if we could avoid merge conflicts.
>
> It's merged into the SELinux tree, next branch; see the links below.
> Last I checked DaveM doesn't pull the selinux/next into his net-next
> tree (that would be a little funny for historical reasons).
>
> Any idea on how bad the merge conflicts are?
I know about 5 patchsets that we are cooking. For 4 of them I think it
would be mostly fine, perhaps one conflict here and there. But the
other one is a refactoring on MTU handling and it touches lots of
places that 92c49e12646e4 ("sctp: Add ip option support") also
touched, like in the chunk below:
+++ b/include/net/sctp/sctp.h
@@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
{
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
int frag = pmtu;
- frag -= sp->pf->af->net_header_len;
+ frag -= af->ip_options_len(asoc->base.sk);
+ frag -= af->net_header_len;
In the refactor I'm removing this function from here and adding a
similar, not quite the same but similar, in a .c file.
I post the mtu patchset as RFC next week so we can know better.
Marcelo
>
> >> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
> >> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>
> --
> paul moore
> www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-24 0:56 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-24 0:56 UTC (permalink / raw)
To: Paul Moore
Cc: Richard Haines, selinux, netdev, linux-sctp,
linux-security-module, Vlad Yasevich, nhorman, Stephen Smalley,
Eric Paris, casey, James Morris
On Fri, Feb 23, 2018 at 11:11:50AM -0500, Paul Moore wrote:
> On Thu, Feb 22, 2018 at 9:40 PM, Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> > On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
> >> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
> >> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
> >> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> >> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> >> >>> and CALIPSO/IPv6 services.
> >> >>>
> >> >>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> >> >>
> >> >> LGTM too, thanks!
> >> >>
> >> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> >> >
> >> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
> >>
> >> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
> >> v7 patchset) in selinux/next and did a quick sanity test on the kernel
> >> (booted, no basic SELinux regressions). Additional testing help is
> >> always appreciated ...
> >
> > I'll try it early next week.
> >
> > Any ideas on when this is going to appear on Dave's net-next tree?
> > We have a lot of SCTP changes to be posted on this cycle and would be
> > nice if we could avoid merge conflicts.
>
> It's merged into the SELinux tree, next branch; see the links below.
> Last I checked DaveM doesn't pull the selinux/next into his net-next
> tree (that would be a little funny for historical reasons).
>
> Any idea on how bad the merge conflicts are?
I know about 5 patchsets that we are cooking. For 4 of them I think it
would be mostly fine, perhaps one conflict here and there. But the
other one is a refactoring on MTU handling and it touches lots of
places that 92c49e12646e4 ("sctp: Add ip option support") also
touched, like in the chunk below:
+++ b/include/net/sctp/sctp.h
@@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
{
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
int frag = pmtu;
- frag -= sp->pf->af->net_header_len;
+ frag -= af->ip_options_len(asoc->base.sk);
+ frag -= af->net_header_len;
In the refactor I'm removing this function from here and adding a
similar, not quite the same but similar, in a .c file.
I post the mtu patchset as RFC next week so we can know better.
Marcelo
>
> >> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
> >> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>
> --
> paul moore
> www.paul-moore.com
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V7 2/4] sctp: Add ip option support
@ 2018-02-24 0:56 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2018-02-24 0:56 UTC (permalink / raw)
To: linux-security-module
On Fri, Feb 23, 2018 at 11:11:50AM -0500, Paul Moore wrote:
> On Thu, Feb 22, 2018 at 9:40 PM, Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> > On Thu, Feb 22, 2018 at 06:08:05PM -0500, Paul Moore wrote:
> >> On Wed, Feb 21, 2018 at 3:45 PM, Paul Moore <paul@paul-moore.com> wrote:
> >> > On February 21, 2018 9:33:51 AM Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
> >> >> On Tue, Feb 20, 2018 at 07:15:27PM +0000, Richard Haines wrote:
> >> >>> Add ip option support to allow LSM security modules to utilise CIPSO/IPv4
> >> >>> and CALIPSO/IPv6 services.
> >> >>>
> >> >>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> >> >>
> >> >> LGTM too, thanks!
> >> >>
> >> >> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> >> >
> >> > I agree, thanks everyone for all the work, review, and patience behind this patchset! I'll work on merging this into selinux/next and I'll send a note when it's done.
> >>
> >> I just merged the four patches (1,3,4 from the v6 patchset, 2 from the
> >> v7 patchset) in selinux/next and did a quick sanity test on the kernel
> >> (booted, no basic SELinux regressions). Additional testing help is
> >> always appreciated ...
> >
> > I'll try it early next week.
> >
> > Any ideas on when this is going to appear on Dave's net-next tree?
> > We have a lot of SCTP changes to be posted on this cycle and would be
> > nice if we could avoid merge conflicts.
>
> It's merged into the SELinux tree, next branch; see the links below.
> Last I checked DaveM doesn't pull the selinux/next into his net-next
> tree (that would be a little funny for historical reasons).
>
> Any idea on how bad the merge conflicts are?
I know about 5 patchsets that we are cooking. For 4 of them I think it
would be mostly fine, perhaps one conflict here and there. But the
other one is a refactoring on MTU handling and it touches lots of
places that 92c49e12646e4 ("sctp: Add ip option support") also
touched, like in the chunk below:
+++ b/include/net/sctp/sctp.h
@@ -441,9 +441,11 @@ static inline int sctp_list_single_entry(struct list_head *head)
static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
{
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+ struct sctp_af *af = sp->pf->af;
int frag = pmtu;
- frag -= sp->pf->af->net_header_len;
+ frag -= af->ip_options_len(asoc->base.sk);
+ frag -= af->net_header_len;
In the refactor I'm removing this function from here and adding a
similar, not quite the same but similar, in a .c file.
I post the mtu patchset as RFC next week so we can know better.
Marcelo
>
> >> * git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
> >> * https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
>
> --
> paul moore
> www.paul-moore.com
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2018-02-24 0:56 UTC | newest]
Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-20 19:15 [PATCH V7 2/4] sctp: Add ip option support Richard Haines via Selinux
2018-02-20 19:15 ` Richard Haines
2018-02-20 19:15 ` Richard Haines
2018-02-20 19:15 ` Richard Haines
[not found] ` <20180220191527.14307-1-richard_c_haines-FhtRXb7CoQBt1OO0OYaSVA@public.gmane.org>
2018-02-21 3:44 ` Neil Horman
2018-02-21 3:44 ` Neil Horman
2018-02-21 3:44 ` Neil Horman
2018-02-21 3:44 ` Neil Horman
2018-02-21 14:33 ` Marcelo Ricardo Leitner
2018-02-21 14:33 ` Marcelo Ricardo Leitner
2018-02-21 14:33 ` Marcelo Ricardo Leitner
2018-02-21 14:33 ` Marcelo Ricardo Leitner
[not found] ` <20180221143345.GA3888-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2018-02-21 20:45 ` Paul Moore
2018-02-21 20:45 ` Paul Moore
2018-02-21 20:45 ` Paul Moore
2018-02-21 20:45 ` Paul Moore
[not found] ` <161ba1d60d8.2781.85c95baa4474aabc7814e68940a78392-r2n+y4ga6xFZroRs9YW3xA@public.gmane.org>
2018-02-22 23:08 ` Paul Moore
2018-02-22 23:08 ` Paul Moore
2018-02-22 23:08 ` Paul Moore
2018-02-22 23:08 ` Paul Moore
[not found] ` <CAHC9VhSnPku5SYnNkyUqvi46OpzPZKbJf+fxeCR0y3ym0zcMYA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2018-02-23 2:40 ` Marcelo Ricardo Leitner
2018-02-23 2:40 ` Marcelo Ricardo Leitner
2018-02-23 2:40 ` Marcelo Ricardo Leitner
2018-02-23 2:40 ` Marcelo Ricardo Leitner
[not found] ` <20180223024010.GE4375-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2018-02-23 16:11 ` Paul Moore
2018-02-23 16:11 ` Paul Moore
2018-02-23 16:11 ` Paul Moore
2018-02-23 16:11 ` Paul Moore
[not found] ` <CAHC9VhT_1GQJPoOBN0ambF=F1+ZXhoYB3mMc8kzgCFOep+hsCg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2018-02-24 0:56 ` Marcelo Ricardo Leitner
2018-02-24 0:56 ` Marcelo Ricardo Leitner
2018-02-24 0:56 ` Marcelo Ricardo Leitner
2018-02-24 0:56 ` Marcelo Ricardo Leitner
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.