diff mbox series

[v2] selinux: various sparse fixes

Message ID 164330771809.139041.6643670399086580972.stgit@olly (mailing list archive)
State Accepted
Delegated to: Paul Moore
Headers show
Series [v2] selinux: various sparse fixes | expand

Commit Message

Paul Moore Jan. 27, 2022, 6:21 p.m. UTC
When running the SELinux code through sparse, there are a handful of
warnings.  This patch resolves some of these warnings caused by
"__rcu" mismatches.

 % make W=1 C=1 security/selinux/

Signed-off-by: Paul Moore <paul@paul-moore.com>
---
 security/selinux/hooks.c   |    6 +++---
 security/selinux/ibpkey.c  |    2 +-
 security/selinux/netnode.c |    5 +++--
 security/selinux/netport.c |    2 +-
 4 files changed, 8 insertions(+), 7 deletions(-)

Comments

Ondrej Mosnacek Jan. 27, 2022, 7:02 p.m. UTC | #1
On Thu, Jan 27, 2022 at 7:22 PM Paul Moore <paul@paul-moore.com> wrote:
> When running the SELinux code through sparse, there are a handful of
> warnings.  This patch resolves some of these warnings caused by
> "__rcu" mismatches.
>
>  % make W=1 C=1 security/selinux/
>
> Signed-off-by: Paul Moore <paul@paul-moore.com>
> ---
>  security/selinux/hooks.c   |    6 +++---
>  security/selinux/ibpkey.c  |    2 +-
>  security/selinux/netnode.c |    5 +++--
>  security/selinux/netport.c |    2 +-
>  4 files changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 221e642025f5..0e857f86f5a7 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2534,7 +2534,7 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
>         if (rc) {
>                 clear_itimer();
>
> -               spin_lock_irq(&current->sighand->siglock);
> +               spin_lock_irq(unrcu_pointer(&current->sighand->siglock));
>                 if (!fatal_signal_pending(current)) {
>                         flush_sigqueue(&current->pending);
>                         flush_sigqueue(&current->signal->shared_pending);
> @@ -2542,13 +2542,13 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
>                         sigemptyset(&current->blocked);
>                         recalc_sigpending();
>                 }
> -               spin_unlock_irq(&current->sighand->siglock);
> +               spin_unlock_irq(unrcu_pointer(&current->sighand->siglock));

Shouldn't this be:

spin_[un]lock_irq(&unrcu_pointer(current->sighand)->siglock);
Paul Moore Jan. 27, 2022, 8:03 p.m. UTC | #2
On Thu, Jan 27, 2022 at 2:03 PM Ondrej Mosnacek <omosnace@redhat.com> wrote:
>
> On Thu, Jan 27, 2022 at 7:22 PM Paul Moore <paul@paul-moore.com> wrote:
> > When running the SELinux code through sparse, there are a handful of
> > warnings.  This patch resolves some of these warnings caused by
> > "__rcu" mismatches.
> >
> >  % make W=1 C=1 security/selinux/
> >
> > Signed-off-by: Paul Moore <paul@paul-moore.com>
> > ---
> >  security/selinux/hooks.c   |    6 +++---
> >  security/selinux/ibpkey.c  |    2 +-
> >  security/selinux/netnode.c |    5 +++--
> >  security/selinux/netport.c |    2 +-
> >  4 files changed, 8 insertions(+), 7 deletions(-)
> >
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index 221e642025f5..0e857f86f5a7 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -2534,7 +2534,7 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
> >         if (rc) {
> >                 clear_itimer();
> >
> > -               spin_lock_irq(&current->sighand->siglock);
> > +               spin_lock_irq(unrcu_pointer(&current->sighand->siglock));
> >                 if (!fatal_signal_pending(current)) {
> >                         flush_sigqueue(&current->pending);
> >                         flush_sigqueue(&current->signal->shared_pending);
> > @@ -2542,13 +2542,13 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
> >                         sigemptyset(&current->blocked);
> >                         recalc_sigpending();
> >                 }
> > -               spin_unlock_irq(&current->sighand->siglock);
> > +               spin_unlock_irq(unrcu_pointer(&current->sighand->siglock));
>
> Shouldn't this be:
>
> spin_[un]lock_irq(&unrcu_pointer(current->sighand)->siglock);

Maybe.

The __rcu space annotation is definitely on task_struct::sighand, but
my (quick) look at unrcu_pointer() was that the the de-rcu'ification
applies to all of the dereferencing that is passed as the macro
argument.  Because of that I decided to pass the entire dereferencing
chain to the unrcu_pointer() macro just in case.  If that way of
thinking is incorrect please let me know, otherwise I would rather
just leave it as it is in v2.
Ondrej Mosnacek Jan. 28, 2022, 2:34 p.m. UTC | #3
On Thu, Jan 27, 2022 at 9:04 PM Paul Moore <paul@paul-moore.com> wrote:
> On Thu, Jan 27, 2022 at 2:03 PM Ondrej Mosnacek <omosnace@redhat.com> wrote:
> >
> > On Thu, Jan 27, 2022 at 7:22 PM Paul Moore <paul@paul-moore.com> wrote:
> > > When running the SELinux code through sparse, there are a handful of
> > > warnings.  This patch resolves some of these warnings caused by
> > > "__rcu" mismatches.
> > >
> > >  % make W=1 C=1 security/selinux/
> > >
> > > Signed-off-by: Paul Moore <paul@paul-moore.com>
> > > ---
> > >  security/selinux/hooks.c   |    6 +++---
> > >  security/selinux/ibpkey.c  |    2 +-
> > >  security/selinux/netnode.c |    5 +++--
> > >  security/selinux/netport.c |    2 +-
> > >  4 files changed, 8 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > > index 221e642025f5..0e857f86f5a7 100644
> > > --- a/security/selinux/hooks.c
> > > +++ b/security/selinux/hooks.c
> > > @@ -2534,7 +2534,7 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
> > >         if (rc) {
> > >                 clear_itimer();
> > >
> > > -               spin_lock_irq(&current->sighand->siglock);
> > > +               spin_lock_irq(unrcu_pointer(&current->sighand->siglock));
> > >                 if (!fatal_signal_pending(current)) {
> > >                         flush_sigqueue(&current->pending);
> > >                         flush_sigqueue(&current->signal->shared_pending);
> > > @@ -2542,13 +2542,13 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
> > >                         sigemptyset(&current->blocked);
> > >                         recalc_sigpending();
> > >                 }
> > > -               spin_unlock_irq(&current->sighand->siglock);
> > > +               spin_unlock_irq(unrcu_pointer(&current->sighand->siglock));
> >
> > Shouldn't this be:
> >
> > spin_[un]lock_irq(&unrcu_pointer(current->sighand)->siglock);
>
> Maybe.
>
> The __rcu space annotation is definitely on task_struct::sighand, but
> my (quick) look at unrcu_pointer() was that the the de-rcu'ification
> applies to all of the dereferencing that is passed as the macro
> argument.  Because of that I decided to pass the entire dereferencing
> chain to the unrcu_pointer() macro just in case.  If that way of
> thinking is incorrect please let me know, otherwise I would rather
> just leave it as it is in v2.

While it does work this way, too, it just doesn't feel right. IMHO
it's more self-documenting to mark the exact pointer for which we are
applying the RCU access exception.

--
Ondrej Mosnacek
Software Engineer, Linux Security - SELinux kernel
Red Hat, Inc.
Paul Moore Jan. 28, 2022, 6:13 p.m. UTC | #4
On Fri, Jan 28, 2022 at 9:35 AM Ondrej Mosnacek <omosnace@redhat.com> wrote:
>
> On Thu, Jan 27, 2022 at 9:04 PM Paul Moore <paul@paul-moore.com> wrote:
> > On Thu, Jan 27, 2022 at 2:03 PM Ondrej Mosnacek <omosnace@redhat.com> wrote:
> > >
> > > On Thu, Jan 27, 2022 at 7:22 PM Paul Moore <paul@paul-moore.com> wrote:
> > > > When running the SELinux code through sparse, there are a handful of
> > > > warnings.  This patch resolves some of these warnings caused by
> > > > "__rcu" mismatches.
> > > >
> > > >  % make W=1 C=1 security/selinux/
> > > >
> > > > Signed-off-by: Paul Moore <paul@paul-moore.com>
> > > > ---
> > > >  security/selinux/hooks.c   |    6 +++---
> > > >  security/selinux/ibpkey.c  |    2 +-
> > > >  security/selinux/netnode.c |    5 +++--
> > > >  security/selinux/netport.c |    2 +-
> > > >  4 files changed, 8 insertions(+), 7 deletions(-)
> > > >
> > > > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > > > index 221e642025f5..0e857f86f5a7 100644
> > > > --- a/security/selinux/hooks.c
> > > > +++ b/security/selinux/hooks.c
> > > > @@ -2534,7 +2534,7 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
> > > >         if (rc) {
> > > >                 clear_itimer();
> > > >
> > > > -               spin_lock_irq(&current->sighand->siglock);
> > > > +               spin_lock_irq(unrcu_pointer(&current->sighand->siglock));
> > > >                 if (!fatal_signal_pending(current)) {
> > > >                         flush_sigqueue(&current->pending);
> > > >                         flush_sigqueue(&current->signal->shared_pending);
> > > > @@ -2542,13 +2542,13 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
> > > >                         sigemptyset(&current->blocked);
> > > >                         recalc_sigpending();
> > > >                 }
> > > > -               spin_unlock_irq(&current->sighand->siglock);
> > > > +               spin_unlock_irq(unrcu_pointer(&current->sighand->siglock));
> > >
> > > Shouldn't this be:
> > >
> > > spin_[un]lock_irq(&unrcu_pointer(current->sighand)->siglock);
> >
> > Maybe.
> >
> > The __rcu space annotation is definitely on task_struct::sighand, but
> > my (quick) look at unrcu_pointer() was that the the de-rcu'ification
> > applies to all of the dereferencing that is passed as the macro
> > argument.  Because of that I decided to pass the entire dereferencing
> > chain to the unrcu_pointer() macro just in case.  If that way of
> > thinking is incorrect please let me know, otherwise I would rather
> > just leave it as it is in v2.
>
> While it does work this way, too, it just doesn't feel right. IMHO
> it's more self-documenting to mark the exact pointer for which we are
> applying the RCU access exception.

FWIW, the documentation aspect here is the "__rcu" marking on the
pointer in the task_struct, and possibly the sparse warnings.  What we
are doing here is basically a hack to tell sparse to be quiet, and
since these core kernel variable annotations are likely to come and go
independent of the SELinux code I'm not overly worried about minor
self-documenting issues such as this (they are going to go out-of-date
anyway).  I'm more concerned with keeping a clean {sparse} build.
Paul Moore Feb. 2, 2022, 12:17 a.m. UTC | #5
On Fri, Jan 28, 2022 at 1:13 PM Paul Moore <paul@paul-moore.com> wrote:
> On Fri, Jan 28, 2022 at 9:35 AM Ondrej Mosnacek <omosnace@redhat.com> wrote:
> > On Thu, Jan 27, 2022 at 9:04 PM Paul Moore <paul@paul-moore.com> wrote:
> > > On Thu, Jan 27, 2022 at 2:03 PM Ondrej Mosnacek <omosnace@redhat.com> wrote:
> > > >
> > > > On Thu, Jan 27, 2022 at 7:22 PM Paul Moore <paul@paul-moore.com> wrote:
> > > > > When running the SELinux code through sparse, there are a handful of
> > > > > warnings.  This patch resolves some of these warnings caused by
> > > > > "__rcu" mismatches.
> > > > >
> > > > >  % make W=1 C=1 security/selinux/
> > > > >
> > > > > Signed-off-by: Paul Moore <paul@paul-moore.com>
> > > > > ---
> > > > >  security/selinux/hooks.c   |    6 +++---
> > > > >  security/selinux/ibpkey.c  |    2 +-
> > > > >  security/selinux/netnode.c |    5 +++--
> > > > >  security/selinux/netport.c |    2 +-
> > > > >  4 files changed, 8 insertions(+), 7 deletions(-)
> > > > >
> > > > > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > > > > index 221e642025f5..0e857f86f5a7 100644
> > > > > --- a/security/selinux/hooks.c
> > > > > +++ b/security/selinux/hooks.c
> > > > > @@ -2534,7 +2534,7 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
> > > > >         if (rc) {
> > > > >                 clear_itimer();
> > > > >
> > > > > -               spin_lock_irq(&current->sighand->siglock);
> > > > > +               spin_lock_irq(unrcu_pointer(&current->sighand->siglock));
> > > > >                 if (!fatal_signal_pending(current)) {
> > > > >                         flush_sigqueue(&current->pending);
> > > > >                         flush_sigqueue(&current->signal->shared_pending);
> > > > > @@ -2542,13 +2542,13 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
> > > > >                         sigemptyset(&current->blocked);
> > > > >                         recalc_sigpending();
> > > > >                 }
> > > > > -               spin_unlock_irq(&current->sighand->siglock);
> > > > > +               spin_unlock_irq(unrcu_pointer(&current->sighand->siglock));
> > > >
> > > > Shouldn't this be:
> > > >
> > > > spin_[un]lock_irq(&unrcu_pointer(current->sighand)->siglock);
> > >
> > > Maybe.
> > >
> > > The __rcu space annotation is definitely on task_struct::sighand, but
> > > my (quick) look at unrcu_pointer() was that the the de-rcu'ification
> > > applies to all of the dereferencing that is passed as the macro
> > > argument.  Because of that I decided to pass the entire dereferencing
> > > chain to the unrcu_pointer() macro just in case.  If that way of
> > > thinking is incorrect please let me know, otherwise I would rather
> > > just leave it as it is in v2.
> >
> > While it does work this way, too, it just doesn't feel right. IMHO
> > it's more self-documenting to mark the exact pointer for which we are
> > applying the RCU access exception.
>
> FWIW, the documentation aspect here is the "__rcu" marking on the
> pointer in the task_struct, and possibly the sparse warnings.  What we
> are doing here is basically a hack to tell sparse to be quiet, and
> since these core kernel variable annotations are likely to come and go
> independent of the SELinux code I'm not overly worried about minor
> self-documenting issues such as this (they are going to go out-of-date
> anyway).  I'm more concerned with keeping a clean {sparse} build.

Merged into selinux/next, and ultimately I changed my mind and decided
to change the current::sighand lines as Ondrej suggested.
diff mbox series

Patch

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 221e642025f5..0e857f86f5a7 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2534,7 +2534,7 @@  static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
 	if (rc) {
 		clear_itimer();
 
-		spin_lock_irq(&current->sighand->siglock);
+		spin_lock_irq(unrcu_pointer(&current->sighand->siglock));
 		if (!fatal_signal_pending(current)) {
 			flush_sigqueue(&current->pending);
 			flush_sigqueue(&current->signal->shared_pending);
@@ -2542,13 +2542,13 @@  static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
 			sigemptyset(&current->blocked);
 			recalc_sigpending();
 		}
-		spin_unlock_irq(&current->sighand->siglock);
+		spin_unlock_irq(unrcu_pointer(&current->sighand->siglock));
 	}
 
 	/* Wake up the parent if it is waiting so that it can recheck
 	 * wait permission to the new task SID. */
 	read_lock(&tasklist_lock);
-	__wake_up_parent(current, current->real_parent);
+	__wake_up_parent(current, unrcu_pointer(current->real_parent));
 	read_unlock(&tasklist_lock);
 }
 
diff --git a/security/selinux/ibpkey.c b/security/selinux/ibpkey.c
index 20b3b2243820..5839ca7bb9c7 100644
--- a/security/selinux/ibpkey.c
+++ b/security/selinux/ibpkey.c
@@ -104,7 +104,7 @@  static void sel_ib_pkey_insert(struct sel_ib_pkey *pkey)
 
 		tail = list_entry(
 			rcu_dereference_protected(
-				sel_ib_pkey_hash[idx].list.prev,
+				list_tail_rcu(&sel_ib_pkey_hash[idx].list),
 				lockdep_is_held(&sel_ib_pkey_lock)),
 			struct sel_ib_pkey, list);
 		list_del_rcu(&tail->list);
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index 889552db0d31..0ac7df9a9367 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -164,8 +164,9 @@  static void sel_netnode_insert(struct sel_netnode *node)
 	if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) {
 		struct sel_netnode *tail;
 		tail = list_entry(
-			rcu_dereference_protected(sel_netnode_hash[idx].list.prev,
-						  lockdep_is_held(&sel_netnode_lock)),
+			rcu_dereference_protected(
+				list_tail_rcu(&sel_netnode_hash[idx].list),
+				lockdep_is_held(&sel_netnode_lock)),
 			struct sel_netnode, list);
 		list_del_rcu(&tail->list);
 		kfree_rcu(tail, rcu);
diff --git a/security/selinux/netport.c b/security/selinux/netport.c
index 9ba09d11c0f5..8eec6347cf01 100644
--- a/security/selinux/netport.c
+++ b/security/selinux/netport.c
@@ -113,7 +113,7 @@  static void sel_netport_insert(struct sel_netport *port)
 		struct sel_netport *tail;
 		tail = list_entry(
 			rcu_dereference_protected(
-				sel_netport_hash[idx].list.prev,
+				list_tail_rcu(&sel_netport_hash[idx].list),
 				lockdep_is_held(&sel_netport_lock)),
 			struct sel_netport, list);
 		list_del_rcu(&tail->list);