aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/seccomp.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-12 17:27:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-12 17:27:40 -0400
commitf9da455b93f6ba076935b4ef4589f61e529ae046 (patch)
tree3c4e69ce1ba1d6bf65915b97a76ca2172105b278 /kernel/seccomp.c
parent0e04c641b199435f3779454055f6a7de258ecdfc (diff)
parente5eca6d41f53db48edd8cf88a3f59d2c30227f8e (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.c110
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 @@
54struct seccomp_filter { 54struct 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
286free_filter_prog:
287 kfree(filter->prog);
281free_filter: 288free_filter:
282 kfree(filter); 289 kfree(filter);
283free_prog: 290free_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}