Commit 2bd080b0 authored by David S. Miller's avatar David S. Miller

Merge branch 'sctp-=security-hook-fixes'

Xin Long says:

====================
security: fixups for the security hooks in sctp

There are a couple of problems in the currect security hooks in sctp:

1. The hooks incorrectly treat sctp_endpoint in SCTP as request_sock in
   TCP, while it's in fact no more than an extension of the sock, and
   represents the local host. It is created when sock is created, not
   when a conn request comes. sctp_association is actually the correct
   one to represent the connection, and created when a conn request
   arrives.

2. security_sctp_assoc_request() hook should also be called in processing
   COOKIE ECHO, as that's the place where the real assoc is created and
   used in the future.

The problems above may cause accept sk, peeloff sk or client sk having
the incorrect security labels.

So this patchset is to change some hooks and pass asoc into them and save
these secids into asoc, as well as add the missing sctp_assoc_request
hook into the COOKIE ECHO processing.

v1->v2:
  - See each patch, and thanks the help from Ondrej, Paul and Richard.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 843c3cbb e7310c94
...@@ -15,10 +15,7 @@ For security module support, three SCTP specific hooks have been implemented:: ...@@ -15,10 +15,7 @@ For security module support, three SCTP specific hooks have been implemented::
security_sctp_assoc_request() security_sctp_assoc_request()
security_sctp_bind_connect() security_sctp_bind_connect()
security_sctp_sk_clone() security_sctp_sk_clone()
security_sctp_assoc_established()
Also the following security hook has been utilised::
security_inet_conn_established()
The usage of these hooks are described below with the SELinux implementation The usage of these hooks are described below with the SELinux implementation
described in the `SCTP SELinux Support`_ chapter. described in the `SCTP SELinux Support`_ chapter.
...@@ -26,11 +23,11 @@ described in the `SCTP SELinux Support`_ chapter. ...@@ -26,11 +23,11 @@ described in the `SCTP SELinux Support`_ chapter.
security_sctp_assoc_request() security_sctp_assoc_request()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Passes the ``@ep`` and ``@chunk->skb`` of the association INIT packet to the Passes the ``@asoc`` and ``@chunk->skb`` of the association INIT packet to the
security module. Returns 0 on success, error on failure. security module. Returns 0 on success, error on failure.
:: ::
@ep - pointer to sctp endpoint structure. @asoc - pointer to sctp association structure.
@skb - pointer to skbuff of association packet. @skb - pointer to skbuff of association packet.
...@@ -117,16 +114,17 @@ Called whenever a new socket is created by **accept**\(2) ...@@ -117,16 +114,17 @@ Called whenever a new socket is created by **accept**\(2)
calls **sctp_peeloff**\(3). calls **sctp_peeloff**\(3).
:: ::
@ep - pointer to current sctp endpoint structure. @asoc - pointer to current sctp association structure.
@sk - pointer to current sock structure. @sk - pointer to current sock structure.
@sk - pointer to new sock structure. @newsk - pointer to new sock structure.
security_inet_conn_established() security_sctp_assoc_established()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Called when a COOKIE ACK is received:: Called when a COOKIE ACK is received, and the peer secid will be
saved into ``@asoc->peer_secid`` for client::
@sk - pointer to sock structure. @asoc - pointer to sctp association structure.
@skb - pointer to skbuff of the COOKIE ACK packet. @skb - pointer to skbuff of the COOKIE ACK packet.
...@@ -134,7 +132,7 @@ Security Hooks used for Association Establishment ...@@ -134,7 +132,7 @@ Security Hooks used for Association Establishment
------------------------------------------------- -------------------------------------------------
The following diagram shows the use of ``security_sctp_bind_connect()``, The following diagram shows the use of ``security_sctp_bind_connect()``,
``security_sctp_assoc_request()``, ``security_inet_conn_established()`` when ``security_sctp_assoc_request()``, ``security_sctp_assoc_established()`` when
establishing an association. establishing an association.
:: ::
...@@ -151,9 +149,9 @@ establishing an association. ...@@ -151,9 +149,9 @@ establishing an association.
INIT ---------------------------------------------> INIT --------------------------------------------->
sctp_sf_do_5_1B_init() sctp_sf_do_5_1B_init()
Respond to an INIT chunk. Respond to an INIT chunk.
SCTP peer endpoint "A" is SCTP peer endpoint "A" is asking
asking for an association. Call for a temporary association.
security_sctp_assoc_request() Call security_sctp_assoc_request()
to set the peer label if first to set the peer label if first
association. association.
If not first association, check If not first association, check
...@@ -163,13 +161,16 @@ establishing an association. ...@@ -163,13 +161,16 @@ establishing an association.
| discard the packet. | discard the packet.
| |
COOKIE ECHO ------------------------------------------> COOKIE ECHO ------------------------------------------>
| sctp_sf_do_5_1D_ce()
| Respond to an COOKIE ECHO chunk.
| Confirm the cookie and create a
permanent association.
Call security_sctp_assoc_request() to
do the same as for INIT chunk Response.
<------------------------------------------- COOKIE ACK <------------------------------------------- COOKIE ACK
| | | |
sctp_sf_do_5_1E_ca | sctp_sf_do_5_1E_ca |
Call security_inet_conn_established() | Call security_sctp_assoc_established() |
to set the peer label. | to set the peer label. |
| | | |
| If SCTP_SOCKET_TCP or peeled off | If SCTP_SOCKET_TCP or peeled off
...@@ -195,27 +196,27 @@ hooks with the SELinux specifics expanded below:: ...@@ -195,27 +196,27 @@ hooks with the SELinux specifics expanded below::
security_sctp_assoc_request() security_sctp_assoc_request()
security_sctp_bind_connect() security_sctp_bind_connect()
security_sctp_sk_clone() security_sctp_sk_clone()
security_inet_conn_established() security_sctp_assoc_established()
security_sctp_assoc_request() security_sctp_assoc_request()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Passes the ``@ep`` and ``@chunk->skb`` of the association INIT packet to the Passes the ``@asoc`` and ``@chunk->skb`` of the association INIT packet to the
security module. Returns 0 on success, error on failure. security module. Returns 0 on success, error on failure.
:: ::
@ep - pointer to sctp endpoint structure. @asoc - pointer to sctp association structure.
@skb - pointer to skbuff of association packet. @skb - pointer to skbuff of association packet.
The security module performs the following operations: The security module performs the following operations:
IF this is the first association on ``@ep->base.sk``, then set the peer IF this is the first association on ``@asoc->base.sk``, then set the peer
sid to that in ``@skb``. This will ensure there is only one peer sid sid to that in ``@skb``. This will ensure there is only one peer sid
assigned to ``@ep->base.sk`` that may support multiple associations. assigned to ``@asoc->base.sk`` that may support multiple associations.
ELSE validate the ``@ep->base.sk peer_sid`` against the ``@skb peer sid`` ELSE validate the ``@asoc->base.sk peer_sid`` against the ``@skb peer sid``
to determine whether the association should be allowed or denied. to determine whether the association should be allowed or denied.
Set the sctp ``@ep sid`` to socket's sid (from ``ep->base.sk``) with Set the sctp ``@asoc sid`` to socket's sid (from ``asoc->base.sk``) with
MLS portion taken from ``@skb peer sid``. This will be used by SCTP 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 TCP style sockets and peeled off connections as they cause a new socket
to be generated. to be generated.
...@@ -259,21 +260,21 @@ security_sctp_sk_clone() ...@@ -259,21 +260,21 @@ security_sctp_sk_clone()
Called whenever a new socket is created by **accept**\(2) (i.e. a TCP style 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 socket) or when a socket is 'peeled off' e.g userspace calls
**sctp_peeloff**\(3). ``security_sctp_sk_clone()`` will set the new **sctp_peeloff**\(3). ``security_sctp_sk_clone()`` will set the new
sockets sid and peer sid to that contained in the ``@ep sid`` and sockets sid and peer sid to that contained in the ``@asoc sid`` and
``@ep peer sid`` respectively. ``@asoc peer sid`` respectively.
:: ::
@ep - pointer to current sctp endpoint structure. @asoc - pointer to current sctp association structure.
@sk - pointer to current sock structure. @sk - pointer to current sock structure.
@sk - pointer to new sock structure. @newsk - pointer to new sock structure.
security_inet_conn_established() security_sctp_assoc_established()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Called when a COOKIE ACK is received where it sets the connection's peer sid Called when a COOKIE ACK is received where it sets the connection's peer sid
to that in ``@skb``:: to that in ``@skb``::
@sk - pointer to sock structure. @asoc - pointer to sctp association structure.
@skb - pointer to skbuff of the COOKIE ACK packet. @skb - pointer to skbuff of the COOKIE ACK packet.
......
...@@ -329,12 +329,14 @@ LSM_HOOK(int, 0, tun_dev_create, void) ...@@ -329,12 +329,14 @@ LSM_HOOK(int, 0, tun_dev_create, void)
LSM_HOOK(int, 0, tun_dev_attach_queue, void *security) LSM_HOOK(int, 0, tun_dev_attach_queue, void *security)
LSM_HOOK(int, 0, tun_dev_attach, struct sock *sk, void *security) LSM_HOOK(int, 0, tun_dev_attach, struct sock *sk, void *security)
LSM_HOOK(int, 0, tun_dev_open, void *security) LSM_HOOK(int, 0, tun_dev_open, void *security)
LSM_HOOK(int, 0, sctp_assoc_request, struct sctp_endpoint *ep, LSM_HOOK(int, 0, sctp_assoc_request, struct sctp_association *asoc,
struct sk_buff *skb) struct sk_buff *skb)
LSM_HOOK(int, 0, sctp_bind_connect, struct sock *sk, int optname, LSM_HOOK(int, 0, sctp_bind_connect, struct sock *sk, int optname,
struct sockaddr *address, int addrlen) struct sockaddr *address, int addrlen)
LSM_HOOK(void, LSM_RET_VOID, sctp_sk_clone, struct sctp_endpoint *ep, LSM_HOOK(void, LSM_RET_VOID, sctp_sk_clone, struct sctp_association *asoc,
struct sock *sk, struct sock *newsk) struct sock *sk, struct sock *newsk)
LSM_HOOK(void, LSM_RET_VOID, sctp_assoc_established, struct sctp_association *asoc,
struct sk_buff *skb)
#endif /* CONFIG_SECURITY_NETWORK */ #endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND #ifdef CONFIG_SECURITY_INFINIBAND
......
...@@ -1027,9 +1027,9 @@ ...@@ -1027,9 +1027,9 @@
* Security hooks for SCTP * Security hooks for SCTP
* *
* @sctp_assoc_request: * @sctp_assoc_request:
* Passes the @ep and @chunk->skb of the association INIT packet to * Passes the @asoc and @chunk->skb of the association INIT packet to
* the security module. * the security module.
* @ep pointer to sctp endpoint structure. * @asoc pointer to sctp association structure.
* @skb pointer to skbuff of association packet. * @skb pointer to skbuff of association packet.
* Return 0 on success, error on failure. * Return 0 on success, error on failure.
* @sctp_bind_connect: * @sctp_bind_connect:
...@@ -1047,9 +1047,14 @@ ...@@ -1047,9 +1047,14 @@
* Called whenever a new socket is created by accept(2) (i.e. a TCP * 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 * style socket) or when a socket is 'peeled off' e.g userspace
* calls sctp_peeloff(3). * calls sctp_peeloff(3).
* @ep pointer to current sctp endpoint structure. * @asoc pointer to current sctp association structure.
* @sk pointer to current sock structure. * @sk pointer to current sock structure.
* @sk pointer to new sock structure. * @newsk pointer to new sock structure.
* @sctp_assoc_established:
* Passes the @asoc and @chunk->skb of the association COOKIE_ACK packet
* to the security module.
* @asoc pointer to sctp association structure.
* @skb pointer to skbuff of association packet.
* *
* Security hooks for Infiniband * Security hooks for Infiniband
* *
......
...@@ -179,7 +179,7 @@ struct xfrm_policy; ...@@ -179,7 +179,7 @@ struct xfrm_policy;
struct xfrm_state; struct xfrm_state;
struct xfrm_user_sec_ctx; struct xfrm_user_sec_ctx;
struct seq_file; struct seq_file;
struct sctp_endpoint; struct sctp_association;
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
extern unsigned long mmap_min_addr; extern unsigned long mmap_min_addr;
...@@ -1425,11 +1425,13 @@ int security_tun_dev_create(void); ...@@ -1425,11 +1425,13 @@ int security_tun_dev_create(void);
int security_tun_dev_attach_queue(void *security); int security_tun_dev_attach_queue(void *security);
int security_tun_dev_attach(struct sock *sk, void *security); int security_tun_dev_attach(struct sock *sk, void *security);
int security_tun_dev_open(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_assoc_request(struct sctp_association *asoc, struct sk_buff *skb);
int security_sctp_bind_connect(struct sock *sk, int optname, int security_sctp_bind_connect(struct sock *sk, int optname,
struct sockaddr *address, int addrlen); struct sockaddr *address, int addrlen);
void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, void security_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk,
struct sock *newsk); struct sock *newsk);
void security_sctp_assoc_established(struct sctp_association *asoc,
struct sk_buff *skb);
#else /* CONFIG_SECURITY_NETWORK */ #else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct sock *sock, static inline int security_unix_stream_connect(struct sock *sock,
...@@ -1631,7 +1633,7 @@ static inline int security_tun_dev_open(void *security) ...@@ -1631,7 +1633,7 @@ static inline int security_tun_dev_open(void *security)
return 0; return 0;
} }
static inline int security_sctp_assoc_request(struct sctp_endpoint *ep, static inline int security_sctp_assoc_request(struct sctp_association *asoc,
struct sk_buff *skb) struct sk_buff *skb)
{ {
return 0; return 0;
...@@ -1644,11 +1646,16 @@ static inline int security_sctp_bind_connect(struct sock *sk, int optname, ...@@ -1644,11 +1646,16 @@ static inline int security_sctp_bind_connect(struct sock *sk, int optname,
return 0; return 0;
} }
static inline void security_sctp_sk_clone(struct sctp_endpoint *ep, static inline void security_sctp_sk_clone(struct sctp_association *asoc,
struct sock *sk, struct sock *sk,
struct sock *newsk) struct sock *newsk)
{ {
} }
static inline void security_sctp_assoc_established(struct sctp_association *asoc,
struct sk_buff *skb)
{
}
#endif /* CONFIG_SECURITY_NETWORK */ #endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND #ifdef CONFIG_SECURITY_INFINIBAND
......
...@@ -1355,16 +1355,6 @@ struct sctp_endpoint { ...@@ -1355,16 +1355,6 @@ struct sctp_endpoint {
reconf_enable:1; reconf_enable:1;
__u8 strreset_enable; __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. */ /* Recover the outter endpoint structure. */
...@@ -2104,6 +2094,16 @@ struct sctp_association { ...@@ -2104,6 +2094,16 @@ struct sctp_association {
__u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1]; __u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1];
__u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1]; __u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1];
/* 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;
struct rcu_head rcu; struct rcu_head rcu;
}; };
......
...@@ -326,11 +326,6 @@ enum sctp_disposition sctp_sf_do_5_1B_init(struct net *net, ...@@ -326,11 +326,6 @@ enum sctp_disposition sctp_sf_do_5_1B_init(struct net *net,
struct sctp_packet *packet; struct sctp_packet *packet;
int len; 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 /* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or * An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks. * SHUTDOWN COMPLETE with any other chunks.
...@@ -415,6 +410,12 @@ enum sctp_disposition sctp_sf_do_5_1B_init(struct net *net, ...@@ -415,6 +410,12 @@ enum sctp_disposition sctp_sf_do_5_1B_init(struct net *net,
if (!new_asoc) if (!new_asoc)
goto nomem; goto nomem;
/* Update socket peer label if first association. */
if (security_sctp_assoc_request(new_asoc, chunk->skb)) {
sctp_association_free(new_asoc);
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
if (sctp_assoc_set_bind_addr_from_ep(new_asoc, if (sctp_assoc_set_bind_addr_from_ep(new_asoc,
sctp_scope(sctp_source(chunk)), sctp_scope(sctp_source(chunk)),
GFP_ATOMIC) < 0) GFP_ATOMIC) < 0)
...@@ -780,6 +781,10 @@ enum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net, ...@@ -780,6 +781,10 @@ enum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net,
} }
} }
if (security_sctp_assoc_request(new_asoc, chunk->skb)) {
sctp_association_free(new_asoc);
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
/* Delay state machine commands until later. /* Delay state machine commands until later.
* *
...@@ -941,7 +946,7 @@ enum sctp_disposition sctp_sf_do_5_1E_ca(struct net *net, ...@@ -941,7 +946,7 @@ enum sctp_disposition sctp_sf_do_5_1E_ca(struct net *net,
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());
/* Set peer label for connection. */ /* Set peer label for connection. */
security_inet_conn_established(ep->base.sk, chunk->skb); security_sctp_assoc_established((struct sctp_association *)asoc, chunk->skb);
/* RFC 2960 5.1 Normal Establishment of an Association /* RFC 2960 5.1 Normal Establishment of an Association
* *
...@@ -1517,11 +1522,6 @@ static enum sctp_disposition sctp_sf_do_unexpected_init( ...@@ -1517,11 +1522,6 @@ static enum sctp_disposition sctp_sf_do_unexpected_init(
struct sctp_packet *packet; struct sctp_packet *packet;
int len; 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 /* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or * An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks. * SHUTDOWN COMPLETE with any other chunks.
...@@ -1594,6 +1594,12 @@ static enum sctp_disposition sctp_sf_do_unexpected_init( ...@@ -1594,6 +1594,12 @@ static enum sctp_disposition sctp_sf_do_unexpected_init(
if (!new_asoc) if (!new_asoc)
goto nomem; goto nomem;
/* Update socket peer label if first association. */
if (security_sctp_assoc_request(new_asoc, chunk->skb)) {
sctp_association_free(new_asoc);
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
if (sctp_assoc_set_bind_addr_from_ep(new_asoc, if (sctp_assoc_set_bind_addr_from_ep(new_asoc,
sctp_scope(sctp_source(chunk)), GFP_ATOMIC) < 0) sctp_scope(sctp_source(chunk)), GFP_ATOMIC) < 0)
goto nomem; goto nomem;
...@@ -2255,8 +2261,7 @@ enum sctp_disposition sctp_sf_do_5_2_4_dupcook( ...@@ -2255,8 +2261,7 @@ enum sctp_disposition sctp_sf_do_5_2_4_dupcook(
} }
/* Update socket peer label if first association. */ /* Update socket peer label if first association. */
if (security_sctp_assoc_request((struct sctp_endpoint *)ep, if (security_sctp_assoc_request(new_asoc, chunk->skb)) {
chunk->skb)) {
sctp_association_free(new_asoc); sctp_association_free(new_asoc);
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
} }
......
...@@ -9412,7 +9412,6 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, ...@@ -9412,7 +9412,6 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
struct inet_sock *newinet; struct inet_sock *newinet;
struct sctp_sock *sp = sctp_sk(sk); struct sctp_sock *sp = sctp_sk(sk);
struct sctp_endpoint *ep = sp->ep;
newsk->sk_type = sk->sk_type; newsk->sk_type = sk->sk_type;
newsk->sk_bound_dev_if = sk->sk_bound_dev_if; newsk->sk_bound_dev_if = sk->sk_bound_dev_if;
...@@ -9457,9 +9456,9 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, ...@@ -9457,9 +9456,9 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
net_enable_timestamp(); net_enable_timestamp();
/* Set newsk security attributes from original sk and connection /* Set newsk security attributes from original sk and connection
* security attribute from ep. * security attribute from asoc.
*/ */
security_sctp_sk_clone(ep, sk, newsk); security_sctp_sk_clone(asoc, sk, newsk);
} }
static inline void sctp_copy_descendant(struct sock *sk_to, static inline void sctp_copy_descendant(struct sock *sk_to,
......
...@@ -2367,9 +2367,9 @@ int security_tun_dev_open(void *security) ...@@ -2367,9 +2367,9 @@ int security_tun_dev_open(void *security)
} }
EXPORT_SYMBOL(security_tun_dev_open); EXPORT_SYMBOL(security_tun_dev_open);
int security_sctp_assoc_request(struct sctp_endpoint *ep, struct sk_buff *skb) int security_sctp_assoc_request(struct sctp_association *asoc, struct sk_buff *skb)
{ {
return call_int_hook(sctp_assoc_request, 0, ep, skb); return call_int_hook(sctp_assoc_request, 0, asoc, skb);
} }
EXPORT_SYMBOL(security_sctp_assoc_request); EXPORT_SYMBOL(security_sctp_assoc_request);
...@@ -2381,13 +2381,20 @@ int security_sctp_bind_connect(struct sock *sk, int optname, ...@@ -2381,13 +2381,20 @@ int security_sctp_bind_connect(struct sock *sk, int optname,
} }
EXPORT_SYMBOL(security_sctp_bind_connect); EXPORT_SYMBOL(security_sctp_bind_connect);
void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, void security_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk,
struct sock *newsk) struct sock *newsk)
{ {
call_void_hook(sctp_sk_clone, ep, sk, newsk); call_void_hook(sctp_sk_clone, asoc, sk, newsk);
} }
EXPORT_SYMBOL(security_sctp_sk_clone); EXPORT_SYMBOL(security_sctp_sk_clone);
void security_sctp_assoc_established(struct sctp_association *asoc,
struct sk_buff *skb)
{
call_void_hook(sctp_assoc_established, asoc, skb);
}
EXPORT_SYMBOL(security_sctp_assoc_established);
#endif /* CONFIG_SECURITY_NETWORK */ #endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND #ifdef CONFIG_SECURITY_INFINIBAND
......
...@@ -5339,10 +5339,10 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent) ...@@ -5339,10 +5339,10 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
* connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association
* already present). * already present).
*/ */
static int selinux_sctp_assoc_request(struct sctp_endpoint *ep, static int selinux_sctp_assoc_request(struct sctp_association *asoc,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct sk_security_struct *sksec = ep->base.sk->sk_security; struct sk_security_struct *sksec = asoc->base.sk->sk_security;
struct common_audit_data ad; struct common_audit_data ad;
struct lsm_network_audit net = {0,}; struct lsm_network_audit net = {0,};
u8 peerlbl_active; u8 peerlbl_active;
...@@ -5359,7 +5359,7 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep, ...@@ -5359,7 +5359,7 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
/* This will return peer_sid = SECSID_NULL if there are /* This will return peer_sid = SECSID_NULL if there are
* no peer labels, see security_net_peersid_resolve(). * no peer labels, see security_net_peersid_resolve().
*/ */
err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family, err = selinux_skb_peerlbl_sid(skb, asoc->base.sk->sk_family,
&peer_sid); &peer_sid);
if (err) if (err)
return err; return err;
...@@ -5383,7 +5383,7 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep, ...@@ -5383,7 +5383,7 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
*/ */
ad.type = LSM_AUDIT_DATA_NET; ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->sk = ep->base.sk; ad.u.net->sk = asoc->base.sk;
err = avc_has_perm(&selinux_state, err = avc_has_perm(&selinux_state,
sksec->peer_sid, peer_sid, sksec->sclass, sksec->peer_sid, peer_sid, sksec->sclass,
SCTP_SOCKET__ASSOCIATION, &ad); SCTP_SOCKET__ASSOCIATION, &ad);
...@@ -5392,7 +5392,7 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep, ...@@ -5392,7 +5392,7 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
} }
/* Compute the MLS component for the connection and store /* Compute the MLS component for the connection and store
* the information in ep. This will be used by SCTP TCP type * the information in asoc. This will be used by SCTP TCP type
* sockets and peeled off connections as they cause a new * sockets and peeled off connections as they cause a new
* socket to be generated. selinux_sctp_sk_clone() will then * socket to be generated. selinux_sctp_sk_clone() will then
* plug this into the new socket. * plug this into the new socket.
...@@ -5401,11 +5401,11 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep, ...@@ -5401,11 +5401,11 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
if (err) if (err)
return err; return err;
ep->secid = conn_sid; asoc->secid = conn_sid;
ep->peer_secid = peer_sid; asoc->peer_secid = peer_sid;
/* Set any NetLabel labels including CIPSO/CALIPSO options. */ /* Set any NetLabel labels including CIPSO/CALIPSO options. */
return selinux_netlbl_sctp_assoc_request(ep, skb); return selinux_netlbl_sctp_assoc_request(asoc, skb);
} }
/* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting /* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting
...@@ -5490,7 +5490,7 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname, ...@@ -5490,7 +5490,7 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
} }
/* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */ /* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */
static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk,
struct sock *newsk) struct sock *newsk)
{ {
struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *sksec = sk->sk_security;
...@@ -5502,8 +5502,9 @@ static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, ...@@ -5502,8 +5502,9 @@ static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
if (!selinux_policycap_extsockclass()) if (!selinux_policycap_extsockclass())
return selinux_sk_clone_security(sk, newsk); return selinux_sk_clone_security(sk, newsk);
newsksec->sid = ep->secid; if (asoc->secid != SECSID_WILD)
newsksec->peer_sid = ep->peer_secid; newsksec->sid = asoc->secid;
newsksec->peer_sid = asoc->peer_secid;
newsksec->sclass = sksec->sclass; newsksec->sclass = sksec->sclass;
selinux_netlbl_sctp_sk_clone(sk, newsk); selinux_netlbl_sctp_sk_clone(sk, newsk);
} }
...@@ -5558,6 +5559,16 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) ...@@ -5558,6 +5559,16 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
} }
static void selinux_sctp_assoc_established(struct sctp_association *asoc,
struct sk_buff *skb)
{
struct sk_security_struct *sksec = asoc->base.sk->sk_security;
selinux_inet_conn_established(asoc->base.sk, skb);
asoc->peer_secid = sksec->peer_sid;
asoc->secid = SECSID_WILD;
}
static int selinux_secmark_relabel_packet(u32 sid) static int selinux_secmark_relabel_packet(u32 sid)
{ {
const struct task_security_struct *__tsec; const struct task_security_struct *__tsec;
...@@ -7228,6 +7239,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { ...@@ -7228,6 +7239,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request), LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request),
LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone), LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect), LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
LSM_HOOK_INIT(sctp_assoc_established, selinux_sctp_assoc_established),
LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request), LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone), LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established), LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
......
...@@ -39,7 +39,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, ...@@ -39,7 +39,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
u16 family, u16 family,
u32 sid); u32 sid);
int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc,
struct sk_buff *skb); struct sk_buff *skb);
int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family); int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family);
void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family); void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family);
...@@ -98,7 +98,7 @@ static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, ...@@ -98,7 +98,7 @@ static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
return 0; return 0;
} }
static inline int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, static inline int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc,
struct sk_buff *skb) struct sk_buff *skb)
{ {
return 0; return 0;
......
...@@ -261,30 +261,30 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, ...@@ -261,30 +261,30 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
/** /**
* selinux_netlbl_sctp_assoc_request - Label an incoming sctp association. * selinux_netlbl_sctp_assoc_request - Label an incoming sctp association.
* @ep: incoming association endpoint. * @asoc: incoming association.
* @skb: the packet. * @skb: the packet.
* *
* Description: * Description:
* A new incoming connection is represented by @ep, ...... * A new incoming connection is represented by @asoc, ......
* Returns zero on success, negative values on failure. * Returns zero on success, negative values on failure.
* *
*/ */
int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc,
struct sk_buff *skb) struct sk_buff *skb)
{ {
int rc; int rc;
struct netlbl_lsm_secattr secattr; struct netlbl_lsm_secattr secattr;
struct sk_security_struct *sksec = ep->base.sk->sk_security; struct sk_security_struct *sksec = asoc->base.sk->sk_security;
struct sockaddr_in addr4; struct sockaddr_in addr4;
struct sockaddr_in6 addr6; struct sockaddr_in6 addr6;
if (ep->base.sk->sk_family != PF_INET && if (asoc->base.sk->sk_family != PF_INET &&
ep->base.sk->sk_family != PF_INET6) asoc->base.sk->sk_family != PF_INET6)
return 0; return 0;
netlbl_secattr_init(&secattr); netlbl_secattr_init(&secattr);
rc = security_netlbl_sid_to_secattr(&selinux_state, rc = security_netlbl_sid_to_secattr(&selinux_state,
ep->secid, &secattr); asoc->secid, &secattr);
if (rc != 0) if (rc != 0)
goto assoc_request_return; goto assoc_request_return;
...@@ -294,11 +294,11 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, ...@@ -294,11 +294,11 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
if (ip_hdr(skb)->version == 4) { if (ip_hdr(skb)->version == 4) {
addr4.sin_family = AF_INET; addr4.sin_family = AF_INET;
addr4.sin_addr.s_addr = ip_hdr(skb)->saddr; addr4.sin_addr.s_addr = ip_hdr(skb)->saddr;
rc = netlbl_conn_setattr(ep->base.sk, (void *)&addr4, &secattr); rc = netlbl_conn_setattr(asoc->base.sk, (void *)&addr4, &secattr);
} else if (IS_ENABLED(CONFIG_IPV6) && ip_hdr(skb)->version == 6) { } else if (IS_ENABLED(CONFIG_IPV6) && ip_hdr(skb)->version == 6) {
addr6.sin6_family = AF_INET6; addr6.sin6_family = AF_INET6;
addr6.sin6_addr = ipv6_hdr(skb)->saddr; addr6.sin6_addr = ipv6_hdr(skb)->saddr;
rc = netlbl_conn_setattr(ep->base.sk, (void *)&addr6, &secattr); rc = netlbl_conn_setattr(asoc->base.sk, (void *)&addr6, &secattr);
} else { } else {
rc = -EAFNOSUPPORT; rc = -EAFNOSUPPORT;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment