C++:__aligned(__alignof__) 导致字符数组数据出现问题?

C++: __aligned(__alignof__) causing problems with char array data?

本文关键字:数据 数组 问题 字符 aligned alignof C++      更新时间:2023-10-16

Tl;dr:我的代码正在访问的字符数组以前指向预期的字符串值,现在在字符串之前有意外的字符。我目前的理论是,这在某种程度上是由字符数组对齐方式的变化引起的,我试图弄清楚我是否正确以及如何修复它。

我正在尝试维护一个用C++编写的 Linux 内核模块。我已经很久没有在C++工作了,所以我有点停留在我目前看到的东西上。

我们在内核 modue 之外有一个单独的实用程序,它讲述了内核密钥环中的密钥。稍后,内核模块会查找该值并将其与预期的键值进行比较。下面是查找方法:

#include <linux/key.h>
#include <keys/user-type.h>
int read_key(char *key_desc, char *expected_key) {
struct key *key;
struct user_key_payload *key_payload;
key = request_key(&key_type_user, key_desc, NULL);
key_payload = rcu_dereference(key->payload.data[0]);
return strncmp(key_payload->data, expected_key, key_payload->datalen));
}

此代码目前适用于我们支持的大多数内核版本。但是最近在一个特定的操作系统中进行了内核升级,现在我的strncmp调用无法找到匹配项。似乎数据以某种方式偏移。就像如果 key_payload->datalen = 16,expected_key = "1234567890123456",那么 key_payload->data = "abcdef1234567890123456"。由于我正在比较前 16 个字符显然不匹配,但如果我从 key_payload->data[6] 开始,则会匹配。到目前为止,key_payload->datalen 仍然是正确的预期字符串长度。它只是在新内核版本上更改的key_payload>数据。

我已经查看了新内核中的一些补丁,我认为可能与问题有关。我发现的一个明显区别是这个。在修补之前,user_key_payload对象如下所示:

struct user_key_payload {
struct rcu_head rcu;        /* RCU destructor */
unsigned short  datalen;    /* length of this data */
char        data[0];    /* actual data */
};

但在它看起来像之后:

struct user_key_payload {
struct rcu_head rcu;        /* RCU destructor */
unsigned short  datalen;    /* length of this data */
char        data[0] __aligned(__alignof__(u64)); /* actual data */
};

我不知道这是否是真正导致我的问题的原因,但这似乎是一个开始寻找的明显地方。我以前从未使用过对齐或对齐的关键字。我读过一些关于对齐的文章,但它的级别比我多年来一直在工作要低得多。有谁知道是否有办法对齐 user_key_payload.data 可能会弄乱关键数据的预期内存地址,以及如何确定我的预期数据实际在哪里?

char data[0]表示紧随结构之后的指针。它在内核中广泛用于指示标头之后的可变长度有效负载。

__aligned(__alignof__(u64))将数据与 8 字节(64 位(边界对齐。这意味着,例如,如果在struct user_key_payload中存储所有字段所需的大小为 10 个字节,则结构将被填充以占用 16 个字节 (2*8(。

因此,如果内核威胁数据 8 字节对齐,但您的模块 - 没有,那么"abcdef"就是您正在读取的填充。

编译模块时,请始终确保包含用于编译内核的相同版本的头文件。