All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] libselinux: add lock callbacks
@ 2021-07-09 19:08 Seth Moore
  2021-07-12  7:29 ` Nicolas Iooss
  0 siblings, 1 reply; 3+ messages in thread
From: Seth Moore @ 2021-07-09 19:08 UTC (permalink / raw)
  To: selinux; +Cc: Seth Moore

The old mechanism to initialize AVC, avc_init(3), is deprected. This
leaves libselinux with no way of guarding the AVC cache when accessed
from multiple threads. When applications call access check APIs from
multiple threads, the AVC cache may become corrupted.

This change adds new callback functions to selinux_set_callback(3).
These new callbacks all correspond to the functions that used to be
passed via avc_init(3). Multi-threaded applications may set these
callbacks to guard the AVC cache against simultaneous access by
multiple threads.

This change adds the following callbacks:
  - SELINUX_CB_ALLOC_LOCK
      is invoked to allocate new locks
  - SELINUX_CB_GET_LOCK
      is invoked to acquire a lock
  - SELINUX_CB_RELEASE_LOCK
      is invoked to release a previously-acquired lock
  - SELINUX_CB_FREE_LOCK
      is invoked to free a previosly-allocated lock

Signed-off-by: Seth Moore <sethmo@google.com>
---
 libselinux/include/selinux/selinux.h       | 12 ++++++
 libselinux/man/man3/selinux_set_callback.3 | 46 ++++++++++++++++++++++
 libselinux/src/avc_internal.h              | 22 +++++++++--
 libselinux/src/callbacks.c                 | 13 ++++++
 4 files changed, 90 insertions(+), 3 deletions(-)

diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h
index ae98a92e..c3c68b3a 100644
--- a/libselinux/include/selinux/selinux.h
+++ b/libselinux/include/selinux/selinux.h
@@ -166,6 +166,14 @@ __attribute__ ((format(printf, 2, 3)))
 	int (*func_setenforce) (int enforcing);
 	/* netlink callback for policyload message */
 	int (*func_policyload) (int seqno);
+	/* create a lock and return an opaque pointer to it */
+	void *(*func_alloc_lock) (void);
+	/* obtain a given lock, blocking if necessary */
+	void (*func_get_lock) (void *lock);
+	/* release a given lock */
+	void (*func_release_lock) (void *lock);
+	/* destroy a given lock */
+	void (*func_free_lock) (void *lock);
 };
 
 #define SELINUX_CB_LOG		0
@@ -173,6 +181,10 @@ __attribute__ ((format(printf, 2, 3)))
 #define SELINUX_CB_VALIDATE	2
 #define SELINUX_CB_SETENFORCE	3
 #define SELINUX_CB_POLICYLOAD	4
+#define SELINUX_CB_ALLOC_LOCK   5
+#define SELINUX_CB_GET_LOCK     6
+#define SELINUX_CB_RELEASE_LOCK 7
+#define SELINUX_CB_FREE_LOCK    8
 
 extern union selinux_callback selinux_get_callback(int type);
 extern void selinux_set_callback(int type, union selinux_callback cb);
diff --git a/libselinux/man/man3/selinux_set_callback.3 b/libselinux/man/man3/selinux_set_callback.3
index 75f49b06..f7371504 100644
--- a/libselinux/man/man3/selinux_set_callback.3
+++ b/libselinux/man/man3/selinux_set_callback.3
@@ -116,6 +116,52 @@ The
 .I seqno
 argument is the current sequential number of the policy generation in the system.
 .
+.TP
+.B SELINUX_CB_ALLOC_LOCK
+.BI "void *(*" alloc_lock ") ();"
+
+This callback is used to allocate a fresh lock for protecting critical sections.
+Applications that call selinux library functions from multiple threads must either
+perform their own locking or set each of the following:
+
+.B SELINUX_CB_ALLOC_LOCK
+
+.B SELINUX_CB_GET_LOCK
+
+.B SELINUX_CB_RELEASE_LOCK
+
+.B SELINUX_CB_FREE_LOCK
+
+.TP
+.B SELINUX_CB_GET_LOCK
+.BI "void (*" get_lock ") (void *" lock ");"
+
+This callback acquires the
+.I lock
+that was previously allocated with
+.I alloc_lock.
+This function must block until the
+.I lock
+can be acquired.
+.
+.TP
+.B SELINUX_CB_RELEASE_LOCK
+.BI "void (*" release_lock ") (void *" lock ");"
+
+This callback releases the
+.I lock
+that was previously acquired with
+.I get_lock.
+.
+.TP
+.B SELINUX_CB_FREE_LOCK
+.BI "void (*" free_lock ") (void *" lock ");"
+
+This callback frees the
+.I lock
+that was previously allocated with
+.I alloc_lock.
+.
 .SH "RETURN VALUE"
 None.
 .
diff --git a/libselinux/src/avc_internal.h b/libselinux/src/avc_internal.h
index a9a4aa0b..f23690a1 100644
--- a/libselinux/src/avc_internal.h
+++ b/libselinux/src/avc_internal.h
@@ -9,6 +9,7 @@
 #ifndef _SELINUX_AVC_INTERNAL_H_
 #define _SELINUX_AVC_INTERNAL_H_
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -112,26 +113,41 @@ static inline void avc_stop_thread(void *thread)
 		avc_func_stop_thread(thread);
 }
 
+#define CHECK_LOCK_CALLBACKS() \
+    if (avc_func_alloc_lock \
+            || avc_func_get_lock \
+            || avc_func_release_lock \
+            || avc_func_free_lock) { \
+        assert(avc_func_alloc_lock \
+                && avc_func_get_lock \
+                && avc_func_release_lock \
+                && avc_func_free_lock); \
+    }
+
 static inline void *avc_alloc_lock(void)
 {
+	CHECK_LOCK_CALLBACKS();
 	return avc_func_alloc_lock ? avc_func_alloc_lock() : NULL;
 }
 
 static inline void avc_get_lock(void *lock)
 {
-	if (avc_func_get_lock)
+	CHECK_LOCK_CALLBACKS();
+	if (avc_func_get_lock && lock)
 		avc_func_get_lock(lock);
 }
 
 static inline void avc_release_lock(void *lock)
 {
-	if (avc_func_release_lock)
+	CHECK_LOCK_CALLBACKS();
+	if (avc_func_release_lock && lock)
 		avc_func_release_lock(lock);
 }
 
 static inline void avc_free_lock(void *lock)
 {
-	if (avc_func_free_lock)
+	CHECK_LOCK_CALLBACKS();
+	if (avc_func_free_lock && lock)
 		avc_func_free_lock(lock);
 }
 
diff --git a/libselinux/src/callbacks.c b/libselinux/src/callbacks.c
index c18ccc54..b635c8d8 100644
--- a/libselinux/src/callbacks.c
+++ b/libselinux/src/callbacks.c
@@ -9,6 +9,7 @@
 #include <errno.h>
 #include <selinux/selinux.h>
 #include "callbacks.h"
+#include "avc_internal.h"
 
 /* default implementations */
 static int __attribute__ ((format(printf, 2, 3)))
@@ -95,6 +96,18 @@ selinux_set_callback(int type, union selinux_callback cb)
 	case SELINUX_CB_POLICYLOAD:
 		selinux_netlink_policyload = cb.func_policyload;
 		break;
+	case SELINUX_CB_ALLOC_LOCK:
+		avc_func_alloc_lock = cb.func_alloc_lock;
+		break;
+	case SELINUX_CB_GET_LOCK:
+		avc_func_get_lock = cb.func_get_lock;
+		break;
+	case SELINUX_CB_RELEASE_LOCK:
+		avc_func_release_lock = cb.func_release_lock;
+		break;
+	case SELINUX_CB_FREE_LOCK:
+		avc_func_free_lock = cb.func_free_lock;
+		break;
 	}
 }
 
-- 
2.32.0.93.g670b81a890-goog


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] libselinux: add lock callbacks
  2021-07-09 19:08 [PATCH] libselinux: add lock callbacks Seth Moore
@ 2021-07-12  7:29 ` Nicolas Iooss
  2021-07-12 15:25   ` Seth Moore
  0 siblings, 1 reply; 3+ messages in thread
From: Nicolas Iooss @ 2021-07-12  7:29 UTC (permalink / raw)
  To: Seth Moore; +Cc: SElinux list

On Fri, Jul 9, 2021 at 9:08 PM Seth Moore <sethmo@google.com> wrote:
>
> The old mechanism to initialize AVC, avc_init(3), is deprected. This
> leaves libselinux with no way of guarding the AVC cache when accessed
> from multiple threads. When applications call access check APIs from
> multiple threads, the AVC cache may become corrupted.
>
> This change adds new callback functions to selinux_set_callback(3).
> These new callbacks all correspond to the functions that used to be
> passed via avc_init(3). Multi-threaded applications may set these
> callbacks to guard the AVC cache against simultaneous access by
> multiple threads.
>
> This change adds the following callbacks:
>   - SELINUX_CB_ALLOC_LOCK
>       is invoked to allocate new locks
>   - SELINUX_CB_GET_LOCK
>       is invoked to acquire a lock
>   - SELINUX_CB_RELEASE_LOCK
>       is invoked to release a previously-acquired lock
>   - SELINUX_CB_FREE_LOCK
>       is invoked to free a previosly-allocated lock
>
> Signed-off-by: Seth Moore <sethmo@google.com>

Hello,

I am not very familiar with libselinux's callback, but this patch
looks good to me and it implements the solution which was discussed
previously (https://lore.kernel.org/selinux/CAEjxPJ4A7KC=+0vTKNU_Z0K-e9Q6hSfTc5WiNms54EN_C5dCLA@mail.gmail.com/).

Nevertheless there is a slight issue with the CHECK_LOCK_CALLBACKS
macro: calling "CHECK_LOCK_CALLBACKS();" will expand to "if
(...){...};", with an unnecessary semicolon which is reported by clang
as -Wextra-semi-stmt (for example in
https://github.com/fishilico/selinux/runs/3035178820?check_suite_focus=true).
While I like this check, it seems better if CHECK_LOCK_CALLBACKS was a
function (which would be static inline). Could you please send a
version 2 with this macro replaced by a function? (or I may be wrong,
in which case please explain why using a macro is better than an
inline function).

Thanks,
Nicolas

> ---
>  libselinux/include/selinux/selinux.h       | 12 ++++++
>  libselinux/man/man3/selinux_set_callback.3 | 46 ++++++++++++++++++++++
>  libselinux/src/avc_internal.h              | 22 +++++++++--
>  libselinux/src/callbacks.c                 | 13 ++++++
>  4 files changed, 90 insertions(+), 3 deletions(-)
>
> diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h
> index ae98a92e..c3c68b3a 100644
> --- a/libselinux/include/selinux/selinux.h
> +++ b/libselinux/include/selinux/selinux.h
> @@ -166,6 +166,14 @@ __attribute__ ((format(printf, 2, 3)))
>         int (*func_setenforce) (int enforcing);
>         /* netlink callback for policyload message */
>         int (*func_policyload) (int seqno);
> +       /* create a lock and return an opaque pointer to it */
> +       void *(*func_alloc_lock) (void);
> +       /* obtain a given lock, blocking if necessary */
> +       void (*func_get_lock) (void *lock);
> +       /* release a given lock */
> +       void (*func_release_lock) (void *lock);
> +       /* destroy a given lock */
> +       void (*func_free_lock) (void *lock);
>  };
>
>  #define SELINUX_CB_LOG         0
> @@ -173,6 +181,10 @@ __attribute__ ((format(printf, 2, 3)))
>  #define SELINUX_CB_VALIDATE    2
>  #define SELINUX_CB_SETENFORCE  3
>  #define SELINUX_CB_POLICYLOAD  4
> +#define SELINUX_CB_ALLOC_LOCK   5
> +#define SELINUX_CB_GET_LOCK     6
> +#define SELINUX_CB_RELEASE_LOCK 7
> +#define SELINUX_CB_FREE_LOCK    8
>
>  extern union selinux_callback selinux_get_callback(int type);
>  extern void selinux_set_callback(int type, union selinux_callback cb);
> diff --git a/libselinux/man/man3/selinux_set_callback.3 b/libselinux/man/man3/selinux_set_callback.3
> index 75f49b06..f7371504 100644
> --- a/libselinux/man/man3/selinux_set_callback.3
> +++ b/libselinux/man/man3/selinux_set_callback.3
> @@ -116,6 +116,52 @@ The
>  .I seqno
>  argument is the current sequential number of the policy generation in the system.
>  .
> +.TP
> +.B SELINUX_CB_ALLOC_LOCK
> +.BI "void *(*" alloc_lock ") ();"
> +
> +This callback is used to allocate a fresh lock for protecting critical sections.
> +Applications that call selinux library functions from multiple threads must either
> +perform their own locking or set each of the following:
> +
> +.B SELINUX_CB_ALLOC_LOCK
> +
> +.B SELINUX_CB_GET_LOCK
> +
> +.B SELINUX_CB_RELEASE_LOCK
> +
> +.B SELINUX_CB_FREE_LOCK
> +
> +.TP
> +.B SELINUX_CB_GET_LOCK
> +.BI "void (*" get_lock ") (void *" lock ");"
> +
> +This callback acquires the
> +.I lock
> +that was previously allocated with
> +.I alloc_lock.
> +This function must block until the
> +.I lock
> +can be acquired.
> +.
> +.TP
> +.B SELINUX_CB_RELEASE_LOCK
> +.BI "void (*" release_lock ") (void *" lock ");"
> +
> +This callback releases the
> +.I lock
> +that was previously acquired with
> +.I get_lock.
> +.
> +.TP
> +.B SELINUX_CB_FREE_LOCK
> +.BI "void (*" free_lock ") (void *" lock ");"
> +
> +This callback frees the
> +.I lock
> +that was previously allocated with
> +.I alloc_lock.
> +.
>  .SH "RETURN VALUE"
>  None.
>  .
> diff --git a/libselinux/src/avc_internal.h b/libselinux/src/avc_internal.h
> index a9a4aa0b..f23690a1 100644
> --- a/libselinux/src/avc_internal.h
> +++ b/libselinux/src/avc_internal.h
> @@ -9,6 +9,7 @@
>  #ifndef _SELINUX_AVC_INTERNAL_H_
>  #define _SELINUX_AVC_INTERNAL_H_
>
> +#include <assert.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
> @@ -112,26 +113,41 @@ static inline void avc_stop_thread(void *thread)
>                 avc_func_stop_thread(thread);
>  }
>
> +#define CHECK_LOCK_CALLBACKS() \
> +    if (avc_func_alloc_lock \
> +            || avc_func_get_lock \
> +            || avc_func_release_lock \
> +            || avc_func_free_lock) { \
> +        assert(avc_func_alloc_lock \
> +                && avc_func_get_lock \
> +                && avc_func_release_lock \
> +                && avc_func_free_lock); \
> +    }
> +
>  static inline void *avc_alloc_lock(void)
>  {
> +       CHECK_LOCK_CALLBACKS();
>         return avc_func_alloc_lock ? avc_func_alloc_lock() : NULL;
>  }
>
>  static inline void avc_get_lock(void *lock)
>  {
> -       if (avc_func_get_lock)
> +       CHECK_LOCK_CALLBACKS();
> +       if (avc_func_get_lock && lock)
>                 avc_func_get_lock(lock);
>  }
>
>  static inline void avc_release_lock(void *lock)
>  {
> -       if (avc_func_release_lock)
> +       CHECK_LOCK_CALLBACKS();
> +       if (avc_func_release_lock && lock)
>                 avc_func_release_lock(lock);
>  }
>
>  static inline void avc_free_lock(void *lock)
>  {
> -       if (avc_func_free_lock)
> +       CHECK_LOCK_CALLBACKS();
> +       if (avc_func_free_lock && lock)
>                 avc_func_free_lock(lock);
>  }
>
> diff --git a/libselinux/src/callbacks.c b/libselinux/src/callbacks.c
> index c18ccc54..b635c8d8 100644
> --- a/libselinux/src/callbacks.c
> +++ b/libselinux/src/callbacks.c
> @@ -9,6 +9,7 @@
>  #include <errno.h>
>  #include <selinux/selinux.h>
>  #include "callbacks.h"
> +#include "avc_internal.h"
>
>  /* default implementations */
>  static int __attribute__ ((format(printf, 2, 3)))
> @@ -95,6 +96,18 @@ selinux_set_callback(int type, union selinux_callback cb)
>         case SELINUX_CB_POLICYLOAD:
>                 selinux_netlink_policyload = cb.func_policyload;
>                 break;
> +       case SELINUX_CB_ALLOC_LOCK:
> +               avc_func_alloc_lock = cb.func_alloc_lock;
> +               break;
> +       case SELINUX_CB_GET_LOCK:
> +               avc_func_get_lock = cb.func_get_lock;
> +               break;
> +       case SELINUX_CB_RELEASE_LOCK:
> +               avc_func_release_lock = cb.func_release_lock;
> +               break;
> +       case SELINUX_CB_FREE_LOCK:
> +               avc_func_free_lock = cb.func_free_lock;
> +               break;
>         }
>  }
>
> --
> 2.32.0.93.g670b81a890-goog
>


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] libselinux: add lock callbacks
  2021-07-12  7:29 ` Nicolas Iooss
