mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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
This commit is contained in:
@@ -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 |
|
||||
------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
+7
-3
@@ -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
|
||||
|
||||
+38
-7
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
+21
-13
@@ -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;
|
||||
}
|
||||
|
||||
@@ -187,6 +187,45 @@ 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);
|
||||
struct ip_options_rcu *inet_opt;
|
||||
int len = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
inet_opt = rcu_dereference(inet->inet_opt);
|
||||
if (inet_opt)
|
||||
len = inet_opt->opt.optlen;
|
||||
|
||||
rcu_read_unlock();
|
||||
return len;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
@@ -538,6 +577,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;
|
||||
@@ -956,6 +997,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
|
||||
};
|
||||
|
||||
@@ -1040,6 +1082,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,
|
||||
|
||||
@@ -3098,6 +3098,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
|
||||
if (af->is_any(&addr))
|
||||
memcpy(&addr, &asconf->source, sizeof(addr));
|
||||
|
||||
if (security_sctp_bind_connect(asoc->ep->base.sk,
|
||||
SCTP_PARAM_ADD_IP,
|
||||
(struct sockaddr *)&addr,
|
||||
af->sockaddr_len))
|
||||
return SCTP_ERROR_REQ_REFUSED;
|
||||
|
||||
/* ADDIP 4.3 D9) If an endpoint receives an ADD IP address
|
||||
* request and does not have the local resources to add this
|
||||
* new address to the association, it MUST return an Error
|
||||
@@ -3164,6 +3170,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
|
||||
if (af->is_any(&addr))
|
||||
memcpy(&addr.v4, sctp_source(asconf), sizeof(addr));
|
||||
|
||||
if (security_sctp_bind_connect(asoc->ep->base.sk,
|
||||
SCTP_PARAM_SET_PRIMARY,
|
||||
(struct sockaddr *)&addr,
|
||||
af->sockaddr_len))
|
||||
return SCTP_ERROR_REQ_REFUSED;
|
||||
|
||||
peer = sctp_assoc_lookup_paddr(asoc, &addr);
|
||||
if (!peer)
|
||||
return SCTP_ERROR_DNS_FAILED;
|
||||
|
||||
@@ -321,6 +321,11 @@ enum sctp_disposition sctp_sf_do_5_1B_init(struct net *net,
|
||||
struct sctp_packet *packet;
|
||||
int len;
|
||||
|
||||
/* Update socket peer label if first association. */
|
||||
if (security_sctp_assoc_request((struct sctp_endpoint *)ep,
|
||||
chunk->skb))
|
||||
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
|
||||
|
||||
/* 6.10 Bundling
|
||||
* An endpoint MUST NOT bundle INIT, INIT ACK or
|
||||
* SHUTDOWN COMPLETE with any other chunks.
|
||||
@@ -922,6 +927,9 @@ enum sctp_disposition sctp_sf_do_5_1E_ca(struct net *net,
|
||||
*/
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());
|
||||
|
||||
/* Set peer label for connection. */
|
||||
security_inet_conn_established(ep->base.sk, chunk->skb);
|
||||
|
||||
/* RFC 2960 5.1 Normal Establishment of an Association
|
||||
*
|
||||
* E) Upon reception of the COOKIE ACK, endpoint "A" will move
|
||||
@@ -1459,6 +1467,11 @@ static enum sctp_disposition sctp_sf_do_unexpected_init(
|
||||
struct sctp_packet *packet;
|
||||
int len;
|
||||
|
||||
/* Update socket peer label if first association. */
|
||||
if (security_sctp_assoc_request((struct sctp_endpoint *)ep,
|
||||
chunk->skb))
|
||||
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
|
||||
|
||||
/* 6.10 Bundling
|
||||
* An endpoint MUST NOT bundle INIT, INIT ACK or
|
||||
* SHUTDOWN COMPLETE with any other chunks.
|
||||
@@ -2145,6 +2158,11 @@ enum sctp_disposition sctp_sf_do_5_2_4_dupcook(
|
||||
}
|
||||
}
|
||||
|
||||
/* Update socket peer label if first association. */
|
||||
if (security_sctp_assoc_request((struct sctp_endpoint *)ep,
|
||||
chunk->skb))
|
||||
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
|
||||
|
||||
/* Set temp so that it won't be added into hashtable */
|
||||
new_asoc->temp = 1;
|
||||
|
||||
|
||||
+66
-4
@@ -1046,6 +1046,12 @@ static int sctp_setsockopt_bindx(struct sock *sk,
|
||||
/* Do the work. */
|
||||
switch (op) {
|
||||
case SCTP_BINDX_ADD_ADDR:
|
||||
/* Allow security module to validate bindx addresses. */
|
||||
err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_BINDX_ADD,
|
||||
(struct sockaddr *)kaddrs,
|
||||
addrs_size);
|
||||
if (err)
|
||||
goto out;
|
||||
err = sctp_bindx_add(sk, kaddrs, addrcnt);
|
||||
if (err)
|
||||
goto out;
|
||||
@@ -1255,6 +1261,7 @@ static int __sctp_connect(struct sock *sk,
|
||||
|
||||
if (assoc_id)
|
||||
*assoc_id = asoc->assoc_id;
|
||||
|
||||
err = sctp_wait_for_connect(asoc, &timeo);
|
||||
/* Note: the asoc may be freed after the return of
|
||||
* sctp_wait_for_connect.
|
||||
@@ -1350,7 +1357,16 @@ static int __sctp_setsockopt_connectx(struct sock *sk,
|
||||
if (unlikely(IS_ERR(kaddrs)))
|
||||
return PTR_ERR(kaddrs);
|
||||
|
||||
/* Allow security module to validate connectx addresses. */
|
||||
err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_CONNECTX,
|
||||
(struct sockaddr *)kaddrs,
|
||||
addrs_size);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id);
|
||||
|
||||
out_free:
|
||||
kvfree(kaddrs);
|
||||
|
||||
return err;
|
||||
@@ -1680,6 +1696,7 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,
|
||||
struct sctp_association *asoc;
|
||||
enum sctp_scope scope;
|
||||
struct cmsghdr *cmsg;
|
||||
struct sctp_af *af;
|
||||
int err;
|
||||
|
||||
*tp = NULL;
|
||||
@@ -1705,6 +1722,21 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,
|
||||
|
||||
scope = sctp_scope(daddr);
|
||||
|
||||
/* Label connection socket for first association 1-to-many
|
||||
* style for client sequence socket()->sendmsg(). This
|
||||
* needs to be done before sctp_assoc_add_peer() as that will
|
||||
* set up the initial packet that needs to account for any
|
||||
* security ip options (CIPSO/CALIPSO) added to the packet.
|
||||
*/
|
||||
af = sctp_get_af_specific(daddr->sa.sa_family);
|
||||
if (!af)
|
||||
return -EINVAL;
|
||||
err = security_sctp_bind_connect(sk, SCTP_SENDMSG_CONNECT,
|
||||
(struct sockaddr *)daddr,
|
||||
af->sockaddr_len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
|
||||
if (!asoc)
|
||||
return -ENOMEM;
|
||||
@@ -2932,6 +2964,8 @@ static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval,
|
||||
{
|
||||
struct sctp_prim prim;
|
||||
struct sctp_transport *trans;
|
||||
struct sctp_af *af;
|
||||
int err;
|
||||
|
||||
if (optlen != sizeof(struct sctp_prim))
|
||||
return -EINVAL;
|
||||
@@ -2939,6 +2973,17 @@ static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval,
|
||||
if (copy_from_user(&prim, optval, sizeof(struct sctp_prim)))
|
||||
return -EFAULT;
|
||||
|
||||
/* Allow security module to validate address but need address len. */
|
||||
af = sctp_get_af_specific(prim.ssp_addr.ss_family);
|
||||
if (!af)
|
||||
return -EINVAL;
|
||||
|
||||
err = security_sctp_bind_connect(sk, SCTP_PRIMARY_ADDR,
|
||||
(struct sockaddr *)&prim.ssp_addr,
|
||||
af->sockaddr_len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id);
|
||||
if (!trans)
|
||||
return -EINVAL;
|
||||
@@ -3161,6 +3206,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;
|
||||
@@ -3185,7 +3231,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);
|
||||
|
||||
@@ -3198,7 +3245,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);
|
||||
}
|
||||
@@ -3267,6 +3315,13 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
|
||||
if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
/* Allow security module to validate address. */
|
||||
err = security_sctp_bind_connect(sk, SCTP_SET_PEER_PRIMARY_ADDR,
|
||||
(struct sockaddr *)&prim.sspp_addr,
|
||||
af->sockaddr_len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Create an ASCONF chunk with SET_PRIMARY parameter */
|
||||
chunk = sctp_make_asconf_set_prim(asoc,
|
||||
(union sctp_addr *)&prim.sspp_addr);
|
||||
@@ -5140,9 +5195,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.
|
||||
@@ -8465,6 +8522,8 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
|
||||
{
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct inet_sock *newinet;
|
||||
struct sctp_sock *sp = sctp_sk(sk);
|
||||
struct sctp_endpoint *ep = sp->ep;
|
||||
|
||||
newsk->sk_type = sk->sk_type;
|
||||
newsk->sk_bound_dev_if = sk->sk_bound_dev_if;
|
||||
@@ -8507,7 +8566,10 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
|
||||
if (newsk->sk_flags & SK_FLAGS_TIMESTAMP)
|
||||
net_enable_timestamp();
|
||||
|
||||
security_sk_clone(sk, newsk);
|
||||
/* Set newsk security attributes from orginal sk and connection
|
||||
* security attribute from ep.
|
||||
*/
|
||||
security_sctp_sk_clone(ep, sk, newsk);
|
||||
}
|
||||
|
||||
static inline void sctp_copy_descendant(struct sock *sk_to,
|
||||
|
||||
@@ -1473,6 +1473,7 @@ void security_inet_conn_established(struct sock *sk,
|
||||
{
|
||||
call_void_hook(inet_conn_established, sk, skb);
|
||||
}
|
||||
EXPORT_SYMBOL(security_inet_conn_established);
|
||||
|
||||
int security_secmark_relabel_packet(u32 secid)
|
||||
{
|
||||
@@ -1528,6 +1529,27 @@ int security_tun_dev_open(void *security)
|
||||
}
|
||||
EXPORT_SYMBOL(security_tun_dev_open);
|
||||
|
||||
int security_sctp_assoc_request(struct sctp_endpoint *ep, struct sk_buff *skb)
|
||||
{
|
||||
return call_int_hook(sctp_assoc_request, 0, ep, skb);
|
||||
}
|
||||
EXPORT_SYMBOL(security_sctp_assoc_request);
|
||||
|
||||
int security_sctp_bind_connect(struct sock *sk, int optname,
|
||||
struct sockaddr *address, int addrlen)
|
||||
{
|
||||
return call_int_hook(sctp_bind_connect, 0, sk, optname,
|
||||
address, addrlen);
|
||||
}
|
||||
EXPORT_SYMBOL(security_sctp_bind_connect);
|
||||
|
||||
void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
|
||||
struct sock *newsk)
|
||||
{
|
||||
call_void_hook(sctp_sk_clone, ep, sk, newsk);
|
||||
}
|
||||
EXPORT_SYMBOL(security_sctp_sk_clone);
|
||||
|
||||
#endif /* CONFIG_SECURITY_NETWORK */
|
||||
|
||||
#ifdef CONFIG_SECURITY_INFINIBAND
|
||||
|
||||
+163
-119
File diff suppressed because it is too large
Load Diff
+690
-232
File diff suppressed because it is too large
Load Diff
@@ -152,7 +152,8 @@ static int sel_ib_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = security_ib_pkey_sid(subnet_prefix, pkey_num, sid);
|
||||
ret = security_ib_pkey_sid(&selinux_state, subnet_prefix, pkey_num,
|
||||
sid);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -20,12 +20,6 @@
|
||||
#include "av_permissions.h"
|
||||
#include "security.h"
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
|
||||
extern int selinux_enforcing;
|
||||
#else
|
||||
#define selinux_enforcing 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* An entry in the AVC.
|
||||
*/
|
||||
@@ -58,6 +52,7 @@ struct selinux_audit_data {
|
||||
u32 audited;
|
||||
u32 denied;
|
||||
int result;
|
||||
struct selinux_state *state;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -102,7 +97,8 @@ static inline u32 avc_audit_required(u32 requested,
|
||||
return audited;
|
||||
}
|
||||
|
||||
int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
|
||||
int slow_avc_audit(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid, u16 tclass,
|
||||
u32 requested, u32 audited, u32 denied, int result,
|
||||
struct common_audit_data *a,
|
||||
unsigned flags);
|
||||
@@ -127,7 +123,8 @@ int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
|
||||
* be performed under a lock, to allow the lock to be released
|
||||
* before calling the auditing code.
|
||||
*/
|
||||
static inline int avc_audit(u32 ssid, u32 tsid,
|
||||
static inline int avc_audit(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
struct av_decision *avd,
|
||||
int result,
|
||||
@@ -138,31 +135,35 @@ static inline int avc_audit(u32 ssid, u32 tsid,
|
||||
audited = avc_audit_required(requested, avd, result, 0, &denied);
|
||||
if (likely(!audited))
|
||||
return 0;
|
||||
return slow_avc_audit(ssid, tsid, tclass,
|
||||
return slow_avc_audit(state, ssid, tsid, tclass,
|
||||
requested, audited, denied, result,
|
||||
a, flags);
|
||||
}
|
||||
|
||||
#define AVC_STRICT 1 /* Ignore permissive mode. */
|
||||
#define AVC_EXTENDED_PERMS 2 /* update extended permissions */
|
||||
int avc_has_perm_noaudit(u32 ssid, u32 tsid,
|
||||
int avc_has_perm_noaudit(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
unsigned flags,
|
||||
struct av_decision *avd);
|
||||
|
||||
int avc_has_perm(u32 ssid, u32 tsid,
|
||||
int avc_has_perm(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
struct common_audit_data *auditdata);
|
||||
int avc_has_perm_flags(u32 ssid, u32 tsid,
|
||||
int avc_has_perm_flags(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
struct common_audit_data *auditdata,
|
||||
int flags);
|
||||
|
||||
int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested,
|
||||
u8 driver, u8 perm, struct common_audit_data *ad);
|
||||
int avc_has_extended_perms(struct selinux_state *state,
|
||||
u32 ssid, u32 tsid, u16 tclass, u32 requested,
|
||||
u8 driver, u8 perm, struct common_audit_data *ad);
|
||||
|
||||
|
||||
u32 avc_policy_seqno(void);
|
||||
u32 avc_policy_seqno(struct selinux_state *state);
|
||||
|
||||
#define AVC_CALLBACK_GRANT 1
|
||||
#define AVC_CALLBACK_TRY_REVOKE 2
|
||||
@@ -177,8 +178,11 @@ u32 avc_policy_seqno(void);
|
||||
int avc_add_callback(int (*callback)(u32 event), u32 events);
|
||||
|
||||
/* Exported to selinuxfs */
|
||||
int avc_get_hash_stats(char *page);
|
||||
extern unsigned int avc_cache_threshold;
|
||||
struct selinux_avc;
|
||||
int avc_get_hash_stats(struct selinux_avc *avc, char *page);
|
||||
unsigned int avc_get_cache_threshold(struct selinux_avc *avc);
|
||||
void avc_set_cache_threshold(struct selinux_avc *avc,
|
||||
unsigned int cache_threshold);
|
||||
|
||||
/* Attempt to free avc node cache */
|
||||
void avc_disable(void);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user