diff mbox

[RFC,1/5] security: Add support for SCTP security hooks

Message ID 20171017140247.4604-1-richard_c_haines@btinternet.com (mailing list archive)
State Superseded
Headers show

Commit Message

Richard Haines Oct. 17, 2017, 2:02 p.m. UTC
The SCTP security hooks are explained in:
Documentation/security/LSM-sctp.txt

Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
---
 Documentation/security/LSM-sctp.txt | 212 ++++++++++++++++++++++++++++++++++++
 include/linux/lsm_hooks.h           |  37 +++++++
 include/linux/security.h            |  27 +++++
 security/security.c                 |  23 ++++
 4 files changed, 299 insertions(+)
 create mode 100644 Documentation/security/LSM-sctp.txt

Comments

James Morris Oct. 20, 2017, 4:53 a.m. UTC | #1
On Tue, 17 Oct 2017, Richard Haines wrote:

> The SCTP security hooks are explained in:
> Documentation/security/LSM-sctp.txt
> 
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> ---
>  Documentation/security/LSM-sctp.txt | 212 ++++++++++++++++++++++++++++++++++++
>  include/linux/lsm_hooks.h           |  37 +++++++
>  include/linux/security.h            |  27 +++++
>  security/security.c                 |  23 ++++
>  4 files changed, 299 insertions(+)
>  create mode 100644 Documentation/security/LSM-sctp.txt

This looks ok from an LSM API pov, but note that I'm not an expert on 
SCTP.  It would be good to see more review from networking folk.


