summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-10-01 16:51:16 +0100
committerMark Brown <broonie@kernel.org>2026-10-01 16:51:16 +0100
commita8400804d5ba45c7aec07ebafbdf88305b1a301e (patch)
tree94e97a657a6011966f8d3de354dcaea183e86d45
parent752643d17b6d6a246b8516232a35113b5df8bbfb (diff)
parent760f96b7f54beb8dc6f85d97ac7854fddba86835 (diff)
downloadlinux-next-a8400804d5ba45c7aec07ebafbdf88305b1a301e.tar.gz
linux-next-a8400804d5ba45c7aec07ebafbdf88305b1a301e.zip
Merge branch 'for-next/kspp' of https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git
-rw-r--r--arch/um/include/asm/common.lds.S1
-rw-r--r--drivers/misc/lkdtm/core.c16
-rw-r--r--fs/signalfd.c28
-rw-r--r--include/linux/fortify-string.h2
-rw-r--r--scripts/coccinelle/api/kmalloc_objs.cocci161
-rw-r--r--scripts/gcc-plugins/randomize_layout_plugin.c63
6 files changed, 219 insertions, 52 deletions
diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S
index 6585cb93e6eb..7b0c6f8a9d4f 100644
--- a/arch/um/include/asm/common.lds.S
+++ b/arch/um/include/asm/common.lds.S
@@ -93,6 +93,7 @@
.fini_array : {
__fini_array_start = .;
*(.fini_array)
+ *(.fini_array.*)
__fini_array_end = .;
}
diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c
index ededa32d6744..01bebcb33bd4 100644
--- a/drivers/misc/lkdtm/core.c
+++ b/drivers/misc/lkdtm/core.c
@@ -236,11 +236,11 @@ static ssize_t lkdtm_debugfs_entry(struct file *f,
if (count >= PAGE_SIZE)
return -EINVAL;
- buf = (char *)__get_free_page(GFP_KERNEL);
+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (copy_from_user(buf, user_buf, count)) {
- free_page((unsigned long) buf);
+ kfree(buf);
return -EFAULT;
}
/* NULL-terminate and remove enter */
@@ -248,7 +248,7 @@ static ssize_t lkdtm_debugfs_entry(struct file *f,
strim(buf);
crashtype = find_crashtype(buf);
- free_page((unsigned long)buf);
+ kfree(buf);
if (!crashtype)
return -EINVAL;
@@ -271,7 +271,7 @@ static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
ssize_t out;
char *buf;
- buf = (char *)__get_free_page(GFP_KERNEL);
+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
@@ -290,7 +290,7 @@ static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
out = simple_read_from_buffer(user_buf, count, off,
buf, n);
- free_page((unsigned long) buf);
+ kfree(buf);
return out;
}
@@ -313,11 +313,11 @@ static ssize_t direct_entry(struct file *f, const char __user *user_buf,
if (count < 1)
return -EINVAL;
- buf = (char *)__get_free_page(GFP_KERNEL);
+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (copy_from_user(buf, user_buf, count)) {
- free_page((unsigned long) buf);
+ kfree(buf);
return -EFAULT;
}
/* NULL-terminate and remove enter */
@@ -325,7 +325,7 @@ static ssize_t direct_entry(struct file *f, const char __user *user_buf,
strim(buf);
crashtype = find_crashtype(buf);
- free_page((unsigned long) buf);
+ kfree(buf);
if (!crashtype)
return -EINVAL;
diff --git a/fs/signalfd.c b/fs/signalfd.c
index dff53745e352..22bc0870a824 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -48,17 +48,30 @@ static int signalfd_release(struct inode *inode, struct file *file)
return 0;
}
+static void refine_sigmask(struct signalfd_ctx *ctx, sigset_t *sigmask)
+{
+ struct k_sigaction *k = current->sighand->action;
+ int n;
+
+ *sigmask = ctx->sigmask;
+ for (n = 1; n <= _NSIG; ++n, ++k) {
+ if (k->sa.sa_flags & SA_IMMUTABLE)
+ sigaddset(sigmask, n);
+ }
+}
+
static __poll_t signalfd_poll(struct file *file, poll_table *wait)
{
struct signalfd_ctx *ctx = file->private_data;
__poll_t events = 0;
+ sigset_t sigmask;
poll_wait(file, &current->sighand->signalfd_wqh, wait);
spin_lock_irq(&current->sighand->siglock);
- if (next_signal(&current->pending, &ctx->sigmask) ||
- next_signal(&current->signal->shared_pending,
- &ctx->sigmask))
+ refine_sigmask(ctx, &sigmask);
+ if (next_signal(&current->pending, &sigmask) ||
+ next_signal(&current->signal->shared_pending, &sigmask))
events |= EPOLLIN;
spin_unlock_irq(&current->sighand->siglock);
@@ -155,11 +168,13 @@ static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, kernel_siginfo_t *info
int nonblock)
{
enum pid_type type;
- ssize_t ret;
DECLARE_WAITQUEUE(wait, current);
+ sigset_t sigmask;
+ ssize_t ret;
spin_lock_irq(&current->sighand->siglock);
- ret = dequeue_signal(&ctx->sigmask, info, &type);
+ refine_sigmask(ctx, &sigmask);
+ ret = dequeue_signal(&sigmask, info, &type);
switch (ret) {
case 0:
if (!nonblock)
@@ -174,7 +189,7 @@ static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, kernel_siginfo_t *info
add_wait_queue(&current->sighand->signalfd_wqh, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
- ret = dequeue_signal(&ctx->sigmask, info, &type);
+ ret = dequeue_signal(&sigmask, info, &type);
if (ret != 0)
break;
if (signal_pending(current)) {
@@ -184,6 +199,7 @@ static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, kernel_siginfo_t *info
spin_unlock_irq(&current->sighand->siglock);
schedule();
spin_lock_irq(&current->sighand->siglock);
+ refine_sigmask(ctx, &sigmask);
}
spin_unlock_irq(&current->sighand->siglock);
diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h
index cf841dc71fef..7e7c369e0a6c 100644
--- a/include/linux/fortify-string.h
+++ b/include/linux/fortify-string.h
@@ -458,10 +458,8 @@ __FORTIFY_INLINE bool fortify_memset_chk(__kernel_size_t size,
* __struct_size() vs __member_size() must be captured here to avoid
* evaluating argument side-effects further into the macro layers.
*/
-#ifndef CONFIG_KMSAN
#define memset(p, c, s) __fortify_memset_chk(p, c, s, \
__struct_size(p), __member_size(p))
-#endif
/*
* To make sure the compiler can enforce protection against buffer overflows,
diff --git a/scripts/coccinelle/api/kmalloc_objs.cocci b/scripts/coccinelle/api/kmalloc_objs.cocci
index e9a415b7b6f4..0a98ddf03eca 100644
--- a/scripts/coccinelle/api/kmalloc_objs.cocci
+++ b/scripts/coccinelle/api/kmalloc_objs.cocci
@@ -24,27 +24,57 @@ def alloc_array(name):
print(f"Unknown transform for {name}", file=sys.stderr)
return func
-// This excludes anything that is assigning to or from integral types or
-// string literals. Everything else gets the sizeof() extracted for the
-// kmalloc_obj() type/var argument. sizeof(void *) is also excluded because
-// it will need case-by-case double-checking to make sure the right type is
+// Allocations sized by a byte-sized type (BYTE_TYPES) or a string literal,
+// and allocations assigned to a pointer to a byte-sized type, are byte
+// buffers and are left alone. sizeof(void *) is also excluded because it
+// will need case-by-case double-checking to make sure the right type is
// being assigned.
+//
+// Allocations sized by a multi-byte integral type (MULTIBYTE_TYPES) are
+// converted when they are assigned to a pointer to that same type.
+// Otherwise they are left alone: the target may be a pointer to an array
+// of that type, such as "s16 (*pairs)[2]", for which the converted
+// allocation would have the wrong pointer type. For the same reason,
+// arrays of pointers to integral types sized as sizeof(char *) and the
+// like are left alone. Allocations of other types assigned to a pointer to
+// a multi-byte integral type are left alone too.
+//
+// Everything else gets the sizeof() extracted for the kmalloc_obj()
+// type/var argument.
+//
+// The first matching alternative below wins, so the exclusions must come
+// before the more general conversions.
@direct depends on patch && !(file in "tools") && !(file in "samples")@
typedef u8, u16, u32, u64;
typedef __u8, __u16, __u32, __u64;
typedef uint8_t, uint16_t, uint32_t, uint64_t;
+typedef s8, s16, s32, s64;
+typedef __s8, __s16, __s32, __s64;
+typedef int8_t, int16_t, int32_t, int64_t;
typedef uchar, ushort, uint, ulong;
typedef __le16, __le32, __le64;
typedef __be16, __be32, __be64;
typedef wchar_t;
-type INTEGRAL = {u8,__u8,uint8_t,char,unsigned char,uchar,wchar_t,
- u16,__u16,uint16_t,unsigned short,ushort,
- u32,__u32,uint32_t,unsigned int,uint,
- u64,__u64,uint64_t,unsigned long,ulong,
- __le16,__le32,__le64,__be16,__be32,__be64};
+type BYTE_TYPES = {char,signed char,unsigned char,uchar,
+ u8,__u8,uint8_t,s8,__s8,int8_t};
+type MULTIBYTE_TYPES = {short,short int,signed short,signed short int,
+ unsigned short,unsigned short int,ushort,
+ int,signed,signed int,unsigned,unsigned int,uint,
+ long,long int,signed long,signed long int,
+ unsigned long,unsigned long int,ulong,
+ long long,long long int,
+ signed long long,signed long long int,
+ unsigned long long,unsigned long long int,
+ u16,__u16,uint16_t,s16,__s16,int16_t,
+ u32,__u32,uint32_t,s32,__s32,int32_t,
+ u64,__u64,uint64_t,s64,__s64,int64_t,
+ __le16,__le32,__le64,__be16,__be32,__be64,
+ wchar_t};
char [] STRING;
-INTEGRAL *BYTES;
-INTEGRAL **BYTES_PTRS;
+BYTE_TYPES *BYTES;
+MULTIBYTE_TYPES *MULTIBYTES;
+const MULTIBYTE_TYPES *CONST_MULTIBYTES;
+MULTIBYTE_TYPES MULTIBYTE;
type TYPE;
expression VAR;
expression GFP;
@@ -59,66 +89,133 @@ fresh identifier ALLOC_OBJS = script:python(ALLOC_ARRAY) { alloc_array(ALLOC_ARR
@@
(
+// Convert a single object sized by its target: p = kmalloc(sizeof(*p), gfp)
- VAR = ALLOC((sizeof(*VAR)), GFP)
+ VAR = ALLOC_OBJ(*VAR, GFP)
|
- ALLOC((\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), GFP)
+// Exclude byte buffers and integral pointers: kmalloc(sizeof(u8), gfp),
+// kmalloc(sizeof("str"), gfp), kmalloc(sizeof(char *), gfp)
+ ALLOC((\(sizeof(STRING)\|sizeof(BYTE_TYPES)\|
+ sizeof(BYTE_TYPES *)\|sizeof(MULTIBYTE_TYPES *)\)), GFP)
|
- BYTES = ALLOC((sizeof(E)), GFP)
+// Exclude anything assigned to a byte pointer:
+// u8 *buf = kmalloc(sizeof(*hdr), gfp)
+ BYTES = ALLOC((\(sizeof(E)\|sizeof(TYPE)\)), GFP)
|
- BYTES = ALLOC((sizeof(TYPE)), GFP)
+// Convert a multi-byte type to a pointer to it:
+// u32 *p = kmalloc(sizeof(u32), gfp)
+ \(MULTIBYTES\|CONST_MULTIBYTES\) =
+- ALLOC((sizeof(MULTIBYTE_TYPES)), GFP)
++ ALLOC_OBJ(MULTIBYTE_TYPES, GFP)
|
- BYTES_PTRS = ALLOC((sizeof(E)), GFP)
+// Same by expression: u32 *p = kmalloc(sizeof(p[0]), gfp)
+ \(MULTIBYTES\|CONST_MULTIBYTES\) =
+- ALLOC((sizeof(MULTIBYTE)), GFP)
++ ALLOC_OBJ(MULTIBYTE, GFP)
|
- BYTES_PTRS = ALLOC((sizeof(TYPE)), GFP)
+// Exclude other multi-byte sizes, e.g. to pointers to arrays: s16 (*p)[2] = ...
+ ALLOC((\(sizeof(MULTIBYTE_TYPES)\|sizeof(MULTIBYTE)\)), GFP)
|
+// Exclude anything else assigned to a multi-byte pointer:
+// u32 *p = kmalloc(sizeof(*hdr), gfp)
+ \(MULTIBYTES\|CONST_MULTIBYTES\) = ALLOC((\(sizeof(E)\|sizeof(TYPE)\)), GFP)
+|
+// Exclude void pointers, to be checked by hand: kmalloc(sizeof(void *), gfp)
ALLOC((sizeof(void *)), GFP)
|
+// Convert any other expression: p = kmalloc(sizeof(s->item), gfp)
- ALLOC((sizeof(E)), GFP)
+ ALLOC_OBJ(E, GFP)
|
+// Convert any other type: p = kmalloc(sizeof(struct item), gfp)
- ALLOC((sizeof(TYPE)), GFP)
+ ALLOC_OBJ(TYPE, GFP)
|
- ALLOC_ARRAY(COUNT, (\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), GFP)
-|
- BYTES = ALLOC_ARRAY(COUNT, (sizeof(E)), GFP)
-|
- BYTES = ALLOC_ARRAY(COUNT, (sizeof(TYPE)), GFP)
-|
- BYTES_PTRS = ALLOC_ARRAY(COUNT, (sizeof(E)), GFP)
+// The same, for arrays allocated as (count, size):
+// Exclude byte buffers and integral pointers: kcalloc(n, sizeof(u8), gfp),
+// kcalloc(n, sizeof(char *), gfp)
+ ALLOC_ARRAY(COUNT, (\(sizeof(STRING)\|sizeof(BYTE_TYPES)\|
+ sizeof(BYTE_TYPES *)\|sizeof(MULTIBYTE_TYPES *)\)), GFP)
|
- BYTES_PTRS = ALLOC_ARRAY(COUNT, (sizeof(TYPE)), GFP)
+// Exclude arrays assigned to a byte pointer:
+// u8 *buf = kcalloc(n, sizeof(*hdr), gfp)
+ BYTES = ALLOC_ARRAY(COUNT, (\(sizeof(E)\|sizeof(TYPE)\)), GFP)
|
- ALLOC_ARRAY((\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), COUNT, GFP)
+// Convert a multi-byte array to a pointer to it:
+// u32 *p = kcalloc(n, sizeof(u32), gfp)
+ \(MULTIBYTES\|CONST_MULTIBYTES\) =
+- ALLOC_ARRAY(COUNT, (sizeof(MULTIBYTE_TYPES)), GFP)
++ ALLOC_OBJS(MULTIBYTE_TYPES, COUNT, GFP)
|
- BYTES = ALLOC_ARRAY((sizeof(E)), COUNT, GFP)
+// Same by expression: u32 *p = kcalloc(n, sizeof(*p), gfp)
+ \(MULTIBYTES\|CONST_MULTIBYTES\) =
+- ALLOC_ARRAY(COUNT, (sizeof(MULTIBYTE)), GFP)
++ ALLOC_OBJS(MULTIBYTE, COUNT, GFP)
|
- BYTES = ALLOC_ARRAY((sizeof(TYPE)), COUNT, GFP)
+// Exclude other multi-byte arrays:
+// s16 (*pairs)[2] = kcalloc(n, sizeof(s16), gfp)
+ ALLOC_ARRAY(COUNT, (\(sizeof(MULTIBYTE_TYPES)\|sizeof(MULTIBYTE)\)), GFP)
|
- BYTES_PTRS = ALLOC_ARRAY((sizeof(E)), COUNT, GFP)
-|
- BYTES_PTRS = ALLOC_ARRAY((sizeof(TYPE)), COUNT, GFP)
+// Exclude other arrays assigned to a multi-byte pointer:
+// u32 *p = kcalloc(n, sizeof(*hdr), gfp)
+ \(MULTIBYTES\|CONST_MULTIBYTES\) = ALLOC_ARRAY(COUNT, (\(sizeof(E)\|sizeof(TYPE)\)), GFP)
|
+// Exclude arrays of void pointers: kcalloc(n, sizeof(void *), gfp)
ALLOC_ARRAY(COUNT, (sizeof(void *)), GFP)
|
- ALLOC_ARRAY((sizeof(void *)), COUNT, GFP)
-|
+// Convert any other expression: p = kcalloc(n, sizeof(*p), gfp)
- ALLOC_ARRAY(COUNT, (sizeof(E)), GFP)
+ ALLOC_OBJS(E, COUNT, GFP)
|
+// Convert any other type: p = kcalloc(n, sizeof(struct item), gfp)
- ALLOC_ARRAY(COUNT, (sizeof(TYPE)), GFP)
+ ALLOC_OBJS(TYPE, COUNT, GFP)
|
+// The same, for arrays allocated as (size, count):
+// Exclude byte buffers and integral pointers: kcalloc(sizeof(u8), n, gfp),
+// kcalloc(sizeof(char *), n, gfp)
+ ALLOC_ARRAY((\(sizeof(STRING)\|sizeof(BYTE_TYPES)\|
+ sizeof(BYTE_TYPES *)\|sizeof(MULTIBYTE_TYPES *)\)), COUNT, GFP)
+|
+// Exclude arrays assigned to a byte pointer:
+// u8 *buf = kcalloc(sizeof(*hdr), n, gfp)
+ BYTES = ALLOC_ARRAY((\(sizeof(E)\|sizeof(TYPE)\)), COUNT, GFP)
+|
+// Convert a multi-byte array to a pointer to it:
+// u32 *p = kcalloc(sizeof(u32), n, gfp)
+ \(MULTIBYTES\|CONST_MULTIBYTES\) =
+- ALLOC_ARRAY((sizeof(MULTIBYTE_TYPES)), COUNT, GFP)
++ ALLOC_OBJS(MULTIBYTE_TYPES, COUNT, GFP)
+|
+// Same by expression: u32 *p = kcalloc(sizeof(*p), n, gfp)
+ \(MULTIBYTES\|CONST_MULTIBYTES\) =
+- ALLOC_ARRAY((sizeof(MULTIBYTE)), COUNT, GFP)
++ ALLOC_OBJS(MULTIBYTE, COUNT, GFP)
+|
+// Exclude other multi-byte arrays:
+// s16 (*pairs)[2] = kcalloc(sizeof(s16), n, gfp)
+ ALLOC_ARRAY((\(sizeof(MULTIBYTE_TYPES)\|sizeof(MULTIBYTE)\)), COUNT, GFP)
+|
+// Exclude other arrays assigned to a multi-byte pointer:
+// u32 *p = kcalloc(sizeof(*hdr), n, gfp)
+ \(MULTIBYTES\|CONST_MULTIBYTES\) = ALLOC_ARRAY((\(sizeof(E)\|sizeof(TYPE)\)), COUNT, GFP)
+|
+// Exclude arrays of void pointers: kcalloc(sizeof(void *), n, gfp)
+ ALLOC_ARRAY((sizeof(void *)), COUNT, GFP)
+|
+// Convert any other expression: p = kcalloc(sizeof(*p), n, gfp)
- ALLOC_ARRAY((sizeof(E)), COUNT, GFP)
+ ALLOC_OBJS(E, COUNT, GFP)
|
+// Convert any other type: p = kcalloc(sizeof(struct item), n, gfp)
- ALLOC_ARRAY((sizeof(TYPE)), COUNT, GFP)
+ ALLOC_OBJS(TYPE, COUNT, GFP)
|
+// Convert flexible array structures: p = kmalloc(struct_size(p, data, n), gfp)
- ALLOC(struct_size(VAR, FLEX, COUNT), GFP)
+ ALLOC_FLEX(*VAR, FLEX, COUNT, GFP)
|
+// Same by type: kmalloc(struct_size_t(struct item, data, n), gfp)
- ALLOC(struct_size_t(TYPE, FLEX, COUNT), GFP)
+ ALLOC_FLEX(TYPE, FLEX, COUNT, GFP)
)
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index ff65a4f87f24..1e66f45fe29b 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -22,7 +22,7 @@
#define ORIG_TYPE_NAME(node) \
(TYPE_NAME(TYPE_MAIN_VARIANT(node)) != NULL_TREE ? ((const unsigned char *)IDENTIFIER_POINTER(TYPE_NAME(TYPE_MAIN_VARIANT(node)))) : (const unsigned char *)"anonymous")
-#define INFORM(loc, msg, ...) inform(loc, "randstruct: " msg, ##__VA_ARGS__)
+#define INFORM(loc, msg, ...) warning_at(loc, 0, "randstruct: " msg, ##__VA_ARGS__)
#define MISMATCH(loc, how, ...) INFORM(loc, "casting between randomized structure pointer types (" how "): %qT and %qT\n", __VA_ARGS__)
__visible int plugin_is_GPL_compatible;
@@ -699,6 +699,63 @@ static void handle_local_var_initializers(void)
}
/*
+ * Does @container reach a field of type @member_type by a chain of
+ * by-value members? That is the relationship container_of() expresses --
+ * its @member argument may be a dotted path, e.g.
+ * container_of(inode, struct ceph_inode_info, netfs.inode) -- so a cast
+ * from @member_type * to @container * is legitimate rather than a
+ * layout-confusing one.
+ *
+ * container_of() used to leave a "void *__mptr" temporary behind, and this
+ * pass recognised such casts by that name. Commit f9e7a7564834
+ * ("container_of: remove local __mptr variable") removed it to stop nested
+ * container_of() shadowing itself, and the cast now folds to a bare SSA
+ * copy when the member sits at offset 0, leaving nothing syntactic to key
+ * on. Match the type relationship instead.
+ *
+ * The depth bound keeps this cheap; container_of() paths are one or two
+ * members deep in practice.
+ */
+#define CONTAINER_OF_MAX_DEPTH 4
+
+static bool is_container_of_cast(const_tree container, const_tree member_type,
+ int depth)
+{
+ const_tree field;
+
+ if (container == NULL_TREE || depth > CONTAINER_OF_MAX_DEPTH)
+ return false;
+
+ if (TREE_CODE(container) != RECORD_TYPE &&
+ TREE_CODE(container) != UNION_TYPE)
+ return false;
+
+ for (field = TYPE_FIELDS(container); field; field = DECL_CHAIN(field)) {
+ const_tree field_type;
+
+ if (TREE_CODE(field) != FIELD_DECL)
+ continue;
+
+ /*
+ * Only a member at offset 0 can reach here: for any other
+ * offset container_of()'s subtraction survives folding, the
+ * cast's rhs stays void *, and the caller skipped it above.
+ */
+ if (!integer_zerop(byte_position(field)))
+ continue;
+
+ field_type = TYPE_MAIN_VARIANT(TREE_TYPE(field));
+ if (field_type == member_type)
+ return true;
+
+ if (is_container_of_cast(field_type, member_type, depth + 1))
+ return true;
+ }
+
+ return false;
+}
+
+/*
* iterate over all statements to find "bad" casts:
* those where the address of the start of a structure is cast
* to a pointer of a structure of a different type, or a
@@ -799,10 +856,8 @@ static unsigned int find_bad_casts_execute(void)
#endif
MISMATCH(gimple_location(stmt), "op0", ptr_lhs_type, op0_type);
} else {
- const_tree ssa_name_var = SSA_NAME_VAR(rhs1);
/* skip bogus type casts introduced by container_of */
- if (ssa_name_var != NULL_TREE && DECL_NAME(ssa_name_var) &&
- !strcmp((const char *)DECL_NAME_POINTER(ssa_name_var), "__mptr"))
+ if (is_container_of_cast(ptr_lhs_type, ptr_rhs_type, 0))
continue;
#ifndef __DEBUG_PLUGIN
if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(ptr_rhs_type)))