Message ID | 3074022fdca04676443a9c74f57328eb729f150e.1671469167.git.pabeni@redhat.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Paul Moore |
Headers | show |
Series | lsm: introduce and use security_mptcp_add_subflow() | expand |
On Mon, Dec 19, 2022 at 12:34 PM Paolo Abeni <pabeni@redhat.com> wrote: > > Newly 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. > > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > --- > 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(-) > > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c > index 3c5be76a9199..f785600b666a 100644 > --- a/security/selinux/hooks.c > +++ b/security/selinux/hooks.c > @@ -5476,6 +5476,32 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk > selinux_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); > +} 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); } > diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c > index 1321f15799e2..8e0080b8a8ef 100644 > --- a/security/selinux/netlabel.c > +++ b/security/selinux/netlabel.c > @@ -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; }
On Tue, 2022-12-20 at 17:07 -0500, Paul Moore wrote: > On Mon, Dec 19, 2022 at 12:34 PM Paolo Abeni <pabeni@redhat.com> wrote: > > > > Newly 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. > > > > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > > --- > > 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(-) > > > > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c > > index 3c5be76a9199..f785600b666a 100644 > > --- a/security/selinux/hooks.c > > +++ b/security/selinux/hooks.c > > @@ -5476,6 +5476,32 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk > > selinux_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); > > +} > > 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- >sk_prot->init() hook. The security_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
On Wed, Dec 21, 2022 at 2:24 PM Paolo Abeni <pabeni@redhat.com> wrote: > On Tue, 2022-12-20 at 17:07 -0500, Paul Moore wrote: > > On Mon, Dec 19, 2022 at 12:34 PM Paolo Abeni <pabeni@redhat.com> wrote: > > > > > > Newly 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. > > > > > > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > > > --- > > > 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(-) > > > > > > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c > > > index 3c5be76a9199..f785600b666a 100644 > > > --- a/security/selinux/hooks.c > > > +++ b/security/selinux/hooks.c > > > @@ -5476,6 +5476,32 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk > > > selinux_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); > > > +} > > > > 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 :( It's never easy, is it? ;) > The first subflow creations happens inside af_inet->create, via the sk- > >sk_prot->init() hook. The security_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). Hmmm. Let's come back to this later on down this email. > 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. 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. > - 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. > - 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 :) > 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
On Wed, 2022-12-21 at 20:21 -0500, Paul Moore wrote: > On Wed, Dec 21, 2022 at 2:24 PM Paolo Abeni <pabeni@redhat.com> wrote: > > I just tested the other option and there is another problem :( > > It's never easy, is it? ;) > > > The first subflow creations happens inside af_inet->create, via the sk- > > > sk_prot->init() hook. The security_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). > > Hmmm. Let's come back to this later on down this email. > > > 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. > > 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. [...] > > 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? 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: https://lore.kernel.org/mptcp/CAHC9VhSQnhH3UL4gqzu+YiA1Q3YyLLCv88gLJOvw-0+uw5Lvkw@mail.gmail.com/T/#m06c612f84f6b6fe759e670573b2c8092df71607b to have a workable short-term solution, and later revert it when the final solution would be in place? Thanks, Paolo
On Thu, Dec 22, 2022 at 10:57 AM Paolo Abeni <pabeni@redhat.com> wrote: > > On Wed, 2022-12-21 at 20:21 -0500, Paul Moore wrote: > > On Wed, Dec 21, 2022 at 2:24 PM Paolo Abeni <pabeni@redhat.com> wrote: > > > I just tested the other option and there is another problem :( > > > > It's never easy, is it? ;) > > > > > The first subflow creations happens inside af_inet->create, via the sk- > > > > sk_prot->init() hook. The security_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). > > > > Hmmm. Let's come back to this later on down this email. > > > > > 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. > > > > 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. > > [...] > > > > 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? > > 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). 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. > 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. 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). > 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? > If that would prove to be the most reasonable option, could we consider > to transiently merge first something alike: > > https://lore.kernel.org/mptcp/CAHC9VhSQnhH3UL4gqzu+YiA1Q3YyLLCv88gLJOvw-0+uw5Lvkw@mail.gmail.com/T/#m06c612f84f6b6fe759e670573b2c8092df71607b > > 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.
Hello, I'm sorry for the long delay: I was on PTO with limited internet access. On Fri, 2022-12-23 at 12:11 -0500, Paul Moore wrote: > On Thu, Dec 22, 2022 at 10:57 AM Paolo Abeni <pabeni@redhat.com> wrote: > > > > On Wed, 2022-12-21 at 20:21 -0500, Paul Moore wrote: > > > On Wed, Dec 21, 2022 at 2:24 PM Paolo Abeni <pabeni@redhat.com> wrote: > > > > I just tested the other option and there is another problem :( > > > > > > It's never easy, is it? ;) > > > > > > > The first subflow creations happens inside af_inet->create, via the sk- > > > > > sk_prot->init() hook. The security_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). > > > > > > Hmmm. Let's come back to this later on down this email. > > > > > > > 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. > > > > > > 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. > > > > [...] > > > > > > 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? > > > > 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). > > 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. > > > 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. > > 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). > > > 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 > :) 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. > 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? > > If that would prove to be the most reasonable option, could we consider > > to transiently merge first something alike: > > > > https://lore.kernel.org/mptcp/CAHC9VhSQnhH3UL4gqzu+YiA1Q3YyLLCv88gLJOvw-0+uw5Lvkw@mail.gmail.com/T/#m06c612f84f6b6fe759e670573b2c8092df71607b > > > > 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
On Mon, Jan 9, 2023 at 5:31 AM Paolo Abeni <pabeni@redhat.com> wrote: > 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!) > On Fri, 2022-12-23 at 12:11 -0500, Paul Moore wrote: > > On Thu, Dec 22, 2022 at 10:57 AM Paolo Abeni <pabeni@redhat.com> wrote: > > > On Wed, 2022-12-21 at 20:21 -0500, Paul Moore wrote: > > > > On Wed, Dec 21, 2022 at 2:24 PM Paolo Abeni <pabeni@redhat.com> wrote: ... > > 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 > > :) > > 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. > > 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? 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 :) > > > If that would prove to be the most reasonable option, could we consider > > > to transiently merge first something alike: > > > > > > https://lore.kernel.org/mptcp/CAHC9VhSQnhH3UL4gqzu+YiA1Q3YyLLCv88gLJOvw-0+uw5Lvkw@mail.gmail.com/T/#m06c612f84f6b6fe759e670573b2c8092df71607b > > > > > > 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. 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 ;).
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3c5be76a9199..f785600b666a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5476,6 +5476,32 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk selinux_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), diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 1321f15799e2..8e0080b8a8ef 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -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; + } } /**
Newly 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. Signed-off-by: Paolo Abeni <pabeni@redhat.com> --- 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(-)