summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-06 15:39:26 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-06 15:39:26 -0700
commit9eda2d2dca830f0f8923b1f377d0fb70f576af1d (patch)
tree5bdc06d14182e67ebdf20e5543de2a407563662f
parent6ad11bdd57ad31182850a54235f0e947cbfd5ad0 (diff)
parent6b6bc6205d98796361962ee282a063f18ba8dc57 (diff)
downloadlinux-9eda2d2dca830f0f8923b1f377d0fb70f576af1d.tar.gz
linux-9eda2d2dca830f0f8923b1f377d0fb70f576af1d.tar.bz2
linux-9eda2d2dca830f0f8923b1f377d0fb70f576af1d.zip
Merge tag 'selinux-pr-20180403' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull SELinux updates from Paul Moore: "A bigger than usual pull request for SELinux, 13 patches (lucky!) along with a scary looking diffstat. Although if you look a bit closer, excluding the usual minor tweaks/fixes, there are really only two significant changes in this pull request: the addition of proper SELinux access controls for SCTP and the encapsulation of a lot of internal SELinux state. The SCTP changes are the result of a multi-month effort (maybe even a year or longer?) between the SELinux folks and the SCTP folks to add proper SELinux controls. A special thanks go to Richard for seeing this through and keeping the effort moving forward. The state encapsulation work is a bit of janitorial work that came out of some early work on SELinux namespacing. The question of namespacing is still an open one, but I believe there is some real value in the encapsulation work so we've split that out and are now sending that up to you" * tag 'selinux-pr-20180403' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinux: wrap AVC state selinux: wrap selinuxfs state selinux: fix handling of uninitialized selinux state in get_bools/classes selinux: Update SELinux SCTP documentation selinux: Fix ltp test connect-syscall failure selinux: rename the {is,set}_enforcing() functions selinux: wrap global selinux state selinux: fix typo in selinux_netlbl_sctp_sk_clone declaration selinux: Add SCTP support sctp: Add LSM hooks sctp: Add ip option support security: Add support for SCTP security hooks netlabel: If PF_INET6, check sk_buff ip header version
-rw-r--r--Documentation/security/LSM-sctp.rst175
-rw-r--r--Documentation/security/SELinux-sctp.rst158
-rw-r--r--include/linux/lsm_hooks.h36
-rw-r--r--include/linux/security.h25
-rw-r--r--include/net/sctp/sctp.h4
-rw-r--r--include/net/sctp/structs.h12
-rw-r--r--include/uapi/linux/sctp.h1
-rw-r--r--net/netlabel/netlabel_unlabeled.c10
-rw-r--r--net/sctp/chunk.c10
-rw-r--r--net/sctp/ipv6.c45
-rw-r--r--net/sctp/output.c34
-rw-r--r--net/sctp/protocol.c43
-rw-r--r--net/sctp/sm_make_chunk.c12
-rw-r--r--net/sctp/sm_statefuns.c18
-rw-r--r--net/sctp/socket.c70
-rw-r--r--security/security.c22
-rw-r--r--security/selinux/avc.c282
-rw-r--r--security/selinux/hooks.c922
-rw-r--r--security/selinux/ibpkey.c3
-rw-r--r--security/selinux/include/avc.h38
-rw-r--r--security/selinux/include/avc_ss.h9
-rw-r--r--security/selinux/include/classmap.h2
-rw-r--r--security/selinux/include/conditional.h11
-rw-r--r--security/selinux/include/netlabel.h22
-rw-r--r--security/selinux/include/objsec.h6
-rw-r--r--security/selinux/include/security.h231
-rw-r--r--security/selinux/netif.c2
-rw-r--r--security/selinux/netlabel.c148
-rw-r--r--security/selinux/netnode.c4
-rw-r--r--security/selinux/netport.c2
-rw-r--r--security/selinux/selinuxfs.c493
-rw-r--r--security/selinux/ss/avtab.c9
-rw-r--r--security/selinux/ss/avtab.h3
-rw-r--r--security/selinux/ss/ebitmap.c7
-rw-r--r--security/selinux/ss/ebitmap.h3
-rw-r--r--security/selinux/ss/hashtab.c8
-rw-r--r--security/selinux/ss/hashtab.h4
-rw-r--r--security/selinux/ss/mls.c72
-rw-r--r--security/selinux/ss/mls.h38
-rw-r--r--security/selinux/ss/services.c1100
-rw-r--r--security/selinux/ss/services.h24
-rw-r--r--security/selinux/ss/status.c47
-rw-r--r--security/selinux/xfrm.c23
43 files changed, 2936 insertions, 1252 deletions
diff --git a/Documentation/security/LSM-sctp.rst b/Documentation/security/LSM-sctp.rst
new file mode 100644
index 000000000000..6e5a3925a860
--- /dev/null
+++ b/Documentation/security/LSM-sctp.rst
@@ -0,0 +1,175 @@
+SCTP LSM Support
+================
+
+For security module support, three SCTP specific hooks have been implemented::
+
+ security_sctp_assoc_request()
+ security_sctp_bind_connect()
+ security_sctp_sk_clone()
+
+Also the following security hook has been utilised::
+
+ security_inet_conn_established()
+
+The usage of these hooks are described below with the SELinux implementation
+described in ``Documentation/security/SELinux-sctp.rst``
+
+
+security_sctp_assoc_request()
+-----------------------------
+Passes the ``@ep`` and ``@chunk->skb`` of the association INIT packet to the
+security module. Returns 0 on success, error on failure.
+::
+
+ @ep - pointer to sctp endpoint structure.
+ @skb - pointer to skbuff of association packet.
+
+
+security_sctp_bind_connect()
+-----------------------------
+Passes one or more ipv4/ipv6 addresses to the security module for validation
+based on the ``@optname`` that will result in either a bind or connect
+service as shown in the permission check tables below.
+Returns 0 on success, error on failure.
+::
+
+ @sk - Pointer to sock structure.
+ @optname - Name of the option to validate.
+ @address - One or more ipv4 / ipv6 addresses.
+ @addrlen - The total length of address(s). This is calculated on each
+ ipv4 or ipv6 address using sizeof(struct sockaddr_in) or
+ sizeof(struct sockaddr_in6).
+
+ ------------------------------------------------------------------
+ | BIND Type Checks |
+ | @optname | @address contains |
+ |----------------------------|-----------------------------------|
+ | SCTP_SOCKOPT_BINDX_ADD | One or more ipv4 / ipv6 addresses |
+ | SCTP_PRIMARY_ADDR | Single ipv4 or ipv6 address |
+ | SCTP_SET_PEER_PRIMARY_ADDR | Single ipv4 or ipv6 address |
+ ------------------------------------------------------------------
+
+ ------------------------------------------------------------------
+ | CONNECT Type Checks |
+ | @optname | @address contains |
+ |----------------------------|-----------------------------------|
+ | SCTP_SOCKOPT_CONNECTX | One or more ipv4 / ipv6 addresses |
+ | SCTP_PARAM_ADD_IP | One or more ipv4 / ipv6 addresses |
+ | SCTP_SENDMSG_CONNECT | Single ipv4 or ipv6 address |
+ | SCTP_PARAM_SET_PRIMARY | Single ipv4 or ipv6 address |
+ ------------------------------------------------------------------
+
+A summary of the ``@optname`` entries is as follows::
+
+ SCTP_SOCKOPT_BINDX_ADD - Allows additional bind addresses to be
+ associated after (optionally) calling
+ bind(3).
+ sctp_bindx(3) adds a set of bind
+ addresses on a socket.
+
+ SCTP_SOCKOPT_CONNECTX - Allows the allocation of multiple
+ addresses for reaching a peer
+ (multi-homed).
+ sctp_connectx(3) initiates a connection
+ on an SCTP socket using multiple
+ destination addresses.
+
+ SCTP_SENDMSG_CONNECT - Initiate a connection that is generated by a
+ sendmsg(2) or sctp_sendmsg(3) on a new asociation.
+
+ SCTP_PRIMARY_ADDR - Set local primary address.
+
+ SCTP_SET_PEER_PRIMARY_ADDR - Request peer sets address as
+ association primary.
+
+ SCTP_PARAM_ADD_IP - These are used when Dynamic Address
+ SCTP_PARAM_SET_PRIMARY - Reconfiguration is enabled as explained below.
+
+
+To support Dynamic Address Reconfiguration the following parameters must be
+enabled on both endpoints (or use the appropriate **setsockopt**\(2))::
+
+ /proc/sys/net/sctp/addip_enable
+ /proc/sys/net/sctp/addip_noauth_enable
+
+then the following *_PARAM_*'s are sent to the peer in an
+ASCONF chunk when the corresponding ``@optname``'s are present::
+
+ @optname ASCONF Parameter
+ ---------- ------------------
+ SCTP_SOCKOPT_BINDX_ADD -> SCTP_PARAM_ADD_IP
+ SCTP_SET_PEER_PRIMARY_ADDR -> SCTP_PARAM_SET_PRIMARY
+
+
+security_sctp_sk_clone()
+-------------------------
+Called whenever a new socket is created by **accept**\(2)
+(i.e. a TCP style socket) or when a socket is 'peeled off' e.g userspace
+calls **sctp_peeloff**\(3).
+::
+
+ @ep - pointer to current sctp endpoint structure.
+ @sk - pointer to current sock structure.
+ @sk - pointer to new sock structure.
+
+
+security_inet_conn_established()
+---------------------------------
+Called when a COOKIE ACK is received::
+
+ @sk - pointer to sock structure.
+ @skb - pointer to skbuff of the COOKIE ACK packet.
+
+
+Security Hooks used for Association Establishment
+=================================================
+The following diagram shows the use of ``security_sctp_bind_connect()``,
+``security_sctp_assoc_request()``, ``security_inet_conn_established()`` when
+establishing an association.
+::
+
+ SCTP endpoint "A" SCTP endpoint "Z"
+ ================= =================
+ sctp_sf_do_prm_asoc()
+ Association setup can be initiated
+ by a connect(2), sctp_connectx(3),
+ sendmsg(2) or sctp_sendmsg(3).
+ These will result in a call to
+ security_sctp_bind_connect() to
+ initiate an association to
+ SCTP peer endpoint "Z".
+ INIT --------------------------------------------->
+ sctp_sf_do_5_1B_init()
+ Respond to an INIT chunk.
+ SCTP peer endpoint "A" is
+ asking for an association. Call
+ security_sctp_assoc_request()
+ to set the peer label if first
+ association.
+ If not first association, check
+ whether allowed, IF so send:
+ <----------------------------------------------- INIT ACK
+ | ELSE audit event and silently
+ | discard the packet.
+ |
+ COOKIE ECHO ------------------------------------------>
+ |
+ |
+ |
+ <------------------------------------------- COOKIE ACK
+ | |
+ sctp_sf_do_5_1E_ca |
+ Call security_inet_conn_established() |
+ to set the peer label. |
+ | |
+ | If SCTP_SOCKET_TCP or peeled off
+ | socket security_sctp_sk_clone() is
+ | called to clone the new socket.
+ | |
+ ESTABLISHED ESTABLISHED
+ | |
+ ------------------------------------------------------------------
+ | Association Established |
+ ------------------------------------------------------------------
+
+
diff --git a/Documentation/security/SELinux-sctp.rst b/Documentation/security/SELinux-sctp.rst
new file mode 100644
index 000000000000..a332cb1c5334
--- /dev/null
+++ b/Documentation/security/SELinux-sctp.rst
@@ -0,0 +1,158 @@
+SCTP SELinux Support
+=====================
+
+Security Hooks
+===============
+
+``Documentation/security/LSM-sctp.rst`` describes the following SCTP security
+hooks with the SELinux specifics expanded below::
+
+ security_sctp_assoc_request()
+ security_sctp_bind_connect()
+ security_sctp_sk_clone()
+ security_inet_conn_established()
+
+
+security_sctp_assoc_request()
+-----------------------------
+Passes the ``@ep`` and ``@chunk->skb`` of the association INIT packet to the
+security module. Returns 0 on success, error on failure.
+::
+
+ @ep - pointer to sctp endpoint structure.
+ @skb - pointer to skbuff of association packet.
+
+The security module performs the following operations:
+ IF this is the first association on ``@ep->base.sk``, then set the peer
+ sid to that in ``@skb``. This will ensure there is only one peer sid
+ assigned to ``@ep->base.sk`` that may support multiple associations.
+
+ ELSE validate the ``@ep->base.sk peer_sid`` against the ``@skb peer sid``
+ to determine whether the association should be allowed or denied.
+
+ Set the sctp ``@ep sid`` to socket's sid (from ``ep->base.sk``) with
+ MLS portion taken from ``@skb peer sid``. This will be used by SCTP
+ TCP style sockets and peeled off connections as they cause a new socket
+ to be generated.
+
+ If IP security options are configured (CIPSO/CALIPSO), then the ip
+ options are set on the socket.
+
+
+security_sctp_bind_connect()
+-----------------------------
+Checks permissions required for ipv4/ipv6 addresses based on the ``@optname``
+as follows::
+
+ ------------------------------------------------------------------
+ | BIND Permission Checks |
+ | @optname | @address contains |
+ |----------------------------|-----------------------------------|
+ | SCTP_SOCKOPT_BINDX_ADD | One or more ipv4 / ipv6 addresses |
+ | SCTP_PRIMARY_ADDR | Single ipv4 or ipv6 address |
+ | SCTP_SET_PEER_PRIMARY_ADDR | Single ipv4 or ipv6 address |
+ ------------------------------------------------------------------
+
+ ------------------------------------------------------------------
+ | CONNECT Permission Checks |
+ | @optname | @address contains |
+ |----------------------------|-----------------------------------|
+ | SCTP_SOCKOPT_CONNECTX | One or more ipv4 / ipv6 addresses |
+ | SCTP_PARAM_ADD_IP | One or more ipv4 / ipv6 addresses |
+ | SCTP_SENDMSG_CONNECT | Single ipv4 or ipv6 address |
+ | SCTP_PARAM_SET_PRIMARY | Single ipv4 or ipv6 address |
+ ------------------------------------------------------------------
+
+
+``Documentation/security/LSM-sctp.rst`` gives a summary of the ``@optname``
+entries and also describes ASCONF chunk processing when Dynamic Address
+Reconfiguration is enabled.
+
+
+security_sctp_sk_clone()
+-------------------------
+Called whenever a new socket is created by **accept**\(2) (i.e. a TCP style
+socket) or when a socket is 'peeled off' e.g userspace calls
+**sctp_peeloff**\(3). ``security_sctp_sk_clone()`` will set the new
+sockets sid and peer sid to that contained in the ``@ep sid`` and
+``@ep peer sid`` respectively.
+::
+
+ @ep - pointer to current sctp endpoint structure.
+ @sk - pointer to current sock structure.
+ @sk - pointer to new sock structure.
+
+
+security_inet_conn_established()
+---------------------------------
+Called when a COOKIE ACK is received where it sets the connection's peer sid
+to that in ``@skb``::
+
+ @sk - pointer to sock structure.
+ @skb - pointer to skbuff of the COOKIE ACK packet.
+
+
+Policy Statements
+==================
+The following class and permissions to support SCTP are available within the
+kernel::
+
+ class sctp_socket inherits socket { node_bind }
+
+whenever the following policy capability is enabled::
+
+ policycap extended_socket_class;
+
+SELinux SCTP support adds the ``name_connect`` permission for connecting
+to a specific port type and the ``association`` permission that is explained
+in the section below.
+
+If userspace tools have been updated, SCTP will support the ``portcon``
+statement as shown in the following example::
+
+ portcon sctp 1024-1036 system_u:object_r:sctp_ports_t:s0
+
+
+SCTP Peer Labeling
+===================
+An SCTP socket will only have one peer label assigned to it. This will be
+assigned during the establishment of the first association. Any further
+associations on this socket will have their packet peer label compared to
+the sockets peer label, and only if they are different will the
+``association`` permission be validated. This is validated by checking the
+socket peer sid against the received packets peer sid to determine whether
+the association should be allowed or denied.
+
+NOTES:
+ 1) If peer labeling is not enabled, then the peer context will always be
+ ``SECINITSID_UNLABELED`` (``unlabeled_t`` in Reference Policy).
+
+ 2) As SCTP can support more than one transport address per endpoint
+ (multi-homing) on a single socket, it is possible to configure policy
+ and NetLabel to provide different peer labels for each of these. As the
+ socket peer label is determined by the first associations transport
+ address, it is recommended that all peer labels are consistent.
+
+ 3) **getpeercon**\(3) may be used by userspace to retrieve the sockets peer
+ context.
+
+ 4) While not SCTP specific, be aware when using NetLabel that if a label
+ is assigned to a specific interface, and that interface 'goes down',
+ then the NetLabel service will remove the entry. Therefore ensure that
+ the network startup scripts call **netlabelctl**\(8) to set the required
+ label (see **netlabel-config**\(8) helper script for details).
+
+ 5) The NetLabel SCTP peer labeling rules apply as discussed in the following
+ set of posts tagged "netlabel" at: http://www.paul-moore.com/blog/t.
+
+ 6) CIPSO is only supported for IPv4 addressing: ``socket(AF_INET, ...)``
+ CALIPSO is only supported for IPv6 addressing: ``socket(AF_INET6, ...)``
+
+ Note the following when testing CIPSO/CALIPSO:
+ a) CIPSO will send an ICMP packet if an SCTP packet cannot be
+ delivered because of an invalid label.
+ b) CALIPSO does not send an ICMP packet, just silently discards it.
+
+ 7) IPSEC is not supported as RFC 3554 - sctp/ipsec support has not been
+ implemented in userspace (**racoon**\(8) or **ipsec_pluto**\(8)),
+ although the kernel supports SCTP/IPSEC.
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index bde167fa2c51..6e6951b42be5 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -906,6 +906,33 @@
* associated with the TUN device's security structure.
* @security pointer to the TUN devices's security structure.
*
+ * Security hooks for SCTP
+ *
+ * @sctp_assoc_request:
+ * Passes the @ep and @chunk->skb of the association INIT packet to
+ * the security module.
+ * @ep pointer to sctp endpoint structure.
+ * @skb pointer to skbuff of association packet.
+ * Return 0 on success, error on failure.
+ * @sctp_bind_connect:
+ * Validiate permissions required for each address associated with sock
+ * @sk. Depending on @optname, the addresses will be treated as either
+ * for a connect or bind service. The @addrlen is calculated on each
+ * ipv4 and ipv6 address using sizeof(struct sockaddr_in) or
+ * sizeof(struct sockaddr_in6).
+ * @sk pointer to sock structure.
+ * @optname name of the option to validate.
+ * @address list containing one or more ipv4/ipv6 addresses.
+ * @addrlen total length of address(s).
+ * Return 0 on success, error on failure.
+ * @sctp_sk_clone:
+ * Called whenever a new socket is created by accept(2) (i.e. a TCP
+ * style socket) or when a socket is 'peeled off' e.g userspace
+ * calls sctp_peeloff(3).
+ * @ep pointer to current sctp endpoint structure.
+ * @sk pointer to current sock structure.
+ * @sk pointer to new sock structure.
+ *
* Security hooks for Infiniband
*
* @ib_pkey_access:
@@ -1665,6 +1692,12 @@ union security_list_options {
int (*tun_dev_attach_queue)(void *security);
int (*tun_dev_attach)(struct sock *sk, void *security);
int (*tun_dev_open)(void *security);
+ int (*sctp_assoc_request)(struct sctp_endpoint *ep,
+ struct sk_buff *skb);
+ int (*sctp_bind_connect)(struct sock *sk, int optname,
+ struct sockaddr *address, int addrlen);
+ void (*sctp_sk_clone)(struct sctp_endpoint *ep, struct sock *sk,
+ struct sock *newsk);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND
@@ -1914,6 +1947,9 @@ struct security_hook_heads {
struct list_head tun_dev_attach_queue;
struct list_head tun_dev_attach;
struct list_head tun_dev_open;
+ struct list_head sctp_assoc_request;
+ struct list_head sctp_bind_connect;
+ struct list_head sctp_sk_clone;
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND
struct list_head ib_pkey_access;
diff --git a/include/linux/security.h b/include/linux/security.h
index 128e1e4a5346..17ffd1ef6074 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -112,6 +112,7 @@ struct xfrm_policy;
struct xfrm_state;
struct xfrm_user_sec_ctx;
struct seq_file;
+struct sctp_endpoint;
#ifdef CONFIG_MMU
extern unsigned long mmap_min_addr;
@@ -1226,6 +1227,11 @@ int security_tun_dev_create(void);
int security_tun_dev_attach_queue(void *security);
int security_tun_dev_attach(struct sock *sk, void *security);
int security_tun_dev_open(void *security);
+int security_sctp_assoc_request(struct sctp_endpoint *ep, struct sk_buff *skb);
+int security_sctp_bind_connect(struct sock *sk, int optname,
+ struct sockaddr *address, int addrlen);
+void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
+ struct sock *newsk);
#else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct sock *sock,
@@ -1418,6 +1424,25 @@ static inline int security_tun_dev_open(void *security)
{
return 0;
}
+
+static inline int security_sctp_assoc_request(struct sctp_endpoint *ep,
+ struct sk_buff *skb)
+{
+ return 0;
+}
+
+static inline int security_sctp_bind_connect(struct sock *sk, int optname,
+ struct sockaddr *address,
+ int addrlen)
+{
+ return 0;
+}
+
+static inline void security_sctp_sk_clone(struct sctp_endpoint *ep,
+ struct sock *sk,
+ struct sock *newsk)
+{
+}
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 72c5b8fc3232..28b996d63490 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -432,9 +432,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 c63249ea34c3..a0ec462bc1a9 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;
};
@@ -1320,6 +1322,16 @@ struct sctp_endpoint {
reconf_enable:1;
__u8 strreset_enable;
+
+ /* Security identifiers from incoming (INIT). These are set by
+ * security_sctp_assoc_request(). These will only be used by
+ * SCTP TCP type sockets and peeled off connections as they
+ * cause a new socket to be generated. security_sctp_sk_clone()
+ * will then plug these into the new socket.
+ */
+
+ u32 secid;
+ u32 peer_secid;
};
/* Recover the outter endpoint structure. */
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index afd4346386e0..b64d583bf053 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -127,6 +127,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_STREAM_SCHEDULER 123
#define SCTP_STREAM_SCHEDULER_VALUE 124
#define SCTP_INTERLEAVING_SUPPORTED 125
+#define SCTP_SENDMSG_CONNECT 126
/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE 0x0000
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 22dc1b9d6362..c070dfc0190a 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -1472,6 +1472,16 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
iface = rcu_dereference(netlbl_unlhsh_def);
if (iface == NULL || !iface->valid)
goto unlabel_getattr_nolabel;
+
+#if IS_ENABLED(CONFIG_IPV6)
+ /* When resolving a fallback label, check the sk_buff version as
+ * it is possible (e.g. SCTP) to have family = PF_INET6 while
+ * receiving ip_hdr(skb)->version = 4.
+ */
+ if (family == PF_INET6 && ip_hdr(skb)->version == 4)
+ family = PF_INET;
+#endif /* IPv6 */
+
switch (family) {
case PF_INET: {
struct iphdr *hdr4;
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index f889a84f264d..be296d633e95 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -172,6 +172,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);
@@ -190,9 +192,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 0d873c58e516..6dd976c8ab61 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 so