hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/net/bridge/netfilter/ebtables.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * ebtables
34 *
....@@ -8,11 +9,6 @@
89 *
910 * This code is strongly inspired by the iptables code which is
1011 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11
- *
12
- * This program is free software; you can redistribute it and/or
13
- * modify it under the terms of the GNU General Public License
14
- * as published by the Free Software Foundation; either version
15
- * 2 of the License, or (at your option) any later version.
1612 */
1713 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1814 #include <linux/kmod.h>
....@@ -381,7 +377,7 @@
381377 par->match = match;
382378 par->matchinfo = m->data;
383379 ret = xt_check_match(par, m->match_size,
384
- e->ethproto, e->invflags & EBT_IPROTO);
380
+ ntohs(e->ethproto), e->invflags & EBT_IPROTO);
385381 if (ret < 0) {
386382 module_put(match->me);
387383 return ret;
....@@ -418,7 +414,7 @@
418414 par->target = watcher;
419415 par->targinfo = w->data;
420416 ret = xt_check_target(par, w->watcher_size,
421
- e->ethproto, e->invflags & EBT_IPROTO);
417
+ ntohs(e->ethproto), e->invflags & EBT_IPROTO);
422418 if (ret < 0) {
423419 module_put(watcher->me);
424420 return ret;
....@@ -744,7 +740,7 @@
744740 tgpar.target = target;
745741 tgpar.targinfo = t->data;
746742 ret = xt_check_target(&tgpar, t->target_size,
747
- e->ethproto, e->invflags & EBT_IPROTO);
743
+ ntohs(e->ethproto), e->invflags & EBT_IPROTO);
748744 if (ret < 0) {
749745 module_put(target->me);
750746 goto cleanup_watchers;
....@@ -1003,9 +999,10 @@
1003999 goto free_iterate;
10041000 }
10051001
1006
- /* the table doesn't like it */
1007
- if (t->check && (ret = t->check(newinfo, repl->valid_hooks)))
1002
+ if (repl->valid_hooks != t->valid_hooks) {
1003
+ ret = -EINVAL;
10081004 goto free_unlock;
1005
+ }
10091006
10101007 if (repl->num_counters && repl->num_counters != t->private->nentries) {
10111008 ret = -EINVAL;
....@@ -1050,15 +1047,9 @@
10501047 vfree(table);
10511048 vfree(counterstmp);
10521049
1053
-#ifdef CONFIG_AUDIT
1054
- if (audit_enabled) {
1055
- audit_log(audit_context(), GFP_KERNEL,
1056
- AUDIT_NETFILTER_CFG,
1057
- "table=%s family=%u entries=%u",
1058
- repl->name, AF_BRIDGE, repl->nentries);
1059
- }
1060
-#endif
1061
- return ret;
1050
+ audit_log_nfcfg(repl->name, AF_BRIDGE, repl->nentries,
1051
+ AUDIT_XT_OP_REPLACE, GFP_KERNEL);
1052
+ return 0;
10621053
10631054 free_unlock:
10641055 mutex_unlock(&ebt_mutex);
....@@ -1073,14 +1064,13 @@
10731064 }
10741065
10751066 /* replace the table */
1076
-static int do_replace(struct net *net, const void __user *user,
1077
- unsigned int len)
1067
+static int do_replace(struct net *net, sockptr_t arg, unsigned int len)
10781068 {
10791069 int ret, countersize;
10801070 struct ebt_table_info *newinfo;
10811071 struct ebt_replace tmp;
10821072
1083
- if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1073
+ if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
10841074 return -EFAULT;
10851075
10861076 if (len != sizeof(tmp) + tmp.entries_size)
....@@ -1099,16 +1089,14 @@
10991089 tmp.name[sizeof(tmp.name) - 1] = 0;
11001090
11011091 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
1102
- newinfo = __vmalloc(sizeof(*newinfo) + countersize, GFP_KERNEL_ACCOUNT,
1103
- PAGE_KERNEL);
1092
+ newinfo = __vmalloc(sizeof(*newinfo) + countersize, GFP_KERNEL_ACCOUNT);
11041093 if (!newinfo)
11051094 return -ENOMEM;
11061095
11071096 if (countersize)
11081097 memset(newinfo->counters, 0, countersize);
11091098
1110
- newinfo->entries = __vmalloc(tmp.entries_size, GFP_KERNEL_ACCOUNT,
1111
- PAGE_KERNEL);
1099
+ newinfo->entries = __vmalloc(tmp.entries_size, GFP_KERNEL_ACCOUNT);
11121100 if (!newinfo->entries) {
11131101 ret = -ENOMEM;
11141102 goto free_newinfo;
....@@ -1134,6 +1122,8 @@
11341122 mutex_lock(&ebt_mutex);
11351123 list_del(&table->list);
11361124 mutex_unlock(&ebt_mutex);
1125
+ audit_log_nfcfg(table->name, AF_BRIDGE, table->private->nentries,
1126
+ AUDIT_XT_OP_UNREGISTER, GFP_KERNEL);
11371127 EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size,
11381128 ebt_cleanup_entry, net, NULL);
11391129 if (table->private->nentries)
....@@ -1197,11 +1187,6 @@
11971187 if (ret != 0)
11981188 goto free_chainstack;
11991189
1200
- if (table->check && table->check(newinfo, table->valid_hooks)) {
1201
- ret = -EINVAL;
1202
- goto free_chainstack;
1203
- }
1204
-
12051190 table->private = newinfo;
12061191 rwlock_init(&table->lock);
12071192 mutex_lock(&ebt_mutex);
....@@ -1221,16 +1206,14 @@
12211206 mutex_unlock(&ebt_mutex);
12221207
12231208 WRITE_ONCE(*res, table);
1224
-
1225
- if (!ops)
1226
- return 0;
1227
-
12281209 ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks));
12291210 if (ret) {
12301211 __ebt_unregister_table(net, table);
12311212 *res = NULL;
12321213 }
12331214
1215
+ audit_log_nfcfg(repl->name, AF_BRIDGE, repl->nentries,
1216
+ AUDIT_XT_OP_REGISTER, GFP_KERNEL);
12341217 return ret;
12351218 free_unlock:
12361219 mutex_unlock(&ebt_mutex);
....@@ -1245,19 +1228,41 @@
12451228 return ret;
12461229 }
12471230
1248
-void ebt_unregister_table(struct net *net, struct ebt_table *table,
1249
- const struct nf_hook_ops *ops)
1231
+static struct ebt_table *__ebt_find_table(struct net *net, const char *name)
12501232 {
1251
- if (ops)
1233
+ struct ebt_table *t;
1234
+
1235
+ mutex_lock(&ebt_mutex);
1236
+
1237
+ list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) {
1238
+ if (strcmp(t->name, name) == 0) {
1239
+ mutex_unlock(&ebt_mutex);
1240
+ return t;
1241
+ }
1242
+ }
1243
+
1244
+ mutex_unlock(&ebt_mutex);
1245
+ return NULL;
1246
+}
1247
+
1248
+void ebt_unregister_table_pre_exit(struct net *net, const char *name, const struct nf_hook_ops *ops)
1249
+{
1250
+ struct ebt_table *table = __ebt_find_table(net, name);
1251
+
1252
+ if (table)
12521253 nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks));
1254
+}
1255
+EXPORT_SYMBOL(ebt_unregister_table_pre_exit);
1256
+
1257
+void ebt_unregister_table(struct net *net, struct ebt_table *table)
1258
+{
12531259 __ebt_unregister_table(net, table);
12541260 }
12551261
12561262 /* userspace just supplied us with counters */
12571263 static int do_update_counters(struct net *net, const char *name,
1258
- struct ebt_counter __user *counters,
1259
- unsigned int num_counters,
1260
- const void __user *user, unsigned int len)
1264
+ struct ebt_counter __user *counters,
1265
+ unsigned int num_counters, unsigned int len)
12611266 {
12621267 int i, ret;
12631268 struct ebt_counter *tmp;
....@@ -1300,19 +1305,18 @@
13001305 return ret;
13011306 }
13021307
1303
-static int update_counters(struct net *net, const void __user *user,
1304
- unsigned int len)
1308
+static int update_counters(struct net *net, sockptr_t arg, unsigned int len)
13051309 {
13061310 struct ebt_replace hlp;
13071311
1308
- if (copy_from_user(&hlp, user, sizeof(hlp)))
1312
+ if (copy_from_sockptr(&hlp, arg, sizeof(hlp)))
13091313 return -EFAULT;
13101314
13111315 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
13121316 return -EINVAL;
13131317
13141318 return do_update_counters(net, hlp.name, hlp.counters,
1315
- hlp.num_counters, user, len);
1319
+ hlp.num_counters, len);
13161320 }
13171321
13181322 static inline int ebt_obj_to_user(char __user *um, const char *_name,
....@@ -1464,86 +1468,6 @@
14641468 ebt_entry_to_user, entries, tmp.entries);
14651469 }
14661470
1467
-static int do_ebt_set_ctl(struct sock *sk,
1468
- int cmd, void __user *user, unsigned int len)
1469
-{
1470
- int ret;
1471
- struct net *net = sock_net(sk);
1472
-
1473
- if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1474
- return -EPERM;
1475
-
1476
- switch (cmd) {
1477
- case EBT_SO_SET_ENTRIES:
1478
- ret = do_replace(net, user, len);
1479
- break;
1480
- case EBT_SO_SET_COUNTERS:
1481
- ret = update_counters(net, user, len);
1482
- break;
1483
- default:
1484
- ret = -EINVAL;
1485
- }
1486
- return ret;
1487
-}
1488
-
1489
-static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1490
-{
1491
- int ret;
1492
- struct ebt_replace tmp;
1493
- struct ebt_table *t;
1494
- struct net *net = sock_net(sk);
1495
-
1496
- if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1497
- return -EPERM;
1498
-
1499
- if (copy_from_user(&tmp, user, sizeof(tmp)))
1500
- return -EFAULT;
1501
-
1502
- tmp.name[sizeof(tmp.name) - 1] = '\0';
1503
-
1504
- t = find_table_lock(net, tmp.name, &ret, &ebt_mutex);
1505
- if (!t)
1506
- return ret;
1507
-
1508
- switch (cmd) {
1509
- case EBT_SO_GET_INFO:
1510
- case EBT_SO_GET_INIT_INFO:
1511
- if (*len != sizeof(struct ebt_replace)) {
1512
- ret = -EINVAL;
1513
- mutex_unlock(&ebt_mutex);
1514
- break;
1515
- }
1516
- if (cmd == EBT_SO_GET_INFO) {
1517
- tmp.nentries = t->private->nentries;
1518
- tmp.entries_size = t->private->entries_size;
1519
- tmp.valid_hooks = t->valid_hooks;
1520
- } else {
1521
- tmp.nentries = t->table->nentries;
1522
- tmp.entries_size = t->table->entries_size;
1523
- tmp.valid_hooks = t->table->valid_hooks;
1524
- }
1525
- mutex_unlock(&ebt_mutex);
1526
- if (copy_to_user(user, &tmp, *len) != 0) {
1527
- ret = -EFAULT;
1528
- break;
1529
- }
1530
- ret = 0;
1531
- break;
1532
-
1533
- case EBT_SO_GET_ENTRIES:
1534
- case EBT_SO_GET_INIT_ENTRIES:
1535
- ret = copy_everything_to_user(t, user, len, cmd);
1536
- mutex_unlock(&ebt_mutex);
1537
- break;
1538
-
1539
- default:
1540
- mutex_unlock(&ebt_mutex);
1541
- ret = -EINVAL;
1542
- }
1543
-
1544
- return ret;
1545
-}
1546
-
15471471 #ifdef CONFIG_COMPAT
15481472 /* 32 bit-userspace compatibility definitions. */
15491473 struct compat_ebt_replace {
....@@ -1570,7 +1494,7 @@
15701494 compat_uptr_t ptr;
15711495 } u;
15721496 compat_uint_t match_size;
1573
- compat_uint_t data[0] __attribute__ ((aligned (__alignof__(struct compat_ebt_replace))));
1497
+ compat_uint_t data[] __aligned(__alignof__(struct compat_ebt_replace));
15741498 };
15751499
15761500 /* account for possible padding between match_size and ->data */
....@@ -1948,7 +1872,7 @@
19481872 size_kern = match_size;
19491873 module_put(match->me);
19501874 break;
1951
- case EBT_COMPAT_WATCHER: /* fallthrough */
1875
+ case EBT_COMPAT_WATCHER:
19521876 case EBT_COMPAT_TARGET:
19531877 wt = xt_request_find_target(NFPROTO_BRIDGE, name,
19541878 mwt->u.revision);
....@@ -2077,8 +2001,7 @@
20772001 return ret;
20782002
20792003 offsets[0] = sizeof(struct ebt_entry); /* matches come first */
2080
- memcpy(&offsets[1], &entry->watchers_offset,
2081
- sizeof(offsets) - sizeof(offsets[0]));
2004
+ memcpy(&offsets[1], &entry->offsets, sizeof(entry->offsets));
20822005
20832006 if (state->buf_kern_start) {
20842007 buf_start = state->buf_kern_start + state->buf_kern_offset;
....@@ -2173,7 +2096,7 @@
21732096
21742097
21752098 static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
2176
- void __user *user, unsigned int len)
2099
+ sockptr_t arg, unsigned int len)
21772100 {
21782101 struct compat_ebt_replace tmp;
21792102 int i;
....@@ -2181,7 +2104,7 @@
21812104 if (len < sizeof(tmp))
21822105 return -EINVAL;
21832106
2184
- if (copy_from_user(&tmp, user, sizeof(tmp)))
2107
+ if (copy_from_sockptr(&tmp, arg, sizeof(tmp)))
21852108 return -EFAULT;
21862109
21872110 if (len != sizeof(tmp) + tmp.entries_size)
....@@ -2208,8 +2131,7 @@
22082131 return 0;
22092132 }
22102133
2211
-static int compat_do_replace(struct net *net, void __user *user,
2212
- unsigned int len)
2134
+static int compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
22132135 {
22142136 int ret, i, countersize, size64;
22152137 struct ebt_table_info *newinfo;
....@@ -2217,10 +2139,10 @@
22172139 struct ebt_entries_buf_state state;
22182140 void *entries_tmp;
22192141
2220
- ret = compat_copy_ebt_replace_from_user(&tmp, user, len);
2142
+ ret = compat_copy_ebt_replace_from_user(&tmp, arg, len);
22212143 if (ret) {
22222144 /* try real handler in case userland supplied needed padding */
2223
- if (ret == -EINVAL && do_replace(net, user, len) == 0)
2145
+ if (ret == -EINVAL && do_replace(net, arg, len) == 0)
22242146 ret = 0;
22252147 return ret;
22262148 }
....@@ -2311,42 +2233,20 @@
23112233 goto free_entries;
23122234 }
23132235
2314
-static int compat_update_counters(struct net *net, void __user *user,
2236
+static int compat_update_counters(struct net *net, sockptr_t arg,
23152237 unsigned int len)
23162238 {
23172239 struct compat_ebt_replace hlp;
23182240
2319
- if (copy_from_user(&hlp, user, sizeof(hlp)))
2241
+ if (copy_from_sockptr(&hlp, arg, sizeof(hlp)))
23202242 return -EFAULT;
23212243
23222244 /* try real handler in case userland supplied needed padding */
23232245 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
2324
- return update_counters(net, user, len);
2246
+ return update_counters(net, arg, len);
23252247
23262248 return do_update_counters(net, hlp.name, compat_ptr(hlp.counters),
2327
- hlp.num_counters, user, len);
2328
-}
2329
-
2330
-static int compat_do_ebt_set_ctl(struct sock *sk,
2331
- int cmd, void __user *user, unsigned int len)
2332
-{
2333
- int ret;
2334
- struct net *net = sock_net(sk);
2335
-
2336
- if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2337
- return -EPERM;
2338
-
2339
- switch (cmd) {
2340
- case EBT_SO_SET_ENTRIES:
2341
- ret = compat_do_replace(net, user, len);
2342
- break;
2343
- case EBT_SO_SET_COUNTERS:
2344
- ret = compat_update_counters(net, user, len);
2345
- break;
2346
- default:
2347
- ret = -EINVAL;
2348
- }
2349
- return ret;
2249
+ hlp.num_counters, len);
23502250 }
23512251
23522252 static int compat_do_ebt_get_ctl(struct sock *sk, int cmd,
....@@ -2357,13 +2257,9 @@
23572257 struct ebt_table *t;
23582258 struct net *net = sock_net(sk);
23592259
2360
- if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2361
- return -EPERM;
2362
-
2363
- /* try real handler in case userland supplied needed padding */
2364
- if ((cmd == EBT_SO_GET_INFO ||
2365
- cmd == EBT_SO_GET_INIT_INFO) && *len != sizeof(tmp))
2366
- return do_ebt_get_ctl(sk, cmd, user, len);
2260
+ if ((cmd == EBT_SO_GET_INFO || cmd == EBT_SO_GET_INIT_INFO) &&
2261
+ *len != sizeof(struct compat_ebt_replace))
2262
+ return -EINVAL;
23672263
23682264 if (copy_from_user(&tmp, user, sizeof(tmp)))
23692265 return -EFAULT;
....@@ -2426,20 +2322,112 @@
24262322 }
24272323 #endif
24282324
2325
+static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2326
+{
2327
+ struct net *net = sock_net(sk);
2328
+ struct ebt_replace tmp;
2329
+ struct ebt_table *t;
2330
+ int ret;
2331
+
2332
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2333
+ return -EPERM;
2334
+
2335
+#ifdef CONFIG_COMPAT
2336
+ /* try real handler in case userland supplied needed padding */
2337
+ if (in_compat_syscall() &&
2338
+ ((cmd != EBT_SO_GET_INFO && cmd != EBT_SO_GET_INIT_INFO) ||
2339
+ *len != sizeof(tmp)))
2340
+ return compat_do_ebt_get_ctl(sk, cmd, user, len);
2341
+#endif
2342
+
2343
+ if (copy_from_user(&tmp, user, sizeof(tmp)))
2344
+ return -EFAULT;
2345
+
2346
+ tmp.name[sizeof(tmp.name) - 1] = '\0';
2347
+
2348
+ t = find_table_lock(net, tmp.name, &ret, &ebt_mutex);
2349
+ if (!t)
2350
+ return ret;
2351
+
2352
+ switch (cmd) {
2353
+ case EBT_SO_GET_INFO:
2354
+ case EBT_SO_GET_INIT_INFO:
2355
+ if (*len != sizeof(struct ebt_replace)) {
2356
+ ret = -EINVAL;
2357
+ mutex_unlock(&ebt_mutex);
2358
+ break;
2359
+ }
2360
+ if (cmd == EBT_SO_GET_INFO) {
2361
+ tmp.nentries = t->private->nentries;
2362
+ tmp.entries_size = t->private->entries_size;
2363
+ tmp.valid_hooks = t->valid_hooks;
2364
+ } else {
2365
+ tmp.nentries = t->table->nentries;
2366
+ tmp.entries_size = t->table->entries_size;
2367
+ tmp.valid_hooks = t->table->valid_hooks;
2368
+ }
2369
+ mutex_unlock(&ebt_mutex);
2370
+ if (copy_to_user(user, &tmp, *len) != 0) {
2371
+ ret = -EFAULT;
2372
+ break;
2373
+ }
2374
+ ret = 0;
2375
+ break;
2376
+
2377
+ case EBT_SO_GET_ENTRIES:
2378
+ case EBT_SO_GET_INIT_ENTRIES:
2379
+ ret = copy_everything_to_user(t, user, len, cmd);
2380
+ mutex_unlock(&ebt_mutex);
2381
+ break;
2382
+
2383
+ default:
2384
+ mutex_unlock(&ebt_mutex);
2385
+ ret = -EINVAL;
2386
+ }
2387
+
2388
+ return ret;
2389
+}
2390
+
2391
+static int do_ebt_set_ctl(struct sock *sk, int cmd, sockptr_t arg,
2392
+ unsigned int len)
2393
+{
2394
+ struct net *net = sock_net(sk);
2395
+ int ret;
2396
+
2397
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2398
+ return -EPERM;
2399
+
2400
+ switch (cmd) {
2401
+ case EBT_SO_SET_ENTRIES:
2402
+#ifdef CONFIG_COMPAT
2403
+ if (in_compat_syscall())
2404
+ ret = compat_do_replace(net, arg, len);
2405
+ else
2406
+#endif
2407
+ ret = do_replace(net, arg, len);
2408
+ break;
2409
+ case EBT_SO_SET_COUNTERS:
2410
+#ifdef CONFIG_COMPAT
2411
+ if (in_compat_syscall())
2412
+ ret = compat_update_counters(net, arg, len);
2413
+ else
2414
+#endif
2415
+ ret = update_counters(net, arg, len);
2416
+ break;
2417
+ default:
2418
+ ret = -EINVAL;
2419
+ }
2420
+ return ret;
2421
+}
2422
+
24292423 static struct nf_sockopt_ops ebt_sockopts = {
24302424 .pf = PF_INET,
24312425 .set_optmin = EBT_BASE_CTL,
24322426 .set_optmax = EBT_SO_SET_MAX + 1,
24332427 .set = do_ebt_set_ctl,
2434
-#ifdef CONFIG_COMPAT
2435
- .compat_set = compat_do_ebt_set_ctl,
2436
-#endif
24372428 .get_optmin = EBT_BASE_CTL,
24382429 .get_optmax = EBT_SO_GET_MAX + 1,
24392430 .get = do_ebt_get_ctl,
2440
-#ifdef CONFIG_COMPAT
2441
- .compat_get = compat_do_ebt_get_ctl,
2442
-#endif
24432431 .owner = THIS_MODULE,
24442432 };
24452433