Reviewed-by: James Morris <james.l.morris@oracle.com>
Marcelo Ricardo Leitner Oct. 31, 2017, 4:41 p.m. UTC | #2
On Tue, Oct 17, 2017 at 03:02:47PM +0100, Richard Haines wrote:
> The SCTP security hooks are explained in:
> Documentation/security/LSM-sctp.txt
> 
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> ---
>  Documentation/security/LSM-sctp.txt | 212 ++++++++++++++++++++++++++++++++++++
>  include/linux/lsm_hooks.h           |  37 +++++++
>  include/linux/security.h            |  27 +++++
>  security/security.c                 |  23 ++++
>  4 files changed, 299 insertions(+)
>  create mode 100644 Documentation/security/LSM-sctp.txt
> 
> diff --git a/Documentation/security/LSM-sctp.txt b/Documentation/security/LSM-sctp.txt
> new file mode 100644
> index 0000000..30fe9b5
> --- /dev/null
> +++ b/Documentation/security/LSM-sctp.txt
> @@ -0,0 +1,212 @@
> +                               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.txt
> +
> +
> +security_sctp_assoc_request()
> +------------------------------
> +This new hook has been added to net/sctp/sm_statefuns.c where it passes the
> +@ep and @chunk->skb (the association INIT or INIT ACK 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.
> +    @sctp_cid - set to sctp packet type (SCTP_CID_INIT or SCTP_CID_INIT_ACK).
> +
> +The security module performs the following operations:
> +  1) 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.
> +
> +  2) If not the first association, validate the @ep->base.sk peer_sid against
> +     the @skb peer sid to determine whether the association should be allowed
> +     or denied.
> +
> +  3) If @sctp_cid = SCTP_CID_INIT, then set the sctp @ep sid to socket's sid
> +     (from ep->base.sk) with MLS portion taken from @skb peer sid. This will
> +     only 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.
> +
> +     To support this hook include/net/sctp/structs.h "struct sctp_endpoint"
> +     has been updated with the following:
> +
> +	/* 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;
> +
> +
> +security_sctp_bind_connect()
> +-----------------------------
> +This new hook has been added to net/sctp/socket.c and net/sctp/sm_make_chunk.c.
> +It 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.

Nit, indentation issue above.
Richard Haines Nov. 1, 2017, 9:38 p.m. UTC | #3
On Tue, 2017-10-31 at 14:41 -0200, Marcelo Ricardo Leitner wrote:
> On Tue, Oct 17, 2017 at 03:02:47PM +0100, Richard Haines wrote:
> > The SCTP security hooks are explained in:
> > Documentation/security/LSM-sctp.txt
> > 
> > Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> > ---
> >  Documentation/security/LSM-sctp.txt | 212
> > ++++++++++++++++++++++++++++++++++++
> >  include/linux/lsm_hooks.h           |  37 +++++++
> >  include/linux/security.h            |  27 +++++
> >  security/security.c                 |  23 ++++
> >  4 files changed, 299 insertions(+)
> >  create mode 100644 Documentation/security/LSM-sctp.txt
> > 
> > diff --git a/Documentation/security/LSM-sctp.txt
> > b/Documentation/security/LSM-sctp.txt
> > new file mode 100644
> > index 0000000..30fe9b5
> > --- /dev/null
> > +++ b/Documentation/security/LSM-sctp.txt
> > @@ -0,0 +1,212 @@
> > +                               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.txt
> > +
> > +
> > +security_sctp_assoc_request()
> > +------------------------------
> > +This new hook has been added to net/sctp/sm_statefuns.c where it
> > passes the
> > +@ep and @chunk->skb (the association INIT or INIT ACK 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.
> > +    @sctp_cid - set to sctp packet type (SCTP_CID_INIT or
> > SCTP_CID_INIT_ACK).
> > +
> > +The security module performs the following operations:
> > +  1) 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.
> > +
> > +  2) If not the first association, validate the @ep->base.sk
> > peer_sid against
> > +     the @skb peer sid to determine whether the association should
> > be allowed
> > +     or denied.
> > +
> > +  3) If @sctp_cid = SCTP_CID_INIT, then set the sctp @ep sid to
> > socket's sid
> > +     (from ep->base.sk) with MLS portion taken from @skb peer sid.
> > This will
> > +     only 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.
> > +
> > +     To support this hook include/net/sctp/structs.h "struct
> > sctp_endpoint"
> > +     has been updated with the following:
> > +
> > +	/* 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;
> > +
> > +
> > +security_sctp_bind_connect()
> > +-----------------------------
> > +This new hook has been added to net/sctp/socket.c and
> > net/sctp/sm_make_chunk.c.
> > +It 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.
> 
> Nit, indentation issue above.
The nit has been squashed
Thanks for all your comments
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-
> security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Paul Moore Nov. 6, 2017, 10:35 p.m. UTC | #4
On Tue, Oct 17, 2017 at 10:02 AM, Richard Haines
<richard_c_haines@btinternet.com> wrote:
> The SCTP security hooks are explained in:
> Documentation/security/LSM-sctp.txt
>
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> ---
>  Documentation/security/LSM-sctp.txt | 212 ++++++++++++++++++++++++++++++++++++
>  include/linux/lsm_hooks.h           |  37 +++++++
>  include/linux/security.h            |  27 +++++
>  security/security.c                 |  23 ++++
>  4 files changed, 299 insertions(+)
>  create mode 100644 Documentation/security/LSM-sctp.txt

Hi Richard,

Thanks for sticking with this, I really appreciate the effort you're
putting into this and I apologize it has taken me a few weeks to get
to reviewing this patchset ... comments below.

> diff --git a/Documentation/security/LSM-sctp.txt b/Documentation/security/LSM-sctp.txt
> new file mode 100644
> index 0000000..30fe9b5
> --- /dev/null
> +++ b/Documentation/security/LSM-sctp.txt
> @@ -0,0 +1,212 @@

There is a push to convert the docs under Documentation/ to use the
reStructuredText format; from what I can tell this shouldn't have a
major impact on what you've already written, just a few formatting
tweaks.  If you can convert the SCTP/LSM/SELinux docs over to RST that
would be very nice.

> +                               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.txt
> +
> +
> +security_sctp_assoc_request()
> +------------------------------
> +This new hook has been added to net/sctp/sm_statefuns.c where it passes the

I would probably avoid calling out specific source files in this
document as the code is almost certain to change at some point (moving
the LSM hook) and I can almost guarantee we'll forget to update this
document.  I think it's better to say something like this:

  "This new hook passes the @ep ..."

> +@ep and @chunk->skb (the association INIT or INIT ACK 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.
> +    @sctp_cid - set to sctp packet type (SCTP_CID_INIT or SCTP_CID_INIT_ACK).

Once again, I must beg patience with my poor understanding of SCTP,
I'm quickly skimming through the RFCs but I'm sure to get some things
wrong.

> +The security module performs the following operations:
> +  1) 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.

Conceptually this is similar to selinux_inet_conn_request(), yes?
Setting the peer label of a new connection/association triggered by a
remote request.

I'm sure we'll get into this later once I get to the code itself, but
I wonder if we should be tracking the peer label in the endpoint?
Would we ever want to allow multiple different peer labels on a single
endpoint?  That seems a bit crazy to me.  Although it might just be
easier from an implementation perspective to reuse the existing
sksec->peer_sid field ...

> +  2) If not the first association, validate the @ep->base.sk peer_sid against
> +     the @skb peer sid to determine whether the association should be allowed
> +     or denied.

This is possible because SCTP allows multiple associations per
endpoint, yes?  I imagine that most (all?) LSMs would want to restrict
this such that all associations for a given endpoint have the same
label.

> +  3) If @sctp_cid = SCTP_CID_INIT, then set the sctp @ep sid to socket's sid
> +     (from ep->base.sk) with MLS portion taken from @skb peer sid. This will
> +     only be used by SCTP TCP style sockets and peeled off connections as they
> +     cause a new socket to be generated.

Once again, the same logic as in
selinux_inet_conn_request()/selinux_conn_sid(), yes?

Presumably we don't need to do anything special for the
SCTP_CID_INIT_ACK case as this is the client side of the connection,
yes?

> +     If IP security options are configured (CIPSO/CALIPSO), then the ip options
> +     are set on the socket.
> +
> +     To support this hook include/net/sctp/structs.h "struct sctp_endpoint"
> +     has been updated with the following:
> +
> +       /* 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;

I would drop the filename and code details for the reasons mentioned above.

> +security_sctp_bind_connect()
> +-----------------------------
> +This new hook has been added to net/sctp/socket.c and net/sctp/sm_make_chunk.c.

See previous comments on filenames/code.

> +It 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       |
> +  ------------------------------------------------------------------

I'm guessing/hoping the reasons for multiplexing all of these
operations onto a single LSM hook will make sense when I get to the
code.

> +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 setsockopts):
> +    /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()
> +-------------------------
> +This new hook has been added to net/sctp/socket.c sctp_sock_migrate() that is

See my previous comments on filenames/code.

> +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).

You can only "peeloff" a socket from a one-to-many socket, not a
one-to-one socket, yes?

(If I'm understanding SCTP correctly, it wouldn't make sense to have a
many-to-one socket, yes?)

> +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 old sctp endpoint structure.
> +    @sk - pointer to old sock structure.
> +    @sk - pointer to new sock structure.
> +
> +security_inet_conn_established()
> +---------------------------------
> +This hook has been added to net/sctp/sm_statefuns.c COOKIE ECHO processing

See my previous comments on filenames/code.

> +where it sets the connection's peer sid to that in @skb.
> +
> +    @sk  - pointer to sock structure.
> +    @skb - pointer to skbuff of the COOKIE ECHO packet.
> +
> +
> +Security Hooks used for Association Establishment
> +==================================================
> +The following diagram shows the use of security_sctp_connect_bind(),
> +security_sctp_assoc_request(), security_inet_conn_established() in
> +net/sctp/sm_statefuns.c and security_sctp_sk_clone() in net/sctp/socket.c,
> +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.

I'm guessing there is no IETF/RFC guidance on using SCTP in a labeled
network environment?  I was just wondering if we should send a ICMP
error back to the other end of the association; I'm guessing we should
defer to the underlying protocol.  While CIPSO predates SCTP, it seems
in keeping with the CIPSO protocol that we would send an ICMP error,
however I imagine that with CALIPSO we would want to silently drop the
packet.

> +    sctp_sf_do_5_1C_ack
> + Respond to an INIT ACK chunk.
> + SCTP peer endpoint"A" initiated
> + this association to SCTP peer
> + endpoint "Z". Call
> + security_sctp_assoc_request()
> + to set the peer label if first
> + association. If not first
> + association, check whether
> + allowed, IF so send:
> +    COOKIE ECHO ------------------------------------------>
> + ELSE audit event and silently                            |
> +      discard the packet.                                 |

Same as above with respect to handling LSM denials.

> +                                                          |
> +          <------------------------------------------- COOKIE ACK
> +          |                                               |
> +    sctp_sf_do_5_1E_ca                                    |
> + Call security_inet_conn_established()                    |
> + to set the correct peer sid.                             |

We would only get here if this association was the first for a given
endpoint, yes?

> +          |                                               |
> +          |                               net/sctp/socket.c sctp_copy_sock()
> +          |                               If SCTP_SOCKET_TCP or peeled off
> +          |                               socket security_sctp_sk_clone() is
> +          |                               called to clone the new socket.

In this case we are establishing a new association for a given endpoint, yes?

> +          |                                               |
> +      ESTABLISHED                                    ESTABLISHED
> +          |                                               |
> +    ------------------------------------------------------------------
> +    |                     Association Established                    |
> +    ------------------------------------------------------------------
> +
> +
diff mbox

Patch

diff --git a/Documentation/security/LSM-sctp.txt b/Documentation/security/LSM-sctp.txt
new file mode 100644
index 0000000..30fe9b5
--- /dev/null
+++ b/Documentation/security/LSM-sctp.txt
@@ -0,0 +1,212 @@ 
+                               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.txt
+
+
+security_sctp_assoc_request()
+------------------------------
+This new hook has been added to net/sctp/sm_statefuns.c where it passes the
+@ep and @chunk->skb (the association INIT or INIT ACK 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.
+    @sctp_cid - set to sctp packet type (SCTP_CID_INIT or SCTP_CID_INIT_ACK).
+
+The security module performs the following operations:
+  1) 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.
+
+  2) If not the first association, validate the @ep->base.sk peer_sid against
+     the @skb peer sid to determine whether the association should be allowed
+     or denied.
+
+  3) If @sctp_cid = SCTP_CID_INIT, then set the sctp @ep sid to socket's sid
+     (from ep->base.sk) with MLS portion taken from @skb peer sid. This will
+     only 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.
+
+     To support this hook include/net/sctp/structs.h "struct sctp_endpoint"
+     has been updated with the following:
+
+	/* 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;
+
+
+security_sctp_bind_connect()
+-----------------------------
+This new hook has been added to net/sctp/socket.c and net/sctp/sm_make_chunk.c.
+It 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 setsockopts):
+    /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()
+-------------------------
+This new hook has been added to net/sctp/socket.c sctp_sock_migrate() that is
+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 old sctp endpoint structure.
+    @sk - pointer to old sock structure.
+    @sk - pointer to new sock structure.
+
+security_inet_conn_established()
+---------------------------------
+This hook has been added to net/sctp/sm_statefuns.c COOKIE ECHO processing
+where it sets the connection's peer sid to that in @skb.
+
+    @sk  - pointer to sock structure.
+    @skb - pointer to skbuff of the COOKIE ECHO packet.
+
+
+Security Hooks used for Association Establishment
+==================================================
+The following diagram shows the use of security_sctp_connect_bind(),
+security_sctp_assoc_request(), security_inet_conn_established() in
+net/sctp/sm_statefuns.c and security_sctp_sk_clone() in net/sctp/socket.c,
+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.
+    sctp_sf_do_5_1C_ack
+ Respond to an INIT ACK chunk.
+ SCTP peer endpoint"A" initiated
+ this association to SCTP peer
+ endpoint "Z". Call
+ security_sctp_assoc_request()
+ to set the peer label if first
+ association. If not first
+ association, check whether
+ allowed, IF so send:
+    COOKIE ECHO ------------------------------------------>
+ ELSE audit event and silently                            |
+      discard the packet.                                 |
+                                                          |
+          <------------------------------------------- COOKIE ACK
+          |                                               |
+    sctp_sf_do_5_1E_ca                                    |
+ Call security_inet_conn_established()                    |
+ to set the correct peer sid.                             |
+          |                                               |
+          |                               net/sctp/socket.c sctp_copy_sock()
+          |                               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/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 3a90feb..42370a7 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -913,6 +913,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:
+ *	If first association, then set the peer sid to that in @skb. If
+ *	@sctp_cid is from an INIT chunk, then set the sctp endpoint sid to
+ *	socket's sid (ep->base.sk) with MLS portion taken from peer sid.
+ *	@ep pointer to sctp endpoint structure.
+ *	@skb pointer to skbuff of association packet.
+ *	@sctp_cid whether association from INIT or INIT_ACK chunk.
+ *	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:
+ *	Sets the new child socket's sid to the old endpoint sid.
+ *	@ep pointer to old sctp endpoint structure.
+ *	@sk pointer to old sock structure.
+ *	@sk pointer to new sock structure.
+ *
  * Security hooks for Infiniband
  *
  * @ib_pkey_access:
@@ -1640,6 +1667,13 @@  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_cid);
+	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
@@ -1880,6 +1914,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 834b355..2054023 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -114,6 +114,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;
@@ -1240,6 +1241,12 @@  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 sctp_cid);
+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,
@@ -1432,6 +1439,26 @@  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,
+					      int sctp_cid)
+{
+	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/security/security.c b/security/security.c
index 3013237..798fc6e 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1482,6 +1482,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)
 {
@@ -1537,6 +1538,28 @@  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,
+				int sctp_cid)
+{
+	return call_int_hook(sctp_assoc_request, 0, ep, skb, sctp_cid);
+}
+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