VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-45893

CVE-2026-45893

Description

In the Linux kernel, the following vulnerability has been resolved:

apparmor: Fix & Optimize table creation from possibly unaligned memory

Source blob may come from userspace and might be unaligned. Try to optize the copying process by avoiding unaligned memory accesses.

- Added Fixes tag - Added "Fix &" to description as this doesn't just optimize but fixes a potential unaligned memory access [jj: remove duplicate word "convert" in comment trigger checkpatch warning]

Affected products

1

Patches

8
6fc367bfd4c8

apparmor: Fix & Optimize table creation from possibly unaligned memory

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitHelge DellerNov 26, 2025Fixed in 7.0via kernel-cna
4 files changed · +20 20
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
47e351dfef60

apparmor: Fix & Optimize table creation from possibly unaligned memory

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitHelge DellerNov 26, 2025Fixed in 6.12.75via kernel-cna
4 files changed · +20 20
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index ae31a8a631fc6a..dfc93631b43d87 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -102,16 +102,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index ae31a8a631fc6a..dfc93631b43d87 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -102,16 +102,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 4f998715d29427..fae26953619a79 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 4f998715d29427..fae26953619a79 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
e027999049c4

apparmor: Fix & Optimize table creation from possibly unaligned memory

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitHelge DellerNov 26, 2025Fixed in 6.18.14via kernel-cna
4 files changed · +20 20
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
226c3b10aab2

apparmor: Fix & Optimize table creation from possibly unaligned memory

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitHelge DellerNov 26, 2025Fixed in 6.19.4via kernel-cna
4 files changed · +20 20
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
e027999049c4

apparmor: Fix & Optimize table creation from possibly unaligned memory

4 files changed · +20 20
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
47e351dfef60

apparmor: Fix & Optimize table creation from possibly unaligned memory

4 files changed · +20 20
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index ae31a8a631fc6a..dfc93631b43d87 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -102,16 +102,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index ae31a8a631fc6a..dfc93631b43d87 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -102,16 +102,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 4f998715d29427..fae26953619a79 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 4f998715d29427..fae26953619a79 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
226c3b10aab2

apparmor: Fix & Optimize table creation from possibly unaligned memory

4 files changed · +20 20
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
6fc367bfd4c8

apparmor: Fix & Optimize table creation from possibly unaligned memory

4 files changed · +20 20
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/include/match.h+7 5 modified
    diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
    index 1fbe82f5021b16..0dde8eda3d1a59 100644
    --- a/security/apparmor/include/match.h
    +++ b/security/apparmor/include/match.h
    @@ -104,16 +104,18 @@ struct aa_dfa {
     	struct table_header *tables[YYTD_ID_TSIZE];
     };
     
    -#define byte_to_byte(X) (X)
    -
     #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)	\
     	do { \
     		typeof(LEN) __i; \
     		TTYPE *__t = (TTYPE *) TABLE; \
     		BTYPE *__b = (BTYPE *) BLOB; \
    -		for (__i = 0; __i < LEN; __i++) { \
    -			__t[__i] = NTOHX(__b[__i]); \
    -		} \
    +		BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \
    +		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
    +			memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \
    +		else /* copy & convert from big-endian */ \
    +			for (__i = 0; __i < LEN; __i++) { \
    +				__t[__i] = NTOHX(&__b[__i]); \
    +			} \
     	} while (0)
     
     static inline size_t table_size(size_t len, size_t el_size)
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    
  • security/apparmor/match.c+3 5 modified
    diff --git a/security/apparmor/match.c b/security/apparmor/match.c
    index 26e82ba879d44c..bbeb3be68572f1 100644
    --- a/security/apparmor/match.c
    +++ b/security/apparmor/match.c
    @@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
     		table->td_flags = th.td_flags;
     		table->td_lolen = th.td_lolen;
     		if (th.td_flags == YYTD_DATA8)
    -			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u8, u8, byte_to_byte);
    +			memcpy(table->td_data, blob, th.td_lolen);
     		else if (th.td_flags == YYTD_DATA16)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u16, __be16, be16_to_cpu);
    +				     u16, __be16, get_unaligned_be16);
     		else if (th.td_flags == YYTD_DATA32)
     			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
    -				     u32, __be32, be32_to_cpu);
    +				     u32, __be32, get_unaligned_be32);
     		else
     			goto fail;
     		/* if table was vmalloced make sure the page tables are synced
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing use of unaligned-safe accessor functions when reading 16-bit and 32-bit big-endian values from a userspace-supplied blob that may not be aligned."

Attack vector

An attacker who can supply a crafted AppArmor policy blob (e.g., via `apparmor_parser` or a similar interface) can provide a DFA table whose data is not aligned to the natural alignment of `u16` or `u32` values. When the kernel unpacks this table, the old code called `be16_to_cpu()` or `be32_to_cpu()` on potentially unaligned pointers, which on some architectures (e.g., ARM, MIPS) causes an unaligned access fault or data corruption. The attacker does not need special privileges beyond the ability to load an AppArmor policy.

Affected code

The vulnerability resides in the `unpack_table()` function in `security/apparmor/match.c` and the `UNPACK_ARRAY` macro in `security/apparmor/include/match.h`. The `unpack_table()` function receives a `blob` pointer that may point to userspace-supplied, unaligned memory and previously passed it directly to byte-order conversion functions (`be16_to_cpu`, `be32_to_cpu`) that require aligned access [patch_id=2661598].

What the fix does

The patch replaces `be16_to_cpu`/`be32_to_cpu` with `get_unaligned_be16`/`get_unaligned_be32` in `match.c`, which safely handle unaligned source pointers [patch_id=2661598]. In `match.h`, the `UNPACK_ARRAY` macro is updated to use `memcpy` on big-endian systems (which is safe for unaligned copies) and to pass the address of each element (`&__b[__i]`) to the `NTOHX` conversion function on little-endian systems, so the conversion function receives a pointer rather than a dereferenced value that would require alignment [patch_id=2661598]. The unused `byte_to_byte` macro is also removed.

Preconditions

  • inputAttacker must be able to supply a crafted AppArmor policy blob (e.g., via apparmor_parser or equivalent interface) that contains DFA table data at an unaligned offset.
  • configThe kernel must be running on an architecture that enforces alignment (e.g., ARM, MIPS) or where unaligned access causes corruption.

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.