lsm: introduce and use security_mptcp_add_subflow()
Subsystems (4)
Paolo Abeni
maintainerv2 cover lsm: introduce and use security_mptcp_add_subflow()
This series is an attempt to solve the LSM labeling breakage reported here:
As per previous discussion, a new LSM hook is introduced and invoked by the mptcp code to let LSMs set the appropriate label for the newly created subflow.
I'm not sure the chosen hook name is a perfect fit, any suggestion more then welcome.
The new hook requires both the mptcp socket reference and the subflow socket reference, even if the provided LSM implementation for selinux ends-up accessing only the subflow socket. Possibly other LSM implementation could need or use the addtional parameter.
Tested vs the issue reproducer and mptcp self-tests.
v1 -> v2:
- fix a few build issues with unusual configurations reported by bots
Paolo Abeni (2):
security, lsm: Introduce security_mptcp_add_subflow()
selinux: Implement mptcp_add_subflow hook
include/linux/lsm_hook_defs.h | 1 + include/linux/lsm_hooks.h | 9 +++++++++ include/linux/security.h | 6 ++++++ net/mptcp/subflow.c | 6 ++++++ security/security.c | 5 +++++ security/selinux/hooks.c | 27 +++++++++++++++++++++++++++ security/selinux/netlabel.c | 4 +++- 7 files changed, 57 insertions(+), 1 deletion(-)
Signature · 1 line
2.38.1
Paolo Abeni
maintainerPATCH v2 1/2 security, lsm: Introduce security_mptcp_add_subflow()
MPTCP can create subflows in kernel context, and later indirectly expose them to user-space, via the owning mptcp socket.
As discussed in the reported link, the above causes unexpected failures for server, MPTCP-enabled applications.
Let's introduce a new LSM hook to allow the security module to relabel the subflow according to the owing process.
Note that the new hook requires both the mptcp socket and the new subflow. This could allow future extensions, e.g. explicitly validating the mptcp <-> subflow linkage.
---
v1 -> v2:
- fix build issue with !CONFIG_SECURITY_NETWORK
--- include/linux/lsm_hook_defs.h | 1 + include/linux/lsm_hooks.h | 9 +++++++++ include/linux/security.h | 6 ++++++ net/mptcp/subflow.c | 6 ++++++ security/security.c | 5 +++++ 5 files changed, 27 insertions(+)
include/linux/lsm_hook_defs.h +1 -0
@@ -343,6 +343,7 @@ LSM_HOOK(void, LSM_RET_VOID, sctp_sk_clone, struct sctp_association *asoc, struct sock *sk, struct sock *newsk) LSM_HOOK(int, 0, sctp_assoc_established, struct sctp_association *asoc, struct sk_buff *skb) +LSM_HOOK(int, 0, mptcp_add_subflow, struct sock *sk, struct sock *ssk) #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND
include/linux/lsm_hooks.h +9 -0
@@ -1096,6 +1096,15 @@* @skb pointer to skbuff of association packet. * Return 0 if permission is granted. * +* Security hooks for MPTCP +* +* @mptcp_add_subflow +* Update the labeling for the given MPTCP subflow, to match to +* owning MPTCP socket. +* @sk: the owning MPTCP socket +* @ssk: the new subflow +* Return 0 if successful, otherwise < 0 error code. +* * Security hooks for Infiniband * * @ib_pkey_access:
include/linux/security.h +6 -0
@@ -1479,6 +1479,7 @@ void security_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk, struct sock *newsk);int security_sctp_assoc_established (struct sctp_association *asoc,struct sk_buff *skb); +int security_mptcp_add_subflow (struct sock *sk,struct sock *ssk);#else /* CONFIG_SECURITY_NETWORK */ static inline int security_unix_stream_connect(struct sock *sock,
@@ -1706,6 +1707,11 @@ static inline int security_sctp_assoc_established(struct sctp_association *asoc, {return 0 ; } + +static inline int security_mptcp_add_subflow (struct sock *sk,struct sock *ssk) +{ +return 0 ; +}#endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND
net/mptcp/subflow.c +6 -0
@@ -1680,6 +1680,10 @@ int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)lock_sock (sf->sk); + err =security_mptcp_add_subflow (sk, sf->sk); +if (err) + goto release_ssk; +/* the newly created socket has to be in the same cgroup as its parent */ mptcp_attach_cgroup (sk, sf->sk);
@@ -1692,6 +1696,8 @@ int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)get_net_track (net, &sf->sk->ns_tracker,GFP_KERNEL );sock_inuse_add (net,1 ); err =tcp_set_ulp (sf->sk,"mptcp" ); + +release_ssk:release_sock (sf->sk);if (err) {
security/security.c +5 -0
@@ -2493,6 +2493,11 @@ int security_sctp_assoc_established(struct sctp_association *asoc, }EXPORT_SYMBOL (security_sctp_assoc_established); +int security_mptcp_add_subflow (struct sock *sk,struct sock *ssk) +{ +return call_int_hook (mptcp_add_subflow,0 , sk, ssk); +} +#endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND
Signature · 1 line
2.38.1
Re: [PATCH v2 1/2] security, lsm: Introduce security_mptcp_add_subflow()
Quoted 19 lines · Paolo Abeni
MPTCP can create subflows in kernel context, and later indirectly expose them to user-space, via the owning mptcp socket.
As discussed in the reported link, the above causes unexpected failures for server, MPTCP-enabled applications.
Let's introduce a new LSM hook to allow the security module to relabel the subflow according to the owing process.
Note that the new hook requires both the mptcp socket and the new subflow. This could allow future extensions, e.g. explicitly validating the mptcp <-> subflow linkage.
Link https://lore.kernel.org/mptcp/CAHC9VhTNh-YwiyTds=P1e3rixEDqbRTFj22bpya=+qJqfcaMfg@mail.gmail.com/ open hereSigned-off-by Paolo Abeni <[email protected]>---
v1 -> v2:
- fix build issue with !CONFIG_SECURITY_NETWORK
---
Quoted 7 lines
include/linux/lsm_hook_defs.h | 1 + include/linux/lsm_hooks.h | 9 +++++++++ include/linux/security.h | 6 ++++++ net/mptcp/subflow.c | 6 ++++++ security/security.c | 5 +++++ 5 files changed, 27 insertions(+)
Hi Paolo -
Thanks for the patches, the MPTCP content looks good to me:
Quoted 16 lines
net/mptcp/subflow.c +4
-0@@ -1680,6 +1680,10 @@ int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)lock_sock (sf->sk); + err =security_mptcp_add_subflow (sk, sf->sk); +if (err) + goto release_ssk; +/* the newly created socket has to be in the same cgroup as its parent */ mptcp_attach_cgroup (sk, sf->sk);
net/mptcp/subflow.c int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock) · line 1703
Quoted 8 lines
net/mptcp/subflow.c +2
-0@@ -1692,6 +1696,8 @@ int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)get_net_track (net, &sf->sk->ns_tracker,GFP_KERNEL );sock_inuse_add (net,1 ); err =tcp_set_ulp (sf->sk,"mptcp" ); + +release_ssk:release_sock (sf->sk);if (err) {
--
Mat Martineau
Intel
Paolo Abeni
maintainerPATCH v2 2/2 selinux: Implement mptcp_add_subflow hook
In reply to Paolo AbeniNewly added subflows should inherit the associated label from the current process context, regarless of the sk_kern_sock flag value.
This patch implements the above resetting the subflow sid, deleting the existing subflow label, if any, and then re-creating a new one.
The new helper reuses the selinux_netlbl_sk_security_free() function, and it can end-up being called multiple times with the same argument; we additionally need to make it idempotent.
---
v1 -> v2:
- fix build issue with !CONFIG_NETLABEL
--- security/selinux/hooks.c | 27 +++++++++++++++++++++++++++ security/selinux/netlabel.c | 4 +++- 2 files changed, 30 insertions(+), 1 deletion(-)
security/selinux/hooks.c +27 -0
@@ -5476,6 +5476,32 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *skselinux_netlbl_sctp_sk_clone (sk, newsk); } +static int selinux_mptcp_add_subflow (struct sock *sk,struct sock *ssk) +{ +const struct task_security_struct *tsec =selinux_cred (current_cred ()); +struct sk_security_struct *ssksec = ssk->sk_security; +u16 sclass; +u32 sid; +int err; + +/* create the sid using the current cred, regardless of the ssk kern +* flag +*/ + sclass =socket_type_to_security_class (ssk->sk_family, ssk->sk_type, + ssk->sk_protocol); + err =socket_sockcreate_sid (tsec, sclass, &sid); +if (err) +return err; + + ssksec->sid = sid; + +/* replace the existing subflow label deleting the existing one +* and re-recrating a new label using the current context +*/ +selinux_netlbl_sk_security_free (ssksec); +return selinux_netlbl_socket_post_create (ssk, ssk->sk_family); +} +static int selinux_inet_conn_request (const struct sock *sk,struct sk_buff *skb,struct request_sock *req) {
@@ -7216,6 +7242,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {LSM_HOOK_INIT (sctp_sk_clone, selinux_sctp_sk_clone),LSM_HOOK_INIT (sctp_bind_connect, selinux_sctp_bind_connect),LSM_HOOK_INIT (sctp_assoc_established, selinux_sctp_assoc_established), +LSM_HOOK_INIT (mptcp_add_subflow, selinux_mptcp_add_subflow),LSM_HOOK_INIT (inet_conn_request, selinux_inet_conn_request),LSM_HOOK_INIT (inet_csk_clone, selinux_inet_csk_clone), LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
security/selinux/netlabel.c +3 -1
@@ -155,8 +155,10 @@ void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway)*/ void selinux_netlbl_sk_security_free (struct sk_security_struct *sksec) { -if (sksec->nlbl_secattr !=NULL ) +if (sksec->nlbl_secattr !=NULL ) {netlbl_secattr_free (sksec->nlbl_secattr); + sksec->nlbl_secattr =NULL ; + } }/**
Signature · 1 line
2.38.1
Re: selinux: Implement mptcp_add_subflow hook: Tests Results
Hi Paolo,
Thank you for your modifications, that's great!
Our CI did some validations and here is its report:
- KVM Validation: normal (except selftest_mptcp_join):
- Success! ✅:
- Task: https://cirrus-ci.com/task/6575725860356096
- Summary: https://api.cirrus-ci.com/v1/artifact/task/6575725860356096/summary/summary.txt
- KVM Validation: normal (only selftest_mptcp_join):
- Success! ✅:
- Task: https://cirrus-ci.com/task/4746138511736832
- Summary: https://api.cirrus-ci.com/v1/artifact/task/4746138511736832/summary/summary.txt
- KVM Validation: debug (only selftest_mptcp_join):
- Unstable: 1 failed test(s): selftest_mptcp_join 🔴:
- Task: https://cirrus-ci.com/task/5309088465158144
- Summary: https://api.cirrus-ci.com/v1/artifact/task/5309088465158144/summary/summary.txt
- KVM Validation: debug (except selftest_mptcp_join):
- Success! ✅:
- Task: https://cirrus-ci.com/task/6507154962644992
- Summary: https://api.cirrus-ci.com/v1/artifact/task/6507154962644992/summary/summary.txt
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/86a067dd1f5c
If there are some issues, you can reproduce them using the same environment as the one used by the CI thanks to a docker image, e.g.:
$ cd [kernel source code]
$ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
--pull always mptcp/mptcp-upstream-virtme-docker:latest \
auto-debugFor more details:
https://github.com/multipath-tcp/mptcp-upstream-virtme-docker
Please note that despite all the efforts that have been already done to have a stable tests suite when executed on a public CI like here, it is possible some reported issues are not due to your modifications. Still, do not hesitate to help us improve that ;-)
Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (Tessares)
Re: selinux: Implement mptcp_add_subflow hook: Tests Results
In reply to Paolo AbeniHi Paolo,
Thank you for your modifications, that's great!
Our CI did some validations and here is its report:
- KVM Validation: normal (except selftest_mptcp_join):
- Success! ✅:
- Task: https://cirrus-ci.com/task/6620708260806656
- Summary: https://api.cirrus-ci.com/v1/artifact/task/6620708260806656/summary/summary.txt
- KVM Validation: normal (only selftest_mptcp_join):
- Success! ✅:
- Task: https://cirrus-ci.com/task/4548841605693440
- Summary: https://api.cirrus-ci.com/v1/artifact/task/4548841605693440/summary/summary.txt
- KVM Validation: debug (except selftest_mptcp_join):
- Success! ✅:
- Task: https://cirrus-ci.com/task/5705914586497024
- Summary: https://api.cirrus-ci.com/v1/artifact/task/5705914586497024/summary/summary.txt
- KVM Validation: debug (only selftest_mptcp_join):
- Unstable: 1 failed test(s): selftest_mptcp_join 🔴:
- Task: https://cirrus-ci.com/task/5142964633075712
- Summary: https://api.cirrus-ci.com/v1/artifact/task/5142964633075712/summary/summary.txt
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/53ef095bcdc1
If there are some issues, you can reproduce them using the same environment as the one used by the CI thanks to a docker image, e.g.:
$ cd [kernel source code]
$ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
--pull always mptcp/mptcp-upstream-virtme-docker:latest \
auto-debugFor more details:
https://github.com/multipath-tcp/mptcp-upstream-virtme-docker
Please note that despite all the efforts that have been already done to have a stable tests suite when executed on a public CI like here, it is possible some reported issues are not due to your modifications. Still, do not hesitate to help us improve that ;-)
Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (Tessares)
Paul Moore
maintainerRe: [PATCH v2 2/2] selinux: Implement mptcp_add_subflow hook
In reply to Paolo AbeniQuoted 44 lines · Paolo Abeni
Newly added subflows should inherit the associated label from the current process context, regarless of the
sk_kern_sockflag value.This patch implements the above resetting the subflow sid, deleting the existing subflow label, if any, and then re-creating a new one.
The new helper reuses the
selinux_netlbl_sk_security_free()function, and it can end-up being called multiple times with the same argument; we additionally need to make it idempotent.Signed-off-by Paolo Abeni <[email protected]>---
v1 -> v2:
- fix build issue with !CONFIG_NETLABEL--- security/selinux/hooks.c | 27 +++++++++++++++++++++++++++ security/selinux/netlabel.c | 4 +++- 2 files changed, 30 insertions(+), 1 deletion(-)security/selinux/hooks.c +15
-0@@ -5476,6 +5476,32 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *skselinux_netlbl_sctp_sk_clone (sk, newsk); } +static int selinux_mptcp_add_subflow (struct sock *sk,struct sock *ssk) +{ +const struct task_security_struct *tsec =selinux_cred (current_cred ()); +struct sk_security_struct *ssksec = ssk->sk_security; +u16 sclass; +u32 sid; +int err; + +/* create the sid using the current cred, regardless of the ssk kern +* flag +*/ + sclass =socket_type_to_security_class (ssk->sk_family, ssk->sk_type, + ssk->sk_protocol); + err =socket_sockcreate_sid (tsec, sclass, &sid); +if (err)
security/selinux/hooks.c static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk · line 5503
Quoted 10 lines
security/selinux/hooks.c +10
-0+return err; + + ssksec->sid = sid; + +/* replace the existing subflow label deleting the existing one +* and re-recrating a new label using the current context +*/ +selinux_netlbl_sk_security_free (ssksec); +return selinux_netlbl_socket_post_create (ssk, ssk->sk_family); +}
I thought the idea was to ensure that new subflows of an existing MPTCP connection would be created with the same label as the main MPTCP connection socket? The code above labels the new subflow based on the current process, not the main MPTCP connection; it matches the commit description, but not what we had previously discussed - or I am horribly mis-remembering something? :)
I was expecting something more like the following:
static int selinux_mptcp_add_subflow(...)
{
struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *ssksec = ssk->sk_security;
ssksec->sclass = sksec->sclass; ssksec->sid = sksec->sid;
selinux_netlbl_sk_security_free(ssksec); selinux_netlbl_socket_post_create(ssk, ssk->sk_family);
}
Quoted 5 lines
security/selinux/netlabel.c +0
-0
security/selinux/netlabel.c void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway) · line 162
Quoted 9 lines
security/selinux/netlabel.c +3
-1@@ -155,8 +155,10 @@ void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway)*/ void selinux_netlbl_sk_security_free (struct sk_security_struct *sksec) { -if (sksec->nlbl_secattr !=NULL ) +if (sksec->nlbl_secattr !=NULL ) {netlbl_secattr_free (sksec->nlbl_secattr); + sksec->nlbl_secattr =NULL ; + } }
This is pretty nitpicky, but it might be a little cleaner to use the pattern below. At the very least I think it tends to better match a lot of the various free helpers in the kernel.
void free_stuff(void *ptr)
{
if (!ptr)
return;
free_properly(ptr);
}
I would probably also reset sk_security_struct::nlbl_state too, so maybe something like the following:
void selinux_netlbl_sk_security_free(...)
{
if (!sksec)
return;
netlbl_secattr_free(sksec->nlbl_secattr);
sksec->nlbl_secattr = NULL;
sksec->nlbl_state = NLBL_UNSET;
}
Signature · 1 line
paul-moore.com
Paolo Abeni
maintainerRe: [PATCH v2 2/2] selinux: Implement mptcp_add_subflow hook
Quoted 54 lines · Paul Moore
Quoted 53 lines · Paolo Abeni
Newly added subflows should inherit the associated label from the current process context, regarless of the
sk_kern_sockflag value.This patch implements the above resetting the subflow sid, deleting the existing subflow label, if any, and then re-creating a new one.
The new helper reuses the
selinux_netlbl_sk_security_free()function, and it can end-up being called multiple times with the same argument; we additionally need to make it idempotent.Signed-off-by Paolo Abeni <[email protected]>---
v1 -> v2:
- fix build issue with !CONFIG_NETLABEL--- security/selinux/hooks.c | 27 +++++++++++++++++++++++++++ security/selinux/netlabel.c | 4 +++- 2 files changed, 30 insertions(+), 1 deletion(-)security/selinux/hooks.c +24
-0@@ -5476,6 +5476,32 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *skselinux_netlbl_sctp_sk_clone (sk, newsk); } +static int selinux_mptcp_add_subflow (struct sock *sk,struct sock *ssk) +{ +const struct task_security_struct *tsec =selinux_cred (current_cred ()); +struct sk_security_struct *ssksec = ssk->sk_security; +u16 sclass; +u32 sid; +int err; + +/* create the sid using the current cred, regardless of the ssk kern +* flag +*/ + sclass =socket_type_to_security_class (ssk->sk_family, ssk->sk_type, + ssk->sk_protocol); + err =socket_sockcreate_sid (tsec, sclass, &sid); +if (err) +return err; + + ssksec->sid = sid; + +/* replace the existing subflow label deleting the existing one +* and re-recrating a new label using the current context +*/ +selinux_netlbl_sk_security_free (ssksec); +return selinux_netlbl_socket_post_create (ssk, ssk->sk_family);
Quoted 8 lines
security/selinux/hooks.c static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk · line 5503
Quoted 1 line
security/selinux/hooks.c +1
-0+}I thought the idea was to ensure that new subflows of an existing MPTCP connection would be created with the same label as the main MPTCP connection socket? The code above labels the new subflow based on the current process, not the main MPTCP connection; it matches the commit description, but not what we had previously discussed - or I am horribly mis-remembering something? :)
You are right, I picked a wrong turn.
I just tested the other option and there is another problem :(
The first subflow creations happens inside af_inet->create, via the sk-
Quoted 1 line
sk_prot->init()hook. Thesecurity_socket_post_create()call on the
owning MPTCP sockets happens after that point. So we copy data from a not yet initialized security context (and the test fail badly).
There are a few options to cope with that:
- [ugly hack] call security_socket_post_create() on the mptcp code before creating the subflow. I experimented this just to double the problem and a possible solution.
- refactor the mptcp code to create the first subflow on later syscalls, as needed. This will require quite a bit of refactoring in the MPTCP protocol as we will need also to update the shutdown/disconnect accordingly (currently we keep the first subflow around, instead we will need to close it).
- use the code proposed in these patches as-is ;)
WDYT?
Thanks,
Paolo
Paul Moore
maintainerRe: [PATCH v2 2/2] selinux: Implement mptcp_add_subflow hook
Quoted 64 lines · Paolo Abeni
Quoted 54 lines · Paul Moore
Quoted 53 lines · Paolo Abeni
Newly added subflows should inherit the associated label from the current process context, regarless of the
sk_kern_sockflag value.This patch implements the above resetting the subflow sid, deleting the existing subflow label, if any, and then re-creating a new one.
The new helper reuses the
selinux_netlbl_sk_security_free()function, and it can end-up being called multiple times with the same argument; we additionally need to make it idempotent.Signed-off-by Paolo Abeni <[email protected]>---
v1 -> v2:
- fix build issue with !CONFIG_NETLABEL--- security/selinux/hooks.c | 27 +++++++++++++++++++++++++++ security/selinux/netlabel.c | 4 +++- 2 files changed, 30 insertions(+), 1 deletion(-)security/selinux/hooks.c +24
-0@@ -5476,6 +5476,32 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *skselinux_netlbl_sctp_sk_clone (sk, newsk); } +static int selinux_mptcp_add_subflow (struct sock *sk,struct sock *ssk) +{ +const struct task_security_struct *tsec =selinux_cred (current_cred ()); +struct sk_security_struct *ssksec = ssk->sk_security; +u16 sclass; +u32 sid; +int err; + +/* create the sid using the current cred, regardless of the ssk kern +* flag +*/ + sclass =socket_type_to_security_class (ssk->sk_family, ssk->sk_type, + ssk->sk_protocol); + err =socket_sockcreate_sid (tsec, sclass, &sid); +if (err) +return err; + + ssksec->sid = sid; + +/* replace the existing subflow label deleting the existing one +* and re-recrating a new label using the current context +*/ +selinux_netlbl_sk_security_free (ssksec); +return selinux_netlbl_socket_post_create (ssk, ssk->sk_family);Quoted 8 lines
security/selinux/hooks.c static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk · line 5503
Quoted 1 line
security/selinux/hooks.c +1
-0+}I thought the idea was to ensure that new subflows of an existing MPTCP connection would be created with the same label as the main MPTCP connection socket? The code above labels the new subflow based on the current process, not the main MPTCP connection; it matches the commit description, but not what we had previously discussed - or I am horribly mis-remembering something? :)
Quoted 3 lines
You are right, I picked a wrong turn.
I just tested the other option and there is another problem :(
It's never easy, is it? ;)
Quoted 4 lines
The first subflow creations happens inside
af_inet->create, via the sk-Quoted 1 line
sk_prot->init()hook. Thesecurity_socket_post_create()call on theowning MPTCP sockets happens after that point. So we copy data from a not yet initialized security context (and the test fail badly).
Hmmm. Let's come back to this later on down this email.
Quoted 4 lines
There are a few options to cope with that:
- [ugly hack] callsecurity_socket_post_create()on the mptcp code before creating the subflow. I experimented this just to double the problem and a possible solution.
I'm guessing "[ugly hack]" is probably a bit of an understatement. Let's see if we can do better before we explore this option too much further.
Quoted 5 lines
- refactor the mptcp code to create the first subflow on later syscalls, as needed. This will require quite a bit of refactoring in the MPTCP protocol as we will need also to update the shutdown/disconnect accordingly (currently we keep the first subflow around, instead we will need to close it).
Let's see if we can avoid having to do this too.
Quoted 1 line
- use the code proposed in these patches as-is ;)
That's a non-starter from a SELinux perspective as the label is incorrect. It would be similar to saying that for each fork() call the resulting child process would always run as root since we couldn't figure out how to assign the credentials properly :)
Quoted 1 line
WDYT?
Let's go back to the the inet_create() case for a little bit. I'm thinking we might be able to do something by leveraging the sk_alloc()->sk_prot_alloc()->security_sk_alloc() code path. As inet_create() is going to be called from task context here, it seems like we could do the sock's sid/sclass determination here, cached in separate fields in the sk_security_struct if necessary, and use those in a new MPTCP subflow hook. We could also update selinux_socket_post_create() to take advantage of this as well. We could also possibly pass the proto struct into security_sk_alloc() if we needed to identify IPPROTO_MPTCP there as well.
I'll admit to not chasing down all the details, but I suspect this may be the cleanest option - thoughts?
--
paul-moore.com
Paolo Abeni
maintainerRe: [PATCH v2 2/2] selinux: Implement mptcp_add_subflow hook
Quoted 12 lines · Paul Moore
Quoted 1 line · Paolo Abeni
I just tested the other option and there is another problem :(
It's never easy, is it? ;)
Quoted 4 lines
The first subflow creations happens inside
af_inet->create, via the sk-Quoted 1 line
sk_prot->init()hook. Thesecurity_socket_post_create()call on theowning MPTCP sockets happens after that point. So we copy data from a not yet initialized security context (and the test fail badly).
Hmmm. Let's come back to this later on down this email.
Quoted 8 lines
Quoted 4 lines
There are a few options to cope with that:
- [ugly hack] callsecurity_socket_post_create()on the mptcp code before creating the subflow. I experimented this just to double the problem and a possible solution.I'm guessing "[ugly hack]" is probably a bit of an understatement. Let's see if we can do better before we explore this option too much further.
Yup, I compiled the list in "brainstom-mode", trying to include whatever would be possible even if clearly not suitable.
[...]
Quoted 13 lines
Quoted 1 line
WDYT?
Let's go back to the the
inet_create()case for a little bit. I'm thinking we might be able to do something by leveraging the sk_alloc()->sk_prot_alloc()->security_sk_alloc() code path. Asinet_create()is going to be called from task context here, it seems like we could do the sock's sid/sclass determination here, cached in separate fields in thesk_security_structif necessary, and use those in a new MPTCP subflow hook. We could also updateselinux_socket_post_create()to take advantage of this as well. We could also possibly pass the proto struct intosecurity_sk_alloc()if we needed to identifyIPPROTO_MPTCPthere as well.
Quoted 2 lines
I'll admit to not chasing down all the details, but I suspect this may be the cleanest option - thoughts?
Thanks, I did not consider such possibility!
I think we should be careful to avoid increasing sk_security_struct size. Currently it is 16 bytes, nicely matching a kmalloc slab, any increase will move it on kmalloc-32 bytes slab possibly causing performance and memory regressions).
More importantly, I think there is a problem with the sk_clone_lock() -> sk_prot_alloc() -> security_sk_alloc() code path.
sk_clone_lock() happens in BH context, if security_transition_sid() needs process context that would be a problem - quickly skimming the code it does not look so, I need to double check.
sk_clone_lock() is in a very critical path - socket creation for incoming connections. The sid-related operation there will be unnecessary/discarded by later the selinux_inet_csk_clone(), this will likelly cause performance regressions even for plain TCP sockets.
Perhaps the cleanest option could be the one involving the mptcp refactoring, moving subflow creation at a later stage. It could have some minor side benefit for MPTCP, too - solving:
https://github.com/multipath-tcp/mptcp_net-next/issues/290
but I'm not fond of that option because it will require quite a bit of
time: we need first to have the mptcp refactor in place and then cook the lsm patches. I guess such process will require at least 2 release cycles, due to the needed mptcp(netdev)/lsm trees synchronization.
If that would prove to be the most reasonable option, could we consider to transiently merge first something alike:
to have a workable short-term solution, and later revert it when the final solution would be in place?
Thanks,
Paolo
Paul Moore
maintainerRe: [PATCH v2 2/2] selinux: Implement mptcp_add_subflow hook
Quoted 44 lines · Paolo Abeni
Quoted 12 lines · Paul Moore
Quoted 1 line · Paolo Abeni
I just tested the other option and there is another problem :(
It's never easy, is it? ;)
Quoted 4 lines
The first subflow creations happens inside
af_inet->create, via the sk-Quoted 1 line
sk_prot->init()hook. Thesecurity_socket_post_create()call on theowning MPTCP sockets happens after that point. So we copy data from a not yet initialized security context (and the test fail badly).
Hmmm. Let's come back to this later on down this email.
Quoted 8 lines
Quoted 4 lines
There are a few options to cope with that:
- [ugly hack] callsecurity_socket_post_create()on the mptcp code before creating the subflow. I experimented this just to double the problem and a possible solution.I'm guessing "[ugly hack]" is probably a bit of an understatement. Let's see if we can do better before we explore this option too much further.
Yup, I compiled the list in "brainstom-mode", trying to include whatever would be possible even if clearly not suitable.
[...]
Quoted 13 lines
Quoted 1 line
WDYT?
Let's go back to the the
inet_create()case for a little bit. I'm thinking we might be able to do something by leveraging the sk_alloc()->sk_prot_alloc()->security_sk_alloc() code path. Asinet_create()is going to be called from task context here, it seems like we could do the sock's sid/sclass determination here, cached in separate fields in thesk_security_structif necessary, and use those in a new MPTCP subflow hook. We could also updateselinux_socket_post_create()to take advantage of this as well. We could also possibly pass the proto struct intosecurity_sk_alloc()if we needed to identifyIPPROTO_MPTCPthere as well.Quoted 2 lines
I'll admit to not chasing down all the details, but I suspect this may be the cleanest option - thoughts?
Quoted 6 lines
Thanks, I did not consider such possibility!
I think we should be careful to avoid increasing
sk_security_structsize. Currently it is 16 bytes, nicely matching a kmalloc slab, any increase will move it on kmalloc-32 bytes slab possibly causing performance and memory regressions).
FWIW, it is likely that this will end up growing in the future to support stacking LSMs. It's unfortunate, messy, and generally ugly, but inevitable.
See the selinux_inode() function as a similar example using inode/inode_security_struct.
Quoted 7 lines
More importantly, I think there is a problem with the
sk_clone_lock()->sk_prot_alloc()->security_sk_alloc()code path.
sk_clone_lock()happens in BH context, ifsecurity_transition_sid()needs process context that would be a problem - quickly skimming the code it does not look so, I need to double check.
The problem is that in both selinux_socket_create() and selinux_socket_post_create() the credentials from @current are needed to determine the sock/sk_security_stuct label. In selinux_socket_create() @current's credentials are also used to determine if the socket can be created.
It's looking like doing labeling determinations in the security_sk_alloc() struct is not going to work. While sk_clone_lock() will end up calling into security_sk_clone()/selinux_sk_clone_security() via sock_copy(), if I understand you correctly that won't help as the main MPTCP socket is not yet setup (e.g. selinux_socket_post_create() has not yet been run on the main socket).
Quoted 10 lines
Perhaps the cleanest option could be the one involving the mptcp refactoring, moving subflow creation at a later stage. It could have some minor side benefit for MPTCP, too - solving:
https://github.com/multipath-tcp/mptcp_net-next/issues/290
but I'm not fond of that option because it will require quite a bit of
time: we need first to have the mptcp refactor in place and then cook the lsm patches. I guess such process will require at least 2 release cycles, due to the needed mptcp(netdev)/lsm trees synchronization.
I generally take the long term view when it comes to Linux Kernel development; given the nature of the kernel, and all the constraints that come with it, I would much rather pursue solutions that we believe have the longest staying power.
I'm also happy to work on, and/or review, LSM patches in conjunction with a MPTCP refactor. If the only reason to split the work over two kernel releases is to soften the blow during the merge window, I think we can work that out in a single release ... at least I say that now :)
Basically when it comes down to it, I want to make sure that any fix we come up with *works*. In my mind that means doing the LSM fix in conjunction with the rework; I would hate to see all of the rework happen only to find out later that it still didn't solve the LSM problem.
Does that make sense?
Quoted 7 lines
If that would prove to be the most reasonable option, could we consider to transiently merge first something alike:
to have a workable short-term solution, and later revert it when the final solution would be in place?
I would need to go back through that to make sure that it makes sense, and ensure that the hook is idempotent for SELinux, AppArmor, and Smack (current hook implementations), *aaaand* if we promise that this is just a *temporary* hack I think I would be okay with that.
Signature · 1 line
paul-moore.com
Paolo Abeni
maintainerRe: [PATCH v2 2/2] selinux: Implement mptcp_add_subflow hook
Hello,
I'm sorry for the long delay: I was on PTO with limited internet access.
Quoted 97 lines · Paul Moore
Quoted 44 lines · Paolo Abeni
Quoted 12 lines · Paul Moore
Quoted 1 line · Paolo Abeni
I just tested the other option and there is another problem :(
It's never easy, is it? ;)
Quoted 4 lines
The first subflow creations happens inside
af_inet->create, via the sk-Quoted 1 line
sk_prot->init()hook. Thesecurity_socket_post_create()call on theowning MPTCP sockets happens after that point. So we copy data from a not yet initialized security context (and the test fail badly).
Hmmm. Let's come back to this later on down this email.
Quoted 8 lines
Quoted 4 lines
There are a few options to cope with that:
- [ugly hack] callsecurity_socket_post_create()on the mptcp code before creating the subflow. I experimented this just to double the problem and a possible solution.I'm guessing "[ugly hack]" is probably a bit of an understatement. Let's see if we can do better before we explore this option too much further.
Yup, I compiled the list in "brainstom-mode", trying to include whatever would be possible even if clearly not suitable.
[...]
Quoted 13 lines
Quoted 1 line
WDYT?
Let's go back to the the
inet_create()case for a little bit. I'm thinking we might be able to do something by leveraging the sk_alloc()->sk_prot_alloc()->security_sk_alloc() code path. Asinet_create()is going to be called from task context here, it seems like we could do the sock's sid/sclass determination here, cached in separate fields in thesk_security_structif necessary, and use those in a new MPTCP subflow hook. We could also updateselinux_socket_post_create()to take advantage of this as well. We could also possibly pass the proto struct intosecurity_sk_alloc()if we needed to identifyIPPROTO_MPTCPthere as well.Quoted 2 lines
I'll admit to not chasing down all the details, but I suspect this may be the cleanest option - thoughts?
Quoted 6 lines
Thanks, I did not consider such possibility!
I think we should be careful to avoid increasing
sk_security_structsize. Currently it is 16 bytes, nicely matching a kmalloc slab, any increase will move it on kmalloc-32 bytes slab possibly causing performance and memory regressions).FWIW, it is likely that this will end up growing in the future to support stacking LSMs. It's unfortunate, messy, and generally ugly, but inevitable.
See the
selinux_inode()function as a similar example using inode/inode_security_struct.Quoted 7 lines
More importantly, I think there is a problem with the
sk_clone_lock()->sk_prot_alloc()->security_sk_alloc()code path.
sk_clone_lock()happens in BH context, ifsecurity_transition_sid()needs process context that would be a problem - quickly skimming the code it does not look so, I need to double check.The problem is that in both
selinux_socket_create()andselinux_socket_post_create()the credentials from @current are needed to determine the sock/sk_security_stuct label. Inselinux_socket_create()@current's credentials are also used to determine if the socket can be created.It's looking like doing labeling determinations in the
security_sk_alloc()struct is not going to work. Whilesk_clone_lock()will end up calling into security_sk_clone()/selinux_sk_clone_security() viasock_copy(), if I understand you correctly that won't help as the main MPTCP socket is not yet setup (e.g.selinux_socket_post_create()has not yet been run on the main socket).Quoted 10 lines
Perhaps the cleanest option could be the one involving the mptcp refactoring, moving subflow creation at a later stage. It could have some minor side benefit for MPTCP, too - solving:
https://github.com/multipath-tcp/mptcp_net-next/issues/290
but I'm not fond of that option because it will require quite a bit of
time: we need first to have the mptcp refactor in place and then cook the lsm patches. I guess such process will require at least 2 release cycles, due to the needed mptcp(netdev)/lsm trees synchronization.I generally take the long term view when it comes to Linux Kernel development; given the nature of the kernel, and all the constraints that come with it, I would much rather pursue solutions that we believe have the longest staying power.
Quoted 5 lines
I'm also happy to work on, and/or review, LSM patches in conjunction with a MPTCP refactor. If the only reason to split the work over two kernel releases is to soften the blow during the merge window, I think we can work that out in a single release ... at least I say that now :)
I thought about doing the MPTCP and selinux patches sequentially to both avoid the possibly untrivial conflicts resultion issues and to ensure that the mptcp patches are in place when the selinux ones are applied, as there is a fuctional dependency.
Quoted 7 lines
Basically when it comes down to it, I want to make sure that any fix we come up with *works*. In my mind that means doing the LSM fix in conjunction with the rework; I would hate to see all of the rework happen only to find out later that it still didn't solve the LSM problem.
Does that make sense?
Indeed it makes sense to me.
I think we can address that concern in a quite consolidated way. We usually include in the MPTCP tree a (very limited) number of patches that will not be submitted to the netdev because belong to other trees and/or are handled/owned by others devel.
We use the above e.g. to fix build and/or functional issues in our self-tests caused by other subsystems without the need to wait for the proper fix to land into vanilla. When such event happen, we simply drop the local copy of the fixup patch.
We could use a similar schema in this scenario. We can include the the LSM patches to the mptcp in our tree while the rework is in progress to ensure that overall the effort really addresses the LSM issue.
We can rebase the LSM patches as needed to address conflicts as needed/if/when they pops up.
Once that the mptcp patches will land into the LSM tree, we will submit formally the LSM ones to you. During the process I'll check and ensure that the LSM issue is really/still fixed. Would that work for you?
Quoted 5 lines
Quoted 5 lines
If that would prove to be the most reasonable option, could we consider to transiently merge first something alike:
Quoted 7 lines
Quoted 2 lines
to have a workable short-term solution, and later revert it when the final solution would be in place?
I would need to go back through that to make sure that it makes sense, and ensure that the hook is idempotent for SELinux, AppArmor, and Smack (current hook implementations), *aaaand* if we promise that this is just a *temporary* hack I think I would be okay with that.
I would appreciate that addtional extra mile a lot, as it will allow a (temporary!) fix to be delivered quite earlier than what the above process will provide.
Of course the deal is that I'll take ownership of pursuing the complete fix till resolution.
Many thanks!
Paolo
Paul Moore
maintainerRe: [PATCH v2 2/2] selinux: Implement mptcp_add_subflow hook
Quoted 4 lines · Paolo Abeni
Hello,
I'm sorry for the long delay: I was on PTO with limited internet access.
No worries, I hear even kernel developers are allowed to take time off occasionally ... at least that's what they tell me ;)
(I hope you're enjoying the time away!)
Quoted 4 lines · Paul Moore
Quoted 3 lines · Paolo Abeni
Quoted 2 lines · Paul Moore
Quoted 1 line · Paolo Abeni
...
Quoted 11 lines
Quoted 10 lines
I generally take the long term view when it comes to Linux Kernel development; given the nature of the kernel, and all the constraints that come with it, I would much rather pursue solutions that we believe have the longest staying power.
I'm also happy to work on, and/or review, LSM patches in conjunction with a MPTCP refactor. If the only reason to split the work over two kernel releases is to soften the blow during the merge window, I think we can work that out in a single release ... at least I say that now :)
Quoted 4 lines
I thought about doing the MPTCP and selinux patches sequentially to both avoid the possibly untrivial conflicts resultion issues and to ensure that the mptcp patches are in place when the selinux ones are applied, as there is a fuctional dependency.
Sure, when working across subsystems there is usually some sort of dependency challenge which dictates which side is tackled first, I just wanted to make sure we don't consider one side "done" until we finish both sides.
Quoted 24 lines
Quoted 7 lines
Basically when it comes down to it, I want to make sure that any fix we come up with *works*. In my mind that means doing the LSM fix in conjunction with the rework; I would hate to see all of the rework happen only to find out later that it still didn't solve the LSM problem.
Does that make sense?
Indeed it makes sense to me.
I think we can address that concern in a quite consolidated way. We usually include in the MPTCP tree a (very limited) number of patches that will not be submitted to the netdev because belong to other trees and/or are handled/owned by others devel.
We use the above e.g. to fix build and/or functional issues in our self-tests caused by other subsystems without the need to wait for the proper fix to land into vanilla. When such event happen, we simply drop the local copy of the fixup patch.
We could use a similar schema in this scenario. We can include the the LSM patches to the mptcp in our tree while the rework is in progress to ensure that overall the effort really addresses the LSM issue.
Quoted 6 lines
We can rebase the LSM patches as needed to address conflicts as needed/if/when they pops up.
Once that the mptcp patches will land into the LSM tree, we will submit formally the LSM ones to you. During the process I'll check and ensure that the LSM issue is really/still fixed. Would that work for you?
Sure, I'm pretty flexible on how we do these things, I just want it to end up fixed in Linus' tree and there are plenty of ways we can make that happen :)
Quoted 13 lines
Quoted 5 lines
Quoted 5 lines
If that would prove to be the most reasonable option, could we consider to transiently merge first something alike:
Quoted 7 lines
Quoted 2 lines
to have a workable short-term solution, and later revert it when the final solution would be in place?
I would need to go back through that to make sure that it makes sense, and ensure that the hook is idempotent for SELinux, AppArmor, and Smack (current hook implementations), *aaaand* if we promise that this is just a *temporary* hack I think I would be okay with that.
Quoted 6 lines
I would appreciate that addtional extra mile a lot, as it will allow a (temporary!) fix to be delivered quite earlier than what the above process will provide.
Of course the deal is that I'll take ownership of pursuing the complete fix till resolution.
Okay, let me do the investigation mentioned above to make sure this is possible and report back (I need to refresh my memory first, the holiday break kinda flushed this out of my mind ;).
Signature · 1 line
paul-moore.com