• I
    kernel.h: handle pointers to arrays better in container_of() · c7acec71
    Ian Abbott 提交于
    If the first parameter of container_of() is a pointer to a
    non-const-qualified array type (and the third parameter names a
    non-const-qualified array member), the local variable __mptr will be
    defined with a const-qualified array type.  In ISO C, these types are
    incompatible.  They work as expected in GNU C, but some versions will
    issue warnings.  For example, GCC 4.9 produces the warning
    "initialization from incompatible pointer type".
    
    Here is an example of where the problem occurs:
    
    -------------------------------------------------------
       #include <linux/kernel.h>
       #include <linux/module.h>
    
      MODULE_LICENSE("GPL");
    
      struct st {
      	int a;
      	char b[16];
      };
    
      static int __init example_init(void) {
      	struct st t = { .a = 101, .b = "hello" };
      	char (*p)[16] = &t.b;
      	struct st *x = container_of(p, struct st, b);
      	printk(KERN_DEBUG "%p %p\n", (void *)&t, (void *)x);
      	return 0;
      }
    
      static void __exit example_exit(void) {
      }
    
      module_init(example_init);
      module_exit(example_exit);
    -------------------------------------------------------
    
    Building the module with gcc-4.9 results in these warnings (where '{m}'
    is the module source and '{k}' is the kernel source):
    
    -------------------------------------------------------
      In file included from {m}/example.c:1:0:
      {m}/example.c: In function `example_init':
      {k}/include/linux/kernel.h:854:48: warning: initialization from incompatible pointer type
        const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                      ^
      {m}/example.c:14:17: note: in expansion of macro `container_of'
        struct st *x = container_of(p, struct st, b);
                       ^
      {k}/include/linux/kernel.h:854:48: warning: (near initialization for `x')
        const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                      ^
      {m}/example.c:14:17: note: in expansion of macro `container_of'
        struct st *x = container_of(p, struct st, b);
                       ^
    -------------------------------------------------------
    
    Replace the type checking performed by the macro to avoid these
    warnings.  Make sure `*(ptr)` either has type compatible with the
    member, or has type compatible with `void`, ignoring qualifiers.  Raise
    compiler errors if this is not true.  This is stronger than the previous
    behaviour, which only resulted in compiler warnings for a type mismatch.
    
    [arnd@arndb.de: fix new warnings for container_of()]
      Link: http://lkml.kernel.org/r/20170620200940.90557-1-arnd@arndb.de
    Link: http://lkml.kernel.org/r/20170525120316.24473-7-abbotti@mev.co.ukSigned-off-by: NIan Abbott <abbotti@mev.co.uk>
    Signed-off-by: NArnd Bergmann <arnd@arndb.de>
    Acked-by: NMichal Nazarewicz <mina86@mina86.com>
    Acked-by: NKees Cook <keescook@chromium.org>
    Cc: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com>
    Cc: Borislav Petkov <bp@suse.de>
    Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
    Cc: Johannes Berg <johannes.berg@intel.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Alexander Potapenko <glider@google.com>
    Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
    c7acec71
kernel.h 29.2 KB