diff options
| -rw-r--r-- | include/linux/filter.h | 48 | ||||
| -rw-r--r-- | net/core/filter.c | 212 |
2 files changed, 209 insertions, 51 deletions
diff --git a/include/linux/filter.h b/include/linux/filter.h index 151f5d703b7e..69b43dbea6c6 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h | |||
| @@ -91,6 +91,54 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */ | |||
| 91 | #define BPF_TAX 0x00 | 91 | #define BPF_TAX 0x00 |
| 92 | #define BPF_TXA 0x80 | 92 | #define BPF_TXA 0x80 |
| 93 | 93 | ||
| 94 | enum { | ||
| 95 | BPF_S_RET_K = 0, | ||
| 96 | BPF_S_RET_A, | ||
| 97 | BPF_S_ALU_ADD_K, | ||
| 98 | BPF_S_ALU_ADD_X, | ||
| 99 | BPF_S_ALU_SUB_K, | ||
| 100 | BPF_S_ALU_SUB_X, | ||
| 101 | BPF_S_ALU_MUL_K, | ||
| 102 | BPF_S_ALU_MUL_X, | ||
| 103 | BPF_S_ALU_DIV_X, | ||
| 104 | BPF_S_ALU_AND_K, | ||
| 105 | BPF_S_ALU_AND_X, | ||
| 106 | BPF_S_ALU_OR_K, | ||
| 107 | BPF_S_ALU_OR_X, | ||
| 108 | BPF_S_ALU_LSH_K, | ||
| 109 | BPF_S_ALU_LSH_X, | ||
| 110 | BPF_S_ALU_RSH_K, | ||
| 111 | BPF_S_ALU_RSH_X, | ||
| 112 | BPF_S_ALU_NEG, | ||
| 113 | BPF_S_LD_W_ABS, | ||
| 114 | BPF_S_LD_H_ABS, | ||
| 115 | BPF_S_LD_B_ABS, | ||
| 116 | BPF_S_LD_W_LEN, | ||
| 117 | BPF_S_LD_W_IND, | ||
| 118 | BPF_S_LD_H_IND, | ||
| 119 | BPF_S_LD_B_IND, | ||
| 120 | BPF_S_LD_IMM, | ||
| 121 | BPF_S_LDX_W_LEN, | ||
| 122 | BPF_S_LDX_B_MSH, | ||
| 123 | BPF_S_LDX_IMM, | ||
| 124 | BPF_S_MISC_TAX, | ||
| 125 | BPF_S_MISC_TXA, | ||
| 126 | BPF_S_ALU_DIV_K, | ||
| 127 | BPF_S_LD_MEM, | ||
| 128 | BPF_S_LDX_MEM, | ||
| 129 | BPF_S_ST, | ||
| 130 | BPF_S_STX, | ||
| 131 | BPF_S_JMP_JA, | ||
| 132 | BPF_S_JMP_JEQ_K, | ||
| 133 | BPF_S_JMP_JEQ_X, | ||
| 134 | BPF_S_JMP_JGE_K, | ||
| 135 | BPF_S_JMP_JGE_X, | ||
| 136 | BPF_S_JMP_JGT_K, | ||
| 137 | BPF_S_JMP_JGT_X, | ||
| 138 | BPF_S_JMP_JSET_K, | ||
| 139 | BPF_S_JMP_JSET_X, | ||
| 140 | }; | ||
| 141 | |||
| 94 | #ifndef BPF_MAXINSNS | 142 | #ifndef BPF_MAXINSNS |
| 95 | #define BPF_MAXINSNS 4096 | 143 | #define BPF_MAXINSNS 4096 |
| 96 | #endif | 144 | #endif |
diff --git a/net/core/filter.c b/net/core/filter.c index da69fb728d32..52b051f82a01 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -128,87 +128,87 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int | |||
| 128 | fentry = &filter[pc]; | 128 | fentry = &filter[pc]; |
| 129 | 129 | ||
| 130 | switch (fentry->code) { | 130 | switch (fentry->code) { |
| 131 | case BPF_ALU|BPF_ADD|BPF_X: | 131 | case BPF_S_ALU_ADD_X: |
| 132 | A += X; | 132 | A += X; |
| 133 | continue; | 133 | continue; |
| 134 | case BPF_ALU|BPF_ADD|BPF_K: | 134 | case BPF_S_ALU_ADD_K: |
| 135 | A += fentry->k; | 135 | A += fentry->k; |
| 136 | continue; | 136 | continue; |
| 137 | case BPF_ALU|BPF_SUB|BPF_X: | 137 | case BPF_S_ALU_SUB_X: |
| 138 | A -= X; | 138 | A -= X; |
| 139 | continue; | 139 | continue; |
| 140 | case BPF_ALU|BPF_SUB|BPF_K: | 140 | case BPF_S_ALU_SUB_K: |
| 141 | A -= fentry->k; | 141 | A -= fentry->k; |
| 142 | continue; | 142 | continue; |
| 143 | case BPF_ALU|BPF_MUL|BPF_X: | 143 | case BPF_S_ALU_MUL_X: |
| 144 | A *= X; | 144 | A *= X; |
| 145 | continue; | 145 | continue; |
| 146 | case BPF_ALU|BPF_MUL|BPF_K: | 146 | case BPF_S_ALU_MUL_K: |
| 147 | A *= fentry->k; | 147 | A *= fentry->k; |
| 148 | continue; | 148 | continue; |
| 149 | case BPF_ALU|BPF_DIV|BPF_X: | 149 | case BPF_S_ALU_DIV_X: |
| 150 | if (X == 0) | 150 | if (X == 0) |
| 151 | return 0; | 151 | return 0; |
| 152 | A /= X; | 152 | A /= X; |
| 153 | continue; | 153 | continue; |
| 154 | case BPF_ALU|BPF_DIV|BPF_K: | 154 | case BPF_S_ALU_DIV_K: |
| 155 | A /= fentry->k; | 155 | A /= fentry->k; |
| 156 | continue; | 156 | continue; |
| 157 | case BPF_ALU|BPF_AND|BPF_X: | 157 | case BPF_S_ALU_AND_X: |
| 158 | A &= X; | 158 | A &= X; |
| 159 | continue; | 159 | continue; |
| 160 | case BPF_ALU|BPF_AND|BPF_K: | 160 | case BPF_S_ALU_AND_K: |
| 161 | A &= fentry->k; | 161 | A &= fentry->k; |
| 162 | continue; | 162 | continue; |
| 163 | case BPF_ALU|BPF_OR|BPF_X: | 163 | case BPF_S_ALU_OR_X: |
| 164 | A |= X; | 164 | A |= X; |
| 165 | continue; | 165 | continue; |
| 166 | case BPF_ALU|BPF_OR|BPF_K: | 166 | case BPF_S_ALU_OR_K: |
| 167 | A |= fentry->k; | 167 | A |= fentry->k; |
| 168 | continue; | 168 | continue; |
| 169 | case BPF_ALU|BPF_LSH|BPF_X: | 169 | case BPF_S_ALU_LSH_X: |
| 170 | A <<= X; | 170 | A <<= X; |
| 171 | continue; | 171 | continue; |
| 172 | case BPF_ALU|BPF_LSH|BPF_K: | 172 | case BPF_S_ALU_LSH_K: |
| 173 | A <<= fentry->k; | 173 | A <<= fentry->k; |
| 174 | continue; | 174 | continue; |
| 175 | case BPF_ALU|BPF_RSH|BPF_X: | 175 | case BPF_S_ALU_RSH_X: |
| 176 | A >>= X; | 176 | A >>= X; |
| 177 | continue; | 177 | continue; |
| 178 | case BPF_ALU|BPF_RSH|BPF_K: | 178 | case BPF_S_ALU_RSH_K: |
| 179 | A >>= fentry->k; | 179 | A >>= fentry->k; |
| 180 | continue; | 180 | continue; |
| 181 | case BPF_ALU|BPF_NEG: | 181 | case BPF_S_ALU_NEG: |
| 182 | A = -A; | 182 | A = -A; |
| 183 | continue; | 183 | continue; |
| 184 | case BPF_JMP|BPF_JA: | 184 | case BPF_S_JMP_JA: |
| 185 | pc += fentry->k; | 185 | pc += fentry->k; |
| 186 | continue; | 186 | continue; |
| 187 | case BPF_JMP|BPF_JGT|BPF_K: | 187 | case BPF_S_JMP_JGT_K: |
| 188 | pc += (A > fentry->k) ? fentry->jt : fentry->jf; | 188 | pc += (A > fentry->k) ? fentry->jt : fentry->jf; |
| 189 | continue; | 189 | continue; |
| 190 | case BPF_JMP|BPF_JGE|BPF_K: | 190 | case BPF_S_JMP_JGE_K: |
| 191 | pc += (A >= fentry->k) ? fentry->jt : fentry->jf; | 191 | pc += (A >= fentry->k) ? fentry->jt : fentry->jf; |
| 192 | continue; | 192 | continue; |
| 193 | case BPF_JMP|BPF_JEQ|BPF_K: | 193 | case BPF_S_JMP_JEQ_K: |
| 194 | pc += (A == fentry->k) ? fentry->jt : fentry->jf; | 194 | pc += (A == fentry->k) ? fentry->jt : fentry->jf; |
| 195 | continue; | 195 | continue; |
| 196 | case BPF_JMP|BPF_JSET|BPF_K: | 196 | case BPF_S_JMP_JSET_K: |
| 197 | pc += (A & fentry->k) ? fentry->jt : fentry->jf; | 197 | pc += (A & fentry->k) ? fentry->jt : fentry->jf; |
| 198 | continue; | 198 | continue; |
| 199 | case BPF_JMP|BPF_JGT|BPF_X: | 199 | case BPF_S_JMP_JGT_X: |
| 200 | pc += (A > X) ? fentry->jt : fentry->jf; | 200 | pc += (A > X) ? fentry->jt : fentry->jf; |
| 201 | continue; | 201 | continue; |
| 202 | case BPF_JMP|BPF_JGE|BPF_X: | 202 | case BPF_S_JMP_JGE_X: |
| 203 | pc += (A >= X) ? fentry->jt : fentry->jf; | 203 | pc += (A >= X) ? fentry->jt : fentry->jf; |
| 204 | continue; | 204 | continue; |
| 205 | case BPF_JMP|BPF_JEQ|BPF_X: | 205 | case BPF_S_JMP_JEQ_X: |
| 206 | pc += (A == X) ? fentry->jt : fentry->jf; | 206 | pc += (A == X) ? fentry->jt : fentry->jf; |
| 207 | continue; | 207 | continue; |
| 208 | case BPF_JMP|BPF_JSET|BPF_X: | 208 | case BPF_S_JMP_JSET_X: |
| 209 | pc += (A & X) ? fentry->jt : fentry->jf; | 209 | pc += (A & X) ? fentry->jt : fentry->jf; |
| 210 | continue; | 210 | continue; |
| 211 | case BPF_LD|BPF_W|BPF_ABS: | 211 | case BPF_S_LD_W_ABS: |
| 212 | k = fentry->k; | 212 | k = fentry->k; |
| 213 | load_w: | 213 | load_w: |
| 214 | ptr = load_pointer(skb, k, 4, &tmp); | 214 | ptr = load_pointer(skb, k, 4, &tmp); |
| @@ -217,7 +217,7 @@ load_w: | |||
| 217 | continue; | 217 | continue; |
| 218 | } | 218 | } |
| 219 | break; | 219 | break; |
| 220 | case BPF_LD|BPF_H|BPF_ABS: | 220 | case BPF_S_LD_H_ABS: |
| 221 | k = fentry->k; | 221 | k = fentry->k; |
| 222 | load_h: | 222 | load_h: |
| 223 | ptr = load_pointer(skb, k, 2, &tmp); | 223 | ptr = load_pointer(skb, k, 2, &tmp); |
| @@ -226,7 +226,7 @@ load_h: | |||
| 226 | continue; | 226 | continue; |
| 227 | } | 227 | } |
| 228 | break; | 228 | break; |
| 229 | case BPF_LD|BPF_B|BPF_ABS: | 229 | case BPF_S_LD_B_ABS: |
| 230 | k = fentry->k; | 230 | k = fentry->k; |
| 231 | load_b: | 231 | load_b: |
| 232 | ptr = load_pointer(skb, k, 1, &tmp); | 232 | ptr = load_pointer(skb, k, 1, &tmp); |
| @@ -235,54 +235,54 @@ load_b: | |||
| 235 | continue; | 235 | continue; |
| 236 | } | 236 | } |
| 237 | break; | 237 | break; |
| 238 | case BPF_LD|BPF_W|BPF_LEN: | 238 | case BPF_S_LD_W_LEN: |
| 239 | A = skb->len; | 239 | A = skb->len; |
| 240 | continue; | 240 | continue; |
| 241 | case BPF_LDX|BPF_W|BPF_LEN: | 241 | case BPF_S_LDX_W_LEN: |
| 242 | X = skb->len; | 242 | X = skb->len; |
| 243 | continue; | 243 | continue; |
| 244 | case BPF_LD|BPF_W|BPF_IND: | 244 | case BPF_S_LD_W_IND: |
| 245 | k = X + fentry->k; | 245 | k = X + fentry->k; |
| 246 | goto load_w; | 246 | goto load_w; |
| 247 | case BPF_LD|BPF_H|BPF_IND: | 247 | case BPF_S_LD_H_IND: |
| 248 | k = X + fentry->k; | 248 | k = X + fentry->k; |
| 249 | goto load_h; | 249 | goto load_h; |
| 250 | case BPF_LD|BPF_B|BPF_IND: | 250 | case BPF_S_LD_B_IND: |
| 251 | k = X + fentry->k; | 251 | k = X + fentry->k; |
| 252 | goto load_b; | 252 | goto load_b; |
| 253 | case BPF_LDX|BPF_B|BPF_MSH: | 253 | case BPF_S_LDX_B_MSH: |
| 254 | ptr = load_pointer(skb, fentry->k, 1, &tmp); | 254 | ptr = load_pointer(skb, fentry->k, 1, &tmp); |
| 255 | if (ptr != NULL) { | 255 | if (ptr != NULL) { |
| 256 | X = (*(u8 *)ptr & 0xf) << 2; | 256 | X = (*(u8 *)ptr & 0xf) << 2; |
| 257 | continue; | 257 | continue; |
| 258 | } | 258 | } |
| 259 | return 0; | 259 | return 0; |
| 260 | case BPF_LD|BPF_IMM: | 260 | case BPF_S_LD_IMM: |
| 261 | A = fentry->k; | 261 | A = fentry->k; |
| 262 | continue; | 262 | continue; |
| 263 | case BPF_LDX|BPF_IMM: | 263 | case BPF_S_LDX_IMM: |
| 264 | X = fentry->k; | 264 | X = fentry->k; |
| 265 | continue; | 265 | continue; |
| 266 | case BPF_LD|BPF_MEM: | 266 | case BPF_S_LD_MEM: |
| 267 | A = mem[fentry->k]; | 267 | A = mem[fentry->k]; |
| 268 | continue; | 268 | continue; |
| 269 | case BPF_LDX|BPF_MEM: | 269 | case BPF_S_LDX_MEM: |
| 270 | X = mem[fentry->k]; | 270 | X = mem[fentry->k]; |
| 271 | continue; | 271 | continue; |
| 272 | case BPF_MISC|BPF_TAX: | 272 | case BPF_S_MISC_TAX: |
| 273 | X = A; | 273 | X = A; |
| 274 | continue; | 274 | continue; |
| 275 | case BPF_MISC|BPF_TXA: | 275 | case BPF_S_MISC_TXA: |
| 276 | A = X; | 276 | A = X; |
| 277 | continue; | 277 | continue; |
| 278 | case BPF_RET|BPF_K: | 278 | case BPF_S_RET_K: |
| 279 | return fentry->k; | 279 | return fentry->k; |
| 280 | case BPF_RET|BPF_A: | 280 | case BPF_S_RET_A: |
| 281 | return A; | 281 | return A; |
| 282 | case BPF_ST: | 282 | case BPF_S_ST: |
| 283 | mem[fentry->k] = A; | 283 | mem[fentry->k] = A; |
| 284 | continue; | 284 | continue; |
| 285 | case BPF_STX: | 285 | case BPF_S_STX: |
| 286 | mem[fentry->k] = X; | 286 | mem[fentry->k] = X; |
| 287 | continue; | 287 | continue; |
| 288 | default: | 288 | default: |
| @@ -390,53 +390,128 @@ int sk_chk_filter(struct sock_filter *filter, int flen) | |||
| 390 | /* Only allow valid instructions */ | 390 | /* Only allow valid instructions */ |
| 391 | switch (ftest->code) { | 391 | switch (ftest->code) { |
| 392 | case BPF_ALU|BPF_ADD|BPF_K: | 392 | case BPF_ALU|BPF_ADD|BPF_K: |
| 393 | ftest->code = BPF_S_ALU_ADD_K; | ||
| 394 | break; | ||
| 393 | case BPF_ALU|BPF_ADD|BPF_X: | 395 | case BPF_ALU|BPF_ADD|BPF_X: |
| 396 | ftest->code = BPF_S_ALU_ADD_X; | ||
| 397 | break; | ||
| 394 | case BPF_ALU|BPF_SUB|BPF_K: | 398 | case BPF_ALU|BPF_SUB|BPF_K: |
| 399 | ftest->code = BPF_S_ALU_SUB_K; | ||
| 400 | break; | ||
| 395 | case BPF_ALU|BPF_SUB|BPF_X: | 401 | case BPF_ALU|BPF_SUB|BPF_X: |
| 402 | ftest->code = BPF_S_ALU_SUB_X; | ||
| 403 | break; | ||
| 396 | case BPF_ALU|BPF_MUL|BPF_K: | 404 | case BPF_ALU|BPF_MUL|BPF_K: |
| 405 | ftest->code = BPF_S_ALU_MUL_K; | ||
| 406 | break; | ||
| 397 | case BPF_ALU|BPF_MUL|BPF_X: | 407 | case BPF_ALU|BPF_MUL|BPF_X: |
| 408 | ftest->code = BPF_S_ALU_MUL_X; | ||
| 409 | break; | ||
| 398 | case BPF_ALU|BPF_DIV|BPF_X: | 410 | case BPF_ALU|BPF_DIV|BPF_X: |
| 411 | ftest->code = BPF_S_ALU_DIV_X; | ||
| 412 | break; | ||
| 399 | case BPF_ALU|BPF_AND|BPF_K: | 413 | case BPF_ALU|BPF_AND|BPF_K: |
| 414 | ftest->code = BPF_S_ALU_AND_K; | ||
| 415 | break; | ||
| 400 | case BPF_ALU|BPF_AND|BPF_X: | 416 | case BPF_ALU|BPF_AND|BPF_X: |
| 417 | ftest->code = BPF_S_ALU_AND_X; | ||
| 418 | break; | ||
| 401 | case BPF_ALU|BPF_OR|BPF_K: | 419 | case BPF_ALU|BPF_OR|BPF_K: |
| 420 | ftest->code = BPF_S_ALU_OR_K; | ||
| 421 | break; | ||
| 402 | case BPF_ALU|BPF_OR|BPF_X: | 422 | case BPF_ALU|BPF_OR|BPF_X: |
| 423 | ftest->code = BPF_S_ALU_OR_X; | ||
| 424 | break; | ||
| 403 | case BPF_ALU|BPF_LSH|BPF_K: | 425 | case BPF_ALU|BPF_LSH|BPF_K: |
| 426 | ftest->code = BPF_S_ALU_LSH_K; | ||
| 427 | break; | ||
| 404 | case BPF_ALU|BPF_LSH|BPF_X: | 428 | case BPF_ALU|BPF_LSH|BPF_X: |
| 429 | ftest->code = BPF_S_ALU_LSH_X; | ||
| 430 | break; | ||
| 405 | case BPF_ALU|BPF_RSH|BPF_K: | 431 | case BPF_ALU|BPF_RSH|BPF_K: |
| 432 | ftest->code = BPF_S_ALU_RSH_K; | ||
| 433 | break; | ||
| 406 | case BPF_ALU|BPF_RSH|BPF_X: | 434 | case BPF_ALU|BPF_RSH|BPF_X: |
| 435 | ftest->code = BPF_S_ALU_RSH_X; | ||
| 436 | break; | ||
| 407 | case BPF_ALU|BPF_NEG: | 437 | case BPF_ALU|BPF_NEG: |
| 438 | ftest->code = BPF_S_ALU_NEG; | ||
| 439 | break; | ||
| 408 | case BPF_LD|BPF_W|BPF_ABS: | 440 | case BPF_LD|BPF_W|BPF_ABS: |
| 441 | ftest->code = BPF_S_LD_W_ABS; | ||
| 442 | break; | ||
| 409 | case BPF_LD|BPF_H|BPF_ABS: | 443 | case BPF_LD|BPF_H|BPF_ABS: |
| 444 | ftest->code = BPF_S_LD_H_ABS; | ||
| 445 | break; | ||
| 410 | case BPF_LD|BPF_B|BPF_ABS: | 446 | case BPF_LD|BPF_B|BPF_ABS: |
| 447 | ftest->code = BPF_S_LD_B_ABS; | ||
| 448 | break; | ||
| 411 | case BPF_LD|BPF_W|BPF_LEN: | 449 | case BPF_LD|BPF_W|BPF_LEN: |
| 450 | ftest->code = BPF_S_LD_W_LEN; | ||
| 451 | break; | ||
| 412 | case BPF_LD|BPF_W|BPF_IND: | 452 | case BPF_LD|BPF_W|BPF_IND: |
| 453 | ftest->code = BPF_S_LD_W_IND; | ||
| 454 | break; | ||
| 413 | case BPF_LD|BPF_H|BPF_IND: | 455 | case BPF_LD|BPF_H|BPF_IND: |
| 456 | ftest->code = BPF_S_LD_H_IND; | ||
| 457 | break; | ||
| 414 | case BPF_LD|BPF_B|BPF_IND: | 458 | case BPF_LD|BPF_B|BPF_IND: |
| 459 | ftest->code = BPF_S_LD_B_IND; | ||
| 460 | break; | ||
| 415 | case BPF_LD|BPF_IMM: | 461 | case BPF_LD|BPF_IMM: |
| 462 | ftest->code = BPF_S_LD_IMM; | ||
| 463 | break; | ||
| 416 | case BPF_LDX|BPF_W|BPF_LEN: | 464 | case BPF_LDX|BPF_W|BPF_LEN: |
| 465 | ftest->code = BPF_S_LDX_W_LEN; | ||
| 466 | break; | ||
| 417 | case BPF_LDX|BPF_B|BPF_MSH: | 467 | case BPF_LDX|BPF_B|BPF_MSH: |
| 468 | ftest->code = BPF_S_LDX_B_MSH; | ||
| 469 | break; | ||
| 418 | case BPF_LDX|BPF_IMM: | 470 | case BPF_LDX|BPF_IMM: |
| 471 | ftest->code = BPF_S_LDX_IMM; | ||
| 472 | break; | ||
| 419 | case BPF_MISC|BPF_TAX: | 473 | case BPF_MISC|BPF_TAX: |
| 474 | ftest->code = BPF_S_MISC_TAX; | ||
| 475 | break; | ||
| 420 | case BPF_MISC|BPF_TXA: | 476 | case BPF_MISC|BPF_TXA: |
| 477 | ftest->code = BPF_S_MISC_TXA; | ||
| 478 | break; | ||
| 421 | case BPF_RET|BPF_K: | 479 | case BPF_RET|BPF_K: |
| 480 | ftest->code = BPF_S_RET_K; | ||
| 481 | break; | ||
| 422 | case BPF_RET|BPF_A: | 482 | case BPF_RET|BPF_A: |
| 483 | ftest->code = BPF_S_RET_A; | ||
| 423 | break; | 484 | break; |
| 424 | 485 | ||
| 425 | /* Some instructions need special checks */ | 486 | /* Some instructions need special checks */ |
| 426 | 487 | ||
| 427 | case BPF_ALU|BPF_DIV|BPF_K: | ||
| 428 | /* check for division by zero */ | 488 | /* check for division by zero */ |
| 489 | case BPF_ALU|BPF_DIV|BPF_K: | ||
| 429 | if (ftest->k == 0) | 490 | if (ftest->k == 0) |
| 430 | return -EINVAL; | 491 | return -EINVAL; |
| 492 | ftest->code = BPF_S_ALU_DIV_K; | ||
| 431 | break; | 493 | break; |
| 432 | 494 | ||
| 495 | /* check for invalid memory addresses */ | ||
| 433 | case BPF_LD|BPF_MEM: | 496 | case BPF_LD|BPF_MEM: |
| 497 | if (ftest->k >= BPF_MEMWORDS) | ||
| 498 | return -EINVAL; | ||
| 499 | ftest->code = BPF_S_LD_MEM; | ||
| 500 | break; | ||
| 434 | case BPF_LDX|BPF_MEM: | 501 | case BPF_LDX|BPF_MEM: |
| 502 | if (ftest->k >= BPF_MEMWORDS) | ||
| 503 | return -EINVAL; | ||
| 504 | ftest->code = BPF_S_LDX_MEM; | ||
| 505 | break; | ||
| 435 | case BPF_ST: | 506 | case BPF_ST: |
| 507 | if (ftest->k >= BPF_MEMWORDS) | ||
| 508 | return -EINVAL; | ||
| 509 | ftest->code = BPF_S_ST; | ||
| 510 | break; | ||
| 436 | case BPF_STX: | 511 | case BPF_STX: |
| 437 | /* check for invalid memory addresses */ | ||
| 438 | if (ftest->k >= BPF_MEMWORDS) | 512 | if (ftest->k >= BPF_MEMWORDS) |
| 439 | return -EINVAL; | 513 | return -EINVAL; |
| 514 | ftest->code = BPF_S_STX; | ||
| 440 | break; | 515 | break; |
| 441 | 516 | ||
| 442 | case BPF_JMP|BPF_JA: | 517 | case BPF_JMP|BPF_JA: |
| @@ -447,28 +522,63 @@ int sk_chk_filter(struct sock_filter *filter, int flen) | |||
| 447 | */ | 522 | */ |
| 448 | if (ftest->k >= (unsigned)(flen-pc-1)) | 523 | if (ftest->k >= (unsigned)(flen-pc-1)) |
| 449 | return -EINVAL; | 524 | return -EINVAL; |
| 525 | ftest->code = BPF_S_JMP_JA; | ||
| 450 | break; | 526 | break; |
| 451 | 527 | ||
| 452 | case BPF_JMP|BPF_JEQ|BPF_K: | 528 | case BPF_JMP|BPF_JEQ|BPF_K: |
| 529 | ftest->code = BPF_S_JMP_JEQ_K; | ||
| 530 | break; | ||
| 453 | case BPF_JMP|BPF_JEQ|BPF_X: | 531 | case BPF_JMP|BPF_JEQ|BPF_X: |
| 532 | ftest->code = BPF_S_JMP_JEQ_X; | ||
| 533 | break; | ||
| 454 | case BPF_JMP|BPF_JGE|BPF_K: | 534 | case BPF_JMP|BPF_JGE|BPF_K: |
| 535 | ftest->code = BPF_S_JMP_JGE_K; | ||
| 536 | break; | ||
| 455 | case BPF_JMP|BPF_JGE|BPF_X: | 537 | case BPF_JMP|BPF_JGE|BPF_X: |
| 538 | ftest->code = BPF_S_JMP_JGE_X; | ||
| 539 | break; | ||
| 456 | case BPF_JMP|BPF_JGT|BPF_K: | 540 | case BPF_JMP|BPF_JGT|BPF_K: |
| 541 | ftest->code = BPF_S_JMP_JGT_K; | ||
| 542 | break; | ||
| 457 | case BPF_JMP|BPF_JGT|BPF_X: | 543 | case BPF_JMP|BPF_JGT|BPF_X: |
| 544 | ftest->code = BPF_S_JMP_JGT_X; | ||
| 545 | break; | ||
| 458 | case BPF_JMP|BPF_JSET|BPF_K: | 546 | case BPF_JMP|BPF_JSET|BPF_K: |
| 547 | ftest->code = BPF_S_JMP_JSET_K; | ||
| 548 | break; | ||
| 459 | case BPF_JMP|BPF_JSET|BPF_X: | 549 | case BPF_JMP|BPF_JSET|BPF_X: |
| 550 | ftest->code = BPF_S_JMP_JSET_X; | ||
| 551 | break; | ||
| 552 | |||
| 553 | default: | ||
| 554 | return -EINVAL; | ||
| 555 | } | ||
| 556 | |||
| 460 | /* for conditionals both must be safe */ | 557 | /* for conditionals both must be safe */ |
| 558 | switch (ftest->code) { | ||
| 559 | case BPF_S_JMP_JEQ_K: | ||
| 560 | case BPF_S_JMP_JEQ_X: | ||
| 561 | case BPF_S_JMP_JGE_K: | ||
| 562 | case BPF_S_JMP_JGE_X: | ||
| 563 | case BPF_S_JMP_JGT_K: | ||
| 564 | case BPF_S_JMP_JGT_X: | ||
| 565 | case BPF_S_JMP_JSET_X: | ||
| 566 | case BPF_S_JMP_JSET_K: | ||
| 461 | if (pc + ftest->jt + 1 >= flen || | 567 | if (pc + ftest->jt + 1 >= flen || |
| 462 | pc + ftest->jf + 1 >= flen) | 568 | pc + ftest->jf + 1 >= flen) |
| 463 | return -EINVAL; | 569 | return -EINVAL; |
| 464 | break; | 570 | } |
| 571 | } | ||
| 465 | 572 | ||
| 573 | /* last instruction must be a RET code */ | ||
| 574 | switch (filter[flen - 1].code) { | ||
| 575 | case BPF_S_RET_K: | ||
| 576 | case BPF_S_RET_A: | ||
| 577 | return 0; | ||
| 578 | break; | ||
| 466 | default: | 579 | default: |
| 467 | return -EINVAL; | 580 | return -EINVAL; |
| 468 | } | 581 | } |
| 469 | } | ||
| 470 | |||
| 471 | return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; | ||
| 472 | } | 582 | } |
| 473 | EXPORT_SYMBOL(sk_chk_filter); | 583 | EXPORT_SYMBOL(sk_chk_filter); |
| 474 | 584 | ||
