Tl;dr:我的代码正在访问的字符数组(以前指向预期的字符串值)现在在字符串之前有意想不到的字符。我目前的理论是,这在某种程度上是由char数组的对齐引起的,我试图找出我是否正确,以及如何修复它。
我正在尝试维护一个用C++编写的Linux内核模块。自从我在C++工作已经很长时间了,所以我对我目前所看到的东西有点执着。
我们有一个独立的实用工具之外的内核护城河,故事,一个键,在内核钥匙环。稍后,内核模块将查找该值并将其与预期的键值进行比较。下面是查找方法:
#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调用没有找到匹配的。这些数据似乎在某种程度上被抵消了。就像expected_key = "1234567890123456“那样,那么key_payload->data = "abcdef1234567890123456”。因为我在比较前16个字符,所以显然不匹配,但是如果我从key_payload->data6 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的对齐是否会扰乱关键数据的预期内存地址,以及如何确定预期数据的实际位置?
发布于 2020-02-10 13:00:37
char data[0]指的是结构后面的指针。在内核中,它被广泛用于指示在报头之后出现的可变长度的有效载荷。
__aligned(__alignof__(u64))将数据对齐到8字节(64位)边界.例如,如果在struct user_key_payload中存储所有字段所需的大小为10字节,则结构将被填充以占据16个字节(2*8)。
因此,如果内核威胁数据8字节对齐,但您的模块没有,那么"abcdef“就是您正在读取的填充。
在编译模块时,始终要确保包含用于编译内核的相同版本的头文件。
https://stackoverflow.com/questions/60144867
复制相似问题