diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 17:27:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 17:27:40 -0400 |
commit | f9da455b93f6ba076935b4ef4589f61e529ae046 (patch) | |
tree | 3c4e69ce1ba1d6bf65915b97a76ca2172105b278 /kernel/seccomp.c | |
parent | 0e04c641b199435f3779454055f6a7de258ecdfc (diff) | |
parent | e5eca6d41f53db48edd8cf88a3f59d2c30227f8e (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller:
1) Seccomp BPF filters can now be JIT'd, from Alexei Starovoitov.
2) Multiqueue support in xen-netback and xen-netfront, from Andrew J
Benniston.
3) Allow tweaking of aggregation settings in cdc_ncm driver, from Bjørn
Mork.
4) BPF now has a "random" opcode, from Chema Gonzalez.
5) Add more BPF documentation and improve test framework, from Daniel
Borkmann.
6) Support TCP fastopen over ipv6, from Daniel Lee.
7) Add software TSO helper functions and use them to support software
TSO in mvneta and mv643xx_eth drivers. From Ezequiel Garcia.
8) Support software TSO in fec driver too, from Nimrod Andy.
9) Add Broadcom SYSTEMPORT driver, from Florian Fainelli.
10) Handle broadcasts more gracefully over macvlan when there are large
numbers of interfaces configured, from Herbert Xu.
11) Allow more control over fwmark used for non-socket based responses,
from Lorenzo Colitti.
12) Do TCP congestion window limiting based upon measurements, from Neal
Cardwell.
13) Support busy polling in SCTP, from Neal Horman.
14) Allow RSS key to be configured via ethtool, from Venkata Duvvuru.
15) Bridge promisc mode handling improvements from Vlad Yasevich.
16) Don't use inetpeer entries to implement ID generation any more, it
performs poorly, from Eric Dumazet.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1522 commits)
rtnetlink: fix userspace API breakage for iproute2 < v3.9.0
tcp: fixing TLP's FIN recovery
net: fec: Add software TSO support
net: fec: Add Scatter/gather support
net: fec: Increase buffer descriptor entry number
net: fec: Factorize feature setting
net: fec: Enable IP header hardware checksum
net: fec: Factorize the .xmit transmit function
bridge: fix compile error when compiling without IPv6 support
bridge: fix smatch warning / potential null pointer dereference
via-rhine: fix full-duplex with autoneg disable
bnx2x: Enlarge the dorq threshold for VFs
bnx2x: Check for UNDI in uncommon branch
bnx2x: Fix 1G-baseT link
bnx2x: Fix link for KR with swapped polarity lane
sctp: Fix sk_ack_backlog wrap-around problem
net/core: Add VF link state control policy
net/fsl: xgmac_mdio is dependent on OF_MDIO
net/fsl: Make xgmac_mdio read error message useful
net_sched: drr: warn when qdisc is not work conserving
...
Diffstat (limited to 'kernel/seccomp.c')
-rw-r--r-- | kernel/seccomp.c | 110 |
1 files changed, 59 insertions, 51 deletions
diff --git a/kernel/seccomp.c b/kernel/seccomp.c index f6d76bebe69f..301bbc24739c 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c | |||
@@ -54,8 +54,7 @@ | |||
54 | struct seccomp_filter { | 54 | struct seccomp_filter { |
55 | atomic_t usage; | 55 | atomic_t usage; |
56 | struct seccomp_filter *prev; | 56 | struct seccomp_filter *prev; |
57 | unsigned short len; /* Instruction count */ | 57 | struct sk_filter *prog; |
58 | struct sock_filter_int insnsi[]; | ||
59 | }; | 58 | }; |
60 | 59 | ||
61 | /* Limit any path through the tree to 256KB worth of instructions. */ | 60 | /* Limit any path through the tree to 256KB worth of instructions. */ |
@@ -104,60 +103,59 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen) | |||
104 | u32 k = ftest->k; | 103 | u32 k = ftest->k; |
105 | 104 | ||
106 | switch (code) { | 105 | switch (code) { |
107 | case BPF_S_LD_W_ABS: | 106 | case BPF_LD | BPF_W | BPF_ABS: |
108 | ftest->code = BPF_LDX | BPF_W | BPF_ABS; | 107 | ftest->code = BPF_LDX | BPF_W | BPF_ABS; |
109 | /* 32-bit aligned and not out of bounds. */ | 108 | /* 32-bit aligned and not out of bounds. */ |
110 | if (k >= sizeof(struct seccomp_data) || k & 3) | 109 | if (k >= sizeof(struct seccomp_data) || k & 3) |
111 | return -EINVAL; | 110 | return -EINVAL; |
112 | continue; | 111 | continue; |
113 | case BPF_S_LD_W_LEN: | 112 | case BPF_LD | BPF_W | BPF_LEN: |
114 | ftest->code = BPF_LD | BPF_IMM; | 113 | ftest->code = BPF_LD | BPF_IMM; |
115 | ftest->k = sizeof(struct seccomp_data); | 114 | ftest->k = sizeof(struct seccomp_data); |
116 | continue; | 115 | continue; |
117 | case BPF_S_LDX_W_LEN: | 116 | case BPF_LDX | BPF_W | BPF_LEN: |
118 | ftest->code = BPF_LDX | BPF_IMM; | 117 | ftest->code = BPF_LDX | BPF_IMM; |
119 | ftest->k = sizeof(struct seccomp_data); | 118 | ftest->k = sizeof(struct seccomp_data); |
120 | continue; | 119 | continue; |
121 | /* Explicitly include allowed calls. */ | 120 | /* Explicitly include allowed calls. */ |
122 | case BPF_S_RET_K: | 121 | case BPF_RET | BPF_K: |
123 | case BPF_S_RET_A: | 122 | case BPF_RET | BPF_A: |
124 | case BPF_S_ALU_ADD_K: | 123 | case BPF_ALU | BPF_ADD | BPF_K: |
125 | case BPF_S_ALU_ADD_X: | 124 | case BPF_ALU | BPF_ADD | BPF_X: |
126 | case BPF_S_ALU_SUB_K: | 125 | case BPF_ALU | BPF_SUB | BPF_K: |
127 | case BPF_S_ALU_SUB_X: | 126 | case BPF_ALU | BPF_SUB | BPF_X: |
128 | case BPF_S_ALU_MUL_K: | 127 | case BPF_ALU | BPF_MUL | BPF_K: |
129 | case BPF_S_ALU_MUL_X: | 128 | case BPF_ALU | BPF_MUL | BPF_X: |
130 | case BPF_S_ALU_DIV_X: | 129 | case BPF_ALU | BPF_DIV | BPF_K: |
131 | case BPF_S_ALU_AND_K: | 130 | case BPF_ALU | BPF_DIV | BPF_X: |
132 | case BPF_S_ALU_AND_X: | 131 | case BPF_ALU | BPF_AND | BPF_K: |
133 | case BPF_S_ALU_OR_K: | 132 | case BPF_ALU | BPF_AND | BPF_X: |
134 | case BPF_S_ALU_OR_X: | 133 | case BPF_ALU | BPF_OR | BPF_K: |
135 | case BPF_S_ALU_XOR_K: | 134 | case BPF_ALU | BPF_OR | BPF_X: |
136 | case BPF_S_ALU_XOR_X: | 135 | case BPF_ALU | BPF_XOR | BPF_K: |
137 | case BPF_S_ALU_LSH_K: | 136 | case BPF_ALU | BPF_XOR | BPF_X: |
138 | case BPF_S_ALU_LSH_X: | 137 | case BPF_ALU | BPF_LSH | BPF_K: |
139 | case BPF_S_ALU_RSH_K: | 138 | case BPF_ALU | BPF_LSH | BPF_X: |
140 | case BPF_S_ALU_RSH_X: | 139 | case BPF_ALU | BPF_RSH | BPF_K: |
141 | case BPF_S_ALU_NEG: | 140 | case BPF_ALU | BPF_RSH | BPF_X: |
142 | case BPF_S_LD_IMM: | 141 | case BPF_ALU | BPF_NEG: |
143 | case BPF_S_LDX_IMM: | 142 | case BPF_LD | BPF_IMM: |
144 | case BPF_S_MISC_TAX: | 143 | case BPF_LDX | BPF_IMM: |
145 | case BPF_S_MISC_TXA: | 144 | case BPF_MISC | BPF_TAX: |
146 | case BPF_S_ALU_DIV_K: | 145 | case BPF_MISC | BPF_TXA: |
147 | case BPF_S_LD_MEM: | 146 | case BPF_LD | BPF_MEM: |
148 | case BPF_S_LDX_MEM: | 147 | case BPF_LDX | BPF_MEM: |
149 | case BPF_S_ST: | 148 | case BPF_ST: |
150 | case BPF_S_STX: | 149 | case BPF_STX: |
151 | case BPF_S_JMP_JA: | 150 | case BPF_JMP | BPF_JA: |
152 | case BPF_S_JMP_JEQ_K: | 151 | case BPF_JMP | BPF_JEQ | BPF_K: |
153 | case BPF_S_JMP_JEQ_X: | 152 | case BPF_JMP | BPF_JEQ | BPF_X: |
154 | case BPF_S_JMP_JGE_K: | 153 | case BPF_JMP | BPF_JGE | BPF_K: |
155 | case BPF_S_JMP_JGE_X: | 154 | case BPF_JMP | BPF_JGE | BPF_X: |
156 | case BPF_S_JMP_JGT_K: | 155 | case BPF_JMP | BPF_JGT | BPF_K: |
157 | case BPF_S_JMP_JGT_X: | 156 | case BPF_JMP | BPF_JGT | BPF_X: |
158 | case BPF_S_JMP_JSET_K: | 157 | case BPF_JMP | BPF_JSET | BPF_K: |
159 | case BPF_S_JMP_JSET_X: | 158 | case BPF_JMP | BPF_JSET | BPF_X: |
160 | sk_decode_filter(ftest, ftest); | ||
161 | continue; | 159 | continue; |
162 | default: | 160 | default: |
163 | return -EINVAL; | 161 | return -EINVAL; |
@@ -189,7 +187,8 @@ static u32 seccomp_run_filters(int syscall) | |||
189 | * value always takes priority (ignoring the DATA). | 187 | * value always takes priority (ignoring the DATA). |
190 | */ | 188 | */ |
191 | for (f = current->seccomp.filter; f; f = f->prev) { | 189 | for (f = current->seccomp.filter; f; f = f->prev) { |
192 | u32 cur_ret = sk_run_filter_int_seccomp(&sd, f->insnsi); | 190 | u32 cur_ret = SK_RUN_FILTER(f->prog, (void *)&sd); |
191 | |||
193 | if ((cur_ret & SECCOMP_RET_ACTION) < (ret & SECCOMP_RET_ACTION)) | 192 | if ((cur_ret & SECCOMP_RET_ACTION) < (ret & SECCOMP_RET_ACTION)) |
194 | ret = cur_ret; | 193 | ret = cur_ret; |
195 | } | 194 | } |
@@ -215,7 +214,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog) | |||
215 | return -EINVAL; | 214 | return -EINVAL; |
216 | 215 | ||
217 | for (filter = current->seccomp.filter; filter; filter = filter->prev) | 216 | for (filter = current->seccomp.filter; filter; filter = filter->prev) |
218 | total_insns += filter->len + 4; /* include a 4 instr penalty */ | 217 | total_insns += filter->prog->len + 4; /* include a 4 instr penalty */ |
219 | if (total_insns > MAX_INSNS_PER_PATH) | 218 | if (total_insns > MAX_INSNS_PER_PATH) |
220 | return -ENOMEM; | 219 | return -ENOMEM; |
221 | 220 | ||
@@ -256,19 +255,25 @@ static long seccomp_attach_filter(struct sock_fprog *fprog) | |||
256 | 255 | ||
257 | /* Allocate a new seccomp_filter */ | 256 | /* Allocate a new seccomp_filter */ |
258 | ret = -ENOMEM; | 257 | ret = -ENOMEM; |
259 | filter = kzalloc(sizeof(struct seccomp_filter) + | 258 | filter = kzalloc(sizeof(struct seccomp_filter), |
260 | sizeof(struct sock_filter_int) * new_len, | ||
261 | GFP_KERNEL|__GFP_NOWARN); | 259 | GFP_KERNEL|__GFP_NOWARN); |
262 | if (!filter) | 260 | if (!filter) |
263 | goto free_prog; | 261 | goto free_prog; |
264 | 262 | ||
265 | ret = sk_convert_filter(fp, fprog->len, filter->insnsi, &new_len); | 263 | filter->prog = kzalloc(sk_filter_size(new_len), |
266 | if (ret) | 264 | GFP_KERNEL|__GFP_NOWARN); |
265 | if (!filter->prog) | ||
267 | goto free_filter; | 266 | goto free_filter; |
267 | |||
268 | ret = sk_convert_filter(fp, fprog->len, filter->prog->insnsi, &new_len); | ||
269 | if (ret) | ||
270 | goto free_filter_prog; | ||
268 | kfree(fp); | 271 | kfree(fp); |
269 | 272 | ||
270 | atomic_set(&filter->usage, 1); | 273 | atomic_set(&filter->usage, 1); |
271 | filter->len = new_len; | 274 | filter->prog->len = new_len; |
275 | |||
276 | sk_filter_select_runtime(filter->prog); | ||
272 | 277 | ||
273 | /* | 278 | /* |
274 | * If there is an existing filter, make it the prev and don't drop its | 279 | * If there is an existing filter, make it the prev and don't drop its |
@@ -278,6 +283,8 @@ static long seccomp_attach_filter(struct sock_fprog *fprog) | |||
278 | current->seccomp.filter = filter; | 283 | current->seccomp.filter = filter; |
279 | return 0; | 284 | return 0; |
280 | 285 | ||
286 | free_filter_prog: | ||
287 | kfree(filter->prog); | ||
281 | free_filter: | 288 | free_filter: |
282 | kfree(filter); | 289 | kfree(filter); |
283 | free_prog: | 290 | free_prog: |
@@ -330,6 +337,7 @@ void put_seccomp_filter(struct task_struct *tsk) | |||
330 | while (orig && atomic_dec_and_test(&orig->usage)) { | 337 | while (orig && atomic_dec_and_test(&orig->usage)) { |
331 | struct seccomp_filter *freeme = orig; | 338 | struct seccomp_filter *freeme = orig; |
332 | orig = orig->prev; | 339 | orig = orig->prev; |
340 | sk_filter_free(freeme->prog); | ||
333 | kfree(freeme); | 341 | kfree(freeme); |
334 | } | 342 | } |
335 | } | 343 | } |