@ 2021-07-12 15:25   ` Seth Moore
  0 siblings, 0 replies; 3+ messages in thread
From: Seth Moore @ 2021-07-12 15:25 UTC (permalink / raw)
  To: Nicolas Iooss; +Cc: SElinux list

On Mon, Jul 12, 2021 at 12:29 AM Nicolas Iooss <nicolas.iooss@m4x.org> wrote:
>
> On Fri, Jul 9, 2021 at 9:08 PM Seth Moore <sethmo@google.com> wrote:
> >
> > The old mechanism to initialize AVC, avc_init(3), is deprected. This
> > leaves libselinux with no way of guarding the AVC cache when accessed
> > from multiple threads. When applications call access check APIs from
> > multiple threads, the AVC cache may become corrupted.
> >
> > This change adds new callback functions to selinux_set_callback(3).
> > These new callbacks all correspond to the functions that used to be
> > passed via avc_init(3). Multi-threaded applications may set these
> > callbacks to guard the AVC cache against simultaneous access by
> > multiple threads.
> >
> > This change adds the following callbacks:
> >   - SELINUX_CB_ALLOC_LOCK
> >       is invoked to allocate new locks
> >   - SELINUX_CB_GET_LOCK
> >       is invoked to acquire a lock
> >   - SELINUX_CB_RELEASE_LOCK
> >       is invoked to release a previously-acquired lock
> >   - SELINUX_CB_FREE_LOCK
> >       is invoked to free a previosly-allocated lock
> >
> > Signed-off-by: Seth Moore <sethmo@google.com>
>
> Hello,
>
> I am not very familiar with libselinux's callback, but this patch
> looks good to me and it implements the solution which was discussed
> previously (https://lore.kernel.org/selinux/CAEjxPJ4A7KC=+0vTKNU_Z0K-e9Q6hSfTc5WiNms54EN_C5dCLA@mail.gmail.com/).
>
> Nevertheless there is a slight issue with the CHECK_LOCK_CALLBACKS
> macro: calling "CHECK_LOCK_CALLBACKS();" will expand to "if
> (...){...};", with an unnecessary semicolon which is reported by clang
> as -Wextra-semi-stmt (for example in
> https://github.com/fishilico/selinux/runs/3035178820?check_suite_focus=true).
> While I like this check, it seems better if CHECK_LOCK_CALLBACKS was a
> function (which would be static inline). Could you please send a
> version 2 with this macro replaced by a function? (or I may be wrong,
> in which case please explain why using a macro is better than an
> inline function).

Thanks for looking.

I debated making this a function, but in the end liked the idea of the
assert being inside the calling function body. However, the call stack
should have that info anyway, so... in hindsight perhaps I was
overthinking it.

I'll rework and submit a new patch that just calls a function. (Which
I generally prefer to a macro anyhow).

Cheers,
Seth

>
> Thanks,
> Nicolas
>
> > ---
> >  libselinux/include/selinux/selinux.h       | 12 ++++++
> >  libselinux/man/man3/selinux_set_callback.3 | 46 ++++++++++++++++++++++
> >  libselinux/src/avc_internal.h              | 22 +++++++++--
> >  libselinux/src/callbacks.c                 | 13 ++++++
> >  4 files changed, 90 insertions(+), 3 deletions(-)
> >
> > diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h
> > index ae98a92e..c3c68b3a 100644
> > --- a/libselinux/include/selinux/selinux.h
> > +++ b/libselinux/include/selinux/selinux.h
> > @@ -166,6 +166,14 @@ __attribute__ ((format(printf, 2, 3)))
> >         int (*func_setenforce) (int enforcing);
> >         /* netlink callback for policyload message */
> >         int (*func_policyload) (int seqno);
> > +       /* create a lock and return an opaque pointer to it */
> > +       void *(*func_alloc_lock) (void);
> > +       /* obtain a given lock, blocking if necessary */
> > +       void (*func_get_lock) (void *lock);
> > +       /* release a given lock */
> > +       void (*func_release_lock) (void *lock);
> > +       /* destroy a given lock */
> > +       void (*func_free_lock) (void *lock);
> >  };
> >
> >  #define SELINUX_CB_LOG         0
> > @@ -173,6 +181,10 @@ __attribute__ ((format(printf, 2, 3)))
> >  #define SELINUX_CB_VALIDATE    2
> >  #define SELINUX_CB_SETENFORCE  3
> >  #define SELINUX_CB_POLICYLOAD  4
> > +#define SELINUX_CB_ALLOC_LOCK   5
> > +#define SELINUX_CB_GET_LOCK     6
> > +#define SELINUX_CB_RELEASE_LOCK 7
> > +#define SELINUX_CB_FREE_LOCK    8
> >
> >  extern union selinux_callback selinux_get_callback(int type);
> >  extern void selinux_set_callback(int type, union selinux_callback cb);
> > diff --git a/libselinux/man/man3/selinux_set_callback.3 b/libselinux/man/man3/selinux_set_callback.3
> > index 75f49b06..f7371504 100644
> > --- a/libselinux/man/man3/selinux_set_callback.3
> > +++ b/libselinux/man/man3/selinux_set_callback.3
> > @@ -116,6 +116,52 @@ The
> >  .I seqno
> >  argument is the current sequential number of the policy generation in the system.
> >  .
> > +.TP
> > +.B SELINUX_CB_ALLOC_LOCK
> > +.BI "void *(*" alloc_lock ") ();"
> > +
> > +This callback is used to allocate a fresh lock for protecting critical sections.
> > +Applications that call selinux library functions from multiple threads must either
> > +perform their own locking or set each of the following:
> > +
> > +.B SELINUX_CB_ALLOC_LOCK
> > +
> > +.B SELINUX_CB_GET_LOCK
> > +
> > +.B SELINUX_CB_RELEASE_LOCK
> > +
> > +.B SELINUX_CB_FREE_LOCK
> > +
> > +.TP
> > +.B SELINUX_CB_GET_LOCK
> > +.BI "void (*" get_lock ") (void *" lock ");"
> > +
> > +This callback acquires the
> > +.I lock
> > +that was previously allocated with
> > +.I alloc_lock.
> > +This function must block until the
> > +.I lock
> > +can be acquired.
> > +.
> > +.TP
> > +.B SELINUX_CB_RELEASE_LOCK
> > +.BI "void (*" release_lock ") (void *" lock ");"
> > +
> > +This callback releases the
> > +.I lock
> > +that was previously acquired with
> > +.I get_lock.
> > +.
> > +.TP
> > +.B SELINUX_CB_FREE_LOCK
> > +.BI "void (*" free_lock ") (void *" lock ");"
> > +
> > +This callback frees the
> > +.I lock
> > +that was previously allocated with
> > +.I alloc_lock.
> > +.
> >  .SH "RETURN VALUE"
> >  None.
> >  .
> > diff --git a/libselinux/src/avc_internal.h b/libselinux/src/avc_internal.h
> > index a9a4aa0b..f23690a1 100644
> > --- a/libselinux/src/avc_internal.h
> > +++ b/libselinux/src/avc_internal.h
> > @@ -9,6 +9,7 @@
> >  #ifndef _SELINUX_AVC_INTERNAL_H_
> >  #define _SELINUX_AVC_INTERNAL_H_
> >
> > +#include <assert.h>
> >  #include <stdio.h>
> >  #include <stdlib.h>
> >  #include <string.h>
> > @@ -112,26 +113,41 @@ static inline void avc_stop_thread(void *thread)
> >                 avc_func_stop_thread(thread);
> >  }
> >
> > +#define CHECK_LOCK_CALLBACKS() \
> > +    if (avc_func_alloc_lock \
> > +            || avc_func_get_lock \
> > +            || avc_func_release_lock \
> > +            || avc_func_free_lock) { \
> > +        assert(avc_func_alloc_lock \
> > +                && avc_func_get_lock \
> > +                && avc_func_release_lock \
> > +                && avc_func_free_lock); \
> > +    }
> > +
> >  static inline void *avc_alloc_lock(void)
> >  {
> > +       CHECK_LOCK_CALLBACKS();
> >         return avc_func_alloc_lock ? avc_func_alloc_lock() : NULL;
> >  }
> >
> >  static inline void avc_get_lock(void *lock)
> >  {
> > -       if (avc_func_get_lock)
> > +       CHECK_LOCK_CALLBACKS();
> > +       if (avc_func_get_lock && lock)
> >                 avc_func_get_lock(lock);
> >  }
> >
> >  static inline void avc_release_lock(void *lock)
> >  {
> > -       if (avc_func_release_lock)
> > +       CHECK_LOCK_CALLBACKS();
> > +       if (avc_func_release_lock && lock)
> >                 avc_func_release_lock(lock);
> >  }
> >
> >  static inline void avc_free_lock(void *lock)
> >  {
> > -       if (avc_func_free_lock)
> > +       CHECK_LOCK_CALLBACKS();
> > +       if (avc_func_free_lock && lock)
> >                 avc_func_free_lock(lock);
> >  }
> >
> > diff --git a/libselinux/src/callbacks.c b/libselinux/src/callbacks.c
> > index c18ccc54..b635c8d8 100644
> > --- a/libselinux/src/callbacks.c
> > +++ b/libselinux/src/callbacks.c
> > @@ -9,6 +9,7 @@
> >  #include <errno.h>
> >  #include <selinux/selinux.h>
> >  #include "callbacks.h"
> > +#include "avc_internal.h"
> >
> >  /* default implementations */
> >  static int __attribute__ ((format(printf, 2, 3)))
> > @@ -95,6 +96,18 @@ selinux_set_callback(int type, union selinux_callback cb)
> >         case SELINUX_CB_POLICYLOAD:
> >                 selinux_netlink_policyload = cb.func_policyload;
> >                 break;
> > +       case SELINUX_CB_ALLOC_LOCK:
> > +               avc_func_alloc_lock = cb.func_alloc_lock;
> > +               break;
> > +       case SELINUX_CB_GET_LOCK:
> > +               avc_func_get_lock = cb.func_get_lock;
> > +               break;
> > +       case SELINUX_CB_RELEASE_LOCK:
> > +               avc_func_release_lock = cb.func_release_lock;
> > +               break;
> > +       case SELINUX_CB_FREE_LOCK:
> > +               avc_func_free_lock = cb.func_free_lock;
> > +               break;
> >         }
> >  }
> >
> > --
> > 2.32.0.93.g670b81a890-goog
> >
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-07-12 15:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-09 19:08 [PATCH] libselinux: add lock callbacks Seth Moore
2021-07-12  7:29 ` Nicolas Iooss
2021-07-12 15:25   ` Seth Moore

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.