summaryrefslogtreecommitdiff
path: root/include/internal/protect.h
blob: e159e9fee9dd7fc99fdc81f685e11943e4049269 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#pragma once

#include <rte_mbuf.h>
#include <rte_mempool.h>
#include <rte_spinlock.h>

/* 全局asan开关 */
extern unsigned int g_in_protect_mode;

/* asan_poison和asan_unpoison非线程安全,
 * 设置一个全局锁,保证不会同时执行asan_posion和asan_unpoison操作 */
extern rte_spinlock_t g_in_protect_lock;

/* TODO: 这些定义应通过包含GCC的头文件来实现,不应通过这种方式 */
#if defined(__SANITIZE_ADDRESS__)
void __asan_poison_memory_region(void const volatile * addr, size_t size);
void __asan_unpoison_memory_region(void const volatile * addr, size_t size);
#endif

#if defined(__SANITIZE_ADDRESS__)
#define MR_ASAN_POISON_MEMORY_REGION(addr, size)                                                                       \
    do                                                                                                                 \
    {                                                                                                                  \
        if (g_in_protect_mode)                                                                                         \
        {                                                                                                              \
            rte_spinlock_lock(&g_in_protect_lock);                                                                     \
            __asan_poison_memory_region((addr), (size));                                                               \
            rte_spinlock_unlock(&g_in_protect_lock);                                                                   \
        }                                                                                                              \
    } while (0)

#define MR_ASAN_UNPOISON_MEMORY_REGION(addr, size)                                                                     \
    do                                                                                                                 \
    {                                                                                                                  \
        if (g_in_protect_mode)                                                                                         \
        {                                                                                                              \
            rte_spinlock_lock(&g_in_protect_lock);                                                                     \
            __asan_unpoison_memory_region((addr), (size));                                                             \
            rte_spinlock_unlock(&g_in_protect_lock);                                                                   \
        }                                                                                                              \
    } while (0)

#else
#define MR_ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
#define MR_ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
#endif

static inline void PROTECT_rte_mempool_unpoison(struct rte_mempool * pool)
{
    MR_ASAN_UNPOISON_MEMORY_REGION(pool, sizeof(struct rte_mempool));
    MR_ASAN_UNPOISON_MEMORY_REGION(pool, RTE_MEMPOOL_HEADER_SIZE(pool, pool->cache_size));
}

static inline void PROTECT_rte_mbuf_unpoison_meta(struct rte_mbuf * mbuf)
{
    MR_ASAN_UNPOISON_MEMORY_REGION(mbuf, sizeof(struct rte_mbuf));
    MR_ASAN_UNPOISON_MEMORY_REGION((const char *)mbuf + sizeof(struct rte_mbuf), mbuf->priv_size);
}

static inline void PROTECT_rte_mbuf_poison_meta(struct rte_mbuf * mbuf)
{
    MR_ASAN_POISON_MEMORY_REGION((const char *)mbuf + sizeof(struct rte_mbuf), mbuf->priv_size);
    MR_ASAN_POISON_MEMORY_REGION(mbuf, sizeof(struct rte_mbuf));
}

static inline void PROTECT_rte_mbuf_poison_buff(struct rte_mbuf * mbuf)
{
    MR_ASAN_POISON_MEMORY_REGION(mbuf->buf_addr, mbuf->buf_len);
}

static inline void PROTECT_rte_mbuf_unpoison_buff(struct rte_mbuf * mbuf)
{
    MR_ASAN_UNPOISON_MEMORY_REGION(mbuf->buf_addr, mbuf->buf_len);
}

static inline void PROTECT_rte_mbuf_poison(struct rte_mbuf * mbuf)
{
    PROTECT_rte_mbuf_poison_buff(mbuf);
    PROTECT_rte_mbuf_poison_meta(mbuf);
}

static inline void PROTECT_rte_mbuf_unpoison(struct rte_mbuf * mbuf)
{
    PROTECT_rte_mbuf_unpoison_meta(mbuf);
    PROTECT_rte_mbuf_unpoison_buff(mbuf);
}

static inline void PROTECT_rte_mbuf_poison_bulk(struct rte_mbuf * mbufs[], int nr_mbufs)
{
    for (unsigned int i = 0; i < nr_mbufs; i++)
        PROTECT_rte_mbuf_poison(mbufs[i]);
}

static inline void PROTECT_rte_mbuf_unpoison_bulk(struct rte_mbuf * mbufs[], int nr_mbufs)
{
    for (unsigned int i = 0; i < nr_mbufs; i++)
        PROTECT_rte_mbuf_unpoison(mbufs[i]);
}

static inline void PROTECT_rte_mbuf_unpoison_data(struct rte_mbuf * mbuf)
{
    /* Poison all buff area, because some area may be unpoison before. */
    PROTECT_rte_mbuf_poison_buff(mbuf);

    /* Unpoison the area we need to access */
    const char * data_ptr = rte_pktmbuf_mtod(mbuf, const char *);
    size_t data_len = rte_pktmbuf_data_len(mbuf);
    MR_ASAN_UNPOISON_MEMORY_REGION(data_ptr, data_len);
}

