new file mode 100644
@@ -0,0 +1,171 @@
+ SCTP LSM Support
+ ==================
+
+For security module support, four new sctp specific hooks have been
+implemented:
+ security_sctp_assoc_request()
+ security_sctp_accept_conn()
+ security_sctp_sk_clone()
+ security_sctp_addr_list()
+
+The usage of these hooks are described below with further information
+available in include/linux/lsm_hooks.h. The SELinux implementation is
+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
+@sk and @chunk->skb (the association INIT or INIT ACK packet) to the security
+module. Returns 0 on success, error on failure.
+
+ @sk - pointer to sock structure.
+ @skb - pointer to skbuff of association packet (INIT or INIT ACK)
+
+The security module performs two operations:
+ 1) If this is the first association on @sk, then set the peer sid
+ to that in @skb. This will ensure that there is only one peer sid
+ assigned to @sk that may support multiple associations.
+
+ 2) Validate the @sk sid against the @sk peer sid to determine whether the
+ association should be allowed or denied.
+
+
+security_sctp_accept_conn()
+----------------------------
+This new hook has been added to net/sctp/sm_statefuns.c where it sets the
+sctp endpoint @ep->secid to the socket's sid (@ep->base.sk) with the MLS
+portion taken from the COOKIE ECHO packet @skb peer sid. Returns 0 on success,
+error on failure.
+
+ @ep - pointer to sctp endpoint structure.
+ @skb - pointer to skbuff of the COOKIE ECHO packet.
+
+To support this hook include/net/sctp/structs.h "struct sctp_endpoint" has
+been updated with the following:
+
+ /* Security identifiers from incoming (COOKIE-ECHO) connection.
+ * These are set by security_sctp_accept_conn() and used by
+ * security_sctp_sk_clone() to set sids on newsock.
+ */
+ u32 secid;
+ u32 peer_secid;
+
+
+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 for accept(2) (i.e. a TCP type socket)
+or when a socket is 'peeled off' e.g userspace calling sctp_peeloff(3).
+security_sctp_sk_clone() will set the new sockets sid and peer sid to that
+contained in the old @ep sid and peer sid respectively.
+
+ @ep - pointer to old sctp endpoint structure.
+ @sk - pointer to old sock structure.
+ @sk - pointer to new sock structure.
+
+
+security_sctp_addr_list()
+--------------------------
+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 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_PARAM_SET_PRIMARY | Single ipv4 or ipv6 address |
+ ------------------------------------------------------------------
+
+
+Security Hooks used for Association Establishment
+==================================================
+The following diagram shows the use of security_sctp_assoc_request(),
+security_sctp_accept_conn() 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()
+ Initiate an association to
+ SCTP peer endpoint "Z".
+ Send INIT first as we need to obtain
+ a peer label before checking whether
+ this is allowed or not. This will be
+ checked once the INIT ACK has been
+ received.
+ 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, then check
+ if association is allowed or not.
+ IF allowed 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". The security checks
+ are done now as we have a peer
+ label to check against, so call
+ security_sctp_assoc_request()
+ to set the peer label if first
+ association, then check if
+ association is allowed or not.
+ IF allowed send:
+ COOKIE ECHO ------------------------------------------>
+ ELSE audit event and silently |
+ discard the packet. |
+ |
+ sctp_sf_do_5_1D_ce
+ Call security_sctp_accept_conn()
+ This sets the sctp endpoint sid
+ to the socket's sid with the
+ MLS portion taken from the
+ COOKIE ECHO packet peer sid.
+ IF ok send:
+ <------------------------------------------- COOKIE ACK
+ | ELSE silently discard the packet.
+ | |
+ | |
+ | net/sctp/socket.c sctp_sock_migrate()
+ | If SCTP_SOCKET_TCP or peeled off
+ | socket security_sctp_sk_clone()
+ | is called to clone the new socket
+ | with the saved endpoint sid and
+ | peer sid.
+ | |
+ ESTABLISHED ESTABLISHED
+ | |
+ ------------------------------------------------------------------
+ | Association Established |
+ ------------------------------------------------------------------
+
+
@@ -902,6 +902,33 @@
* This hook can be used by the module to update any security state
* associated with the TUN device's security structure.
* @security pointer to the TUN devices's security structure.
+ * @sctp_assoc_request:
+ * If first association on @sk, then set the peer sid to that in @skb.
+ * @sk pointer to sock structure.
+ * @skb pointer to skbuff of association packet (INIT or INIT ACK)
+ * being queried.
+ * Return 0 on success, error on failure.
+ * @sctp_accept_conn:
+ * Sets 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 the COOKIE ECHO packet.
+ * 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.
+ * @sctp_addr_list:
+ * Check permissions required for each address before setting option
+ * associated with sock @sk. 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.
*
* Security hooks for XFRM operations.
*
@@ -1609,6 +1636,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 sock *sk, struct sk_buff *skb);
+ int (*sctp_accept_conn)(struct sctp_endpoint *ep, struct sk_buff *skb);
+ void (*sctp_sk_clone)(struct sctp_endpoint *ep, struct sock *sk,
+ struct sock *newsk);
+ int (*sctp_addr_list)(struct sock *sk, int optname,
+ struct sockaddr *address, int addrlen);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1840,6 +1873,10 @@ 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_accept_conn;
+ struct list_head sctp_sk_clone;
+ struct list_head sctp_addr_list;
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
struct list_head xfrm_policy_alloc_security;
@@ -109,6 +109,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;
@@ -1199,6 +1200,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 sock *sk, struct sk_buff *skb);
+int security_sctp_accept_conn(struct sctp_endpoint *ep, struct sk_buff *skb);
+void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
+ struct sock *newsk);
+int security_sctp_addr_list(struct sock *sk, int optname,
+ struct sockaddr *address, int addrlen);
#else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct sock *sock,
@@ -1391,6 +1398,32 @@ static inline int security_tun_dev_open(void *security)
{
return 0;
}
+
+static inline int security_sctp_assoc_request(struct sock *sk,
+ struct sk_buff *skb)
+{
+ return 0;
+}
+
+static inline int security_sctp_accept_conn(struct sctp_endpoint *ep,
+ struct sk_buff *skb)
+{
+ return 0;
+}
+
+static inline void security_sctp_sk_clone(struct sctp_endpoint *ep,
+ struct sock *sk,
+ struct sock *newsk)
+{
+ return 0;
+}
+
+static inline int security_sctp_addr_list(struct sock *sk, int optname,
+ struct sockaddr *address,
+ int addrlen)
+{
+ return 0;
+}
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1439,6 +1439,32 @@ int security_tun_dev_open(void *security)
}
EXPORT_SYMBOL(security_tun_dev_open);
+int security_sctp_assoc_request(struct sock *sk, struct sk_buff *skb)
+{
+ return call_int_hook(sctp_assoc_request, 0, sk, skb);
+}
+EXPORT_SYMBOL(security_sctp_assoc_request);
+
+int security_sctp_accept_conn(struct sctp_endpoint *ep, struct sk_buff *skb)
+{
+ return call_int_hook(sctp_accept_conn, 0, ep, skb);
+}
+EXPORT_SYMBOL(security_sctp_accept_conn);
+
+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);
+
+int security_sctp_addr_list(struct sock *sk, int optname,
+ struct sockaddr *address, int addrlen)
+{
+ return call_int_hook(sctp_addr_list, 0, sk, optname, address, addrlen);
+}
+EXPORT_SYMBOL(security_sctp_addr_list);
+
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1897,6 +1923,14 @@ struct security_hook_heads security_hook_heads = {
.tun_dev_attach =
LIST_HEAD_INIT(security_hook_heads.tun_dev_attach),
.tun_dev_open = LIST_HEAD_INIT(security_hook_heads.tun_dev_open),
+ .sctp_assoc_request =
+ LIST_HEAD_INIT(security_hook_heads.sctp_assoc_request),
+ .sctp_accept_conn =
+ LIST_HEAD_INIT(security_hook_heads.sctp_accept_conn),
+ .sctp_sk_clone =
+ LIST_HEAD_INIT(security_hook_heads.sctp_sk_clone),
+ .sctp_addr_list =
+ LIST_HEAD_INIT(security_hook_heads.sctp_addr_list),
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
.xfrm_policy_alloc_security =
Add four new SCTP hooks that are detailed in: Documentation/security/LSM-sctp.txt Signed-off-by: Richard Haines <richard_c_haines@btinternet.com> --- Documentation/security/LSM-sctp.txt | 171 ++++++++++++++++++++++++++++++++++++ include/linux/lsm_hooks.h | 37 ++++++++ include/linux/security.h | 33 +++++++ security/security.c | 34 +++++++ 4 files changed, 275 insertions(+) create mode 100644 Documentation/security/LSM-sctp.txt