Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9eda2d2d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 6ad11bdd 6b6bc620
Loading
Loading
Loading
Loading
+175 −0
Original line number Diff line number Diff line
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                    |
    ------------------------------------------------------------------

+158 −0
Original line number Diff line number Diff line
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.
+36 −0
Original line number Diff line number Diff line
@@ -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;
+25 −0
Original line number Diff line number Diff line
@@ -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
+3 −1
Original line number Diff line number Diff line
@@ -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)
Loading