diff mbox series

[nft,1/2] utils: add memory_allocation_check() helper

Message ID 20231108182431.4005745-1-thaller@redhat.com
State Changes Requested
Delegated to: Pablo Neira
Headers show
Series [nft,1/2] utils: add memory_allocation_check() helper | expand

Commit Message

Thomas Haller Nov. 8, 2023, 6:24 p.m. UTC
libnftables kills the process on out of memory (xmalloc()), so
when we use libraries that propagate ENOMEM to libnftables, we
also abort the process.

For example:

     nlr = nftnl_rule_alloc();
     if (!nlr)
          memory_allocation_error();

Add memory_allocation_check() macro which can simplify this common
check to:

     nlr = memory_allocation_check(nftnl_rule_alloc());

Signed-off-by: Thomas Haller <thaller@redhat.com>
---
 include/utils.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

Comments

Pablo Neira Ayuso Nov. 9, 2023, 3:24 p.m. UTC | #1
On Wed, Nov 08, 2023 at 07:24:24PM +0100, Thomas Haller wrote:
> libnftables kills the process on out of memory (xmalloc()), so
> when we use libraries that propagate ENOMEM to libnftables, we
> also abort the process.
> 
> For example:
> 
>      nlr = nftnl_rule_alloc();
>      if (!nlr)
>           memory_allocation_error();
> 
> Add memory_allocation_check() macro which can simplify this common
> check to:
> 
>      nlr = memory_allocation_check(nftnl_rule_alloc());
> 
> Signed-off-by: Thomas Haller <thaller@redhat.com>
> ---
>  include/utils.h | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/include/utils.h b/include/utils.h
> index 36a28f893667..fcd7c598fe9f 100644
> --- a/include/utils.h
> +++ b/include/utils.h
> @@ -142,6 +142,16 @@ extern void __memory_allocation_error(const char *filename, uint32_t line) __nor
>  #define memory_allocation_error()		\
>  	__memory_allocation_error(__FILE__, __LINE__);
>  
> +#define memory_allocation_check(cmd)               \
> +	({                                         \
> +		typeof((cmd)) _v = (cmd);          \
> +		const void *const _v2 = _v;        \
> +                                                   \
> +		if (!_v2)                          \

please don't hide a if branch inside a macro.

> +			memory_allocation_error(); \
> +		_v;                                \
> +	})
> +
>  extern void xfree(const void *ptr);
>  extern void *xmalloc(size_t size);
>  extern void *xmalloc_array(size_t nmemb, size_t size);
> -- 
> 2.41.0
>
Thomas Haller Nov. 9, 2023, 5:02 p.m. UTC | #2
On Thu, 2023-11-09 at 16:24 +0100, Pablo Neira Ayuso wrote:
> On Wed, Nov 08, 2023 at 07:24:24PM +0100, Thomas Haller wrote:
> > 
> > +#define memory_allocation_check(cmd)               \
> > +	({                                         \
> > +		typeof((cmd)) _v = (cmd);          \
> > +		const void *const _v2 = _v;        \
> > +                                                   \
> > +		if (!_v2)                          \
> 
> please don't hide a if branch inside a macro.

What is the reason for this rule? Is there a style guide somewhere?

> 
> > +			memory_allocation_error(); \
> > +		_v;                                \
> > +	})



It could be instead:


static inline void *__memory_allocation_check(const char *file, unsigned line, const void *ptr) {
    if (!ptr)
        __memory_allocation_error(file, line);
    return (void*) ptr;
}

#define memory_allocation_check(cmd) \
   ((typeof(cmd) __memory_allocation_check(__FILE__, __LINE__, (cmd))


Doesn't seem to make a difference either way.



Thomas
Florian Westphal Nov. 15, 2023, 8:52 a.m. UTC | #3
Thomas Haller <thaller@redhat.com> wrote:
> static inline void *__memory_allocation_check(const char *file, unsigned line, const void *ptr) {
>     if (!ptr)
>         __memory_allocation_error(file, line);
>     return (void*) ptr;
> }
> 
> #define memory_allocation_check(cmd) \
>    ((typeof(cmd) __memory_allocation_check(__FILE__, __LINE__, (cmd))
> 
> Doesn't seem to make a difference either way.

We seem to be moving in circles.

I suspect your agenda is to avoid repeating the existing

x = alloc()
if (!x)
  barf()

pattern when adding userhandle support?

If so I think its best to just add a specific ubuf alloc wrapper that
can't fail (i.e. like the 'xmalloc' wrappers).

Like Pablo said, I don't see any added value in providing FILE/LINE
errors on stderr here.  It could be as simple as exit().
Thomas Haller Nov. 15, 2023, 9:06 a.m. UTC | #4
On Wed, 2023-11-15 at 09:52 +0100, Florian Westphal wrote:
> Thomas Haller <thaller@redhat.com> wrote:
> > static inline void *__memory_allocation_check(const char *file,
> > unsigned line, const void *ptr) {
> >     if (!ptr)
> >         __memory_allocation_error(file, line);
> >     return (void*) ptr;
> > }
> > 
> > #define memory_allocation_check(cmd) \
> >    ((typeof(cmd) __memory_allocation_check(__FILE__, __LINE__,
> > (cmd))
> > 
> > Doesn't seem to make a difference either way.
> 
> We seem to be moving in circles.
> 
> I suspect your agenda is to avoid repeating the existing
> 
> x = alloc()
> if (!x)
>   barf()
> 
> pattern when adding userhandle support?

exactly.

> 
> If so I think its best to just add a specific ubuf alloc wrapper that
> can't fail (i.e. like the 'xmalloc' wrappers).

I don't understand.

_nftnl_udata_buf_alloc() *is* that specific wrapper.

Maybe the name is bad... and such wrappers should have a "nft_x_"
prefix (nft_x_nftnl_udata_buf_alloc()).

> 
> Like Pablo said, I don't see any added value in providing FILE/LINE
> errors on stderr here.  It could be as simple as exit().
> 

I don't understand.

The two patches don't change anything about that. There is no change in
behavior -- aside introducing a convenience wrapper for the repeated
ENOMEM check.

If you want to change memory_allocation_error() to not use FILE/LINE or
call exit(), then that is a separate discussion (I'd like to avoid).


Thomas
diff mbox series

Patch

diff --git a/include/utils.h b/include/utils.h
index 36a28f893667..fcd7c598fe9f 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -142,6 +142,16 @@  extern void __memory_allocation_error(const char *filename, uint32_t line) __nor
 #define memory_allocation_error()		\
 	__memory_allocation_error(__FILE__, __LINE__);
 
+#define memory_allocation_check(cmd)               \
+	({                                         \
+		typeof((cmd)) _v = (cmd);          \
+		const void *const _v2 = _v;        \
+                                                   \
+		if (!_v2)                          \
+			memory_allocation_error(); \
+		_v;                                \
+	})
+
 extern void xfree(const void *ptr);
 extern void *xmalloc(size_t size);
 extern void *xmalloc_array(size_t nmemb, size_t size);