/* 从DPDK17.05中移植rte_pktmbuf_alloc
 * 该函数在申请mbuf的同时还要修改mbuf中的元数据,此时由于还没有拿到mbuf的指针,
 * 也就无法去保护,函数功能无法实现。现移植,在拿到mbuf的指针后立即去保护,继续后面的初始化流程 */
static inline struct rte_mbuf * __PROTECT_PORT_rte_mbuf_raw_alloc(struct rte_mempool * mp)
{
    struct rte_mbuf * m;
    void * mb = NULL;

    if (rte_mempool_get(mp, &mb) < 0)
        return NULL;

    m = (struct rte_mbuf *)mb;
    PROTECT_rte_mbuf_unpoison_meta(m);
    MBUF_RAW_ALLOC_CHECK(m);
    return m;
}

static inline struct rte_mbuf * __PROTECT_PORT_rte_pktmbuf_alloc(struct rte_mempool * mp)
{
    struct rte_mbuf * m;
    if ((m = __PROTECT_PORT_rte_mbuf_raw_alloc(mp)) != NULL)
        rte_pktmbuf_reset(m);
    return m;
}

/* 移植完毕,以后DPDK版本升级时,要格外注意以上的实现是否发生了变化 */

static inline struct rte_mbuf * PROTECT_rte_pktmbuf_alloc(struct rte_mempool * mp)
{
#ifndef __SANITIZE_ADDRESS__
    return rte_pktmbuf_alloc(mp);
#else
    struct rte_mbuf * m = __PROTECT_PORT_rte_pktmbuf_alloc(mp);
    PROTECT_rte_mbuf_poison_meta(m);
    return m;
#endif
}

#if 0
static inline void PROTECT_rte_pktmbuf_free(struct rte_mbuf * mbuf)
{
    PROTECT_rte_mbuf_unpoison_meta(mbuf);
    rte_pktmbuf_free(mbuf);
    /* TODO: 应重新对释放的mbuf区域进行保护,需要在释放前计算mbuf的指针,长度,再执行保护 */
}

static inline int PROTECT_rte_pktmbuf_alloc_bulk(struct rte_mempool * pool, struct rte_mbuf ** mbufs, unsigned count)
{
#ifndef __SANITIZE_ADDRESS__
    return rte_pktmbuf_alloc_bulk(pool, mbufs, count);
#else

    unsigned int alloc_count;
    for (alloc_count = 0; alloc_count < count; alloc_count++)
    {
        struct rte_mbuf * m = PROTECT_rte_pktmbuf_alloc(pool);
        if (unlikely(m == NULL))
            goto errout;
        mbufs[alloc_count] = m;
    }

    return 0;

errout:
    for (unsigned i = 0; i < alloc_count; i++)
    {
        PROTECT_rte_pktmbuf_free(mbufs[i]);
        mbufs[i] = NULL;
    }

    return -1;
#endif
}
#endif

static inline char * PROTECT_rte_pktmbuf_append(struct rte_mbuf * m, uint16_t len)
{
    PROTECT_rte_mbuf_unpoison_meta(m);
    char * ret = rte_pktmbuf_append(m, len);
    PROTECT_rte_mbuf_unpoison_data(m);
    return ret;
}

static inline char * PROTECT_rte_pktmbuf_prepend(struct rte_mbuf * m, uint16_t len)
{
    PROTECT_rte_mbuf_unpoison_meta(m);
    char * ret = rte_pktmbuf_prepend(m, len);
    PROTECT_rte_mbuf_unpoison_data(m);
    return ret;
}

static inline char * PROTECT_rte_pktmbuf_adj(struct rte_mbuf * m, uint16_t len)
{
    PROTECT_rte_mbuf_unpoison_meta(m);
    char * ret = rte_pktmbuf_adj(m, len);
    PROTECT_rte_mbuf_unpoison_data(m);
    return ret;
}

static inline int PROTECT_rte_pktmbuf_trim(struct rte_mbuf * m, uint16_t len)
{
    PROTECT_rte_mbuf_unpoison_meta(m);
    int ret = rte_pktmbuf_trim(m, len);
    return ret;
}

static inline uint16_t PROTECT_rte_pktmbuf_data_len(struct rte_mbuf * m)
{
    PROTECT_rte_mbuf_unpoison_meta(m);
    uint16_t ret = rte_pktmbuf_data_len(m);
    return ret;
}

static inline uint32_t PROTECT_rte_pktmbuf_pkt_len(struct rte_mbuf * m)
{
    PROTECT_rte_mbuf_unpoison_meta(m);
    uint32_t ret = rte_pktmbuf_pkt_len(m);
    return ret;
}

static inline uint16_t PROTECT_rte_mbuf_refcnt_update(struct rte_mbuf * m, int16_t value)
{
    PROTECT_rte_mbuf_unpoison_meta(m);
    uint16_t ret = rte_mbuf_refcnt_update(m, value);
    return ret;
}

static inline uint16_t PROTECT_rte_mbuf_refcnt_read(const struct rte_mbuf * m)
{
    PROTECT_rte_mbuf_unpoison_meta((struct rte_mbuf *)m);
    uint16_t ret = rte_mbuf_refcnt_read(m);
    return ret